1*6cefaae1SJack Meng /*
2*6cefaae1SJack Meng  * CDDL HEADER START
3*6cefaae1SJack Meng  *
4*6cefaae1SJack Meng  * The contents of this file are subject to the terms of the
5*6cefaae1SJack Meng  * Common Development and Distribution License (the "License").
6*6cefaae1SJack Meng  * You may not use this file except in compliance with the License.
7*6cefaae1SJack Meng  *
8*6cefaae1SJack Meng  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6cefaae1SJack Meng  * or http://www.opensolaris.org/os/licensing.
10*6cefaae1SJack Meng  * See the License for the specific language governing permissions
11*6cefaae1SJack Meng  * and limitations under the License.
12*6cefaae1SJack Meng  *
13*6cefaae1SJack Meng  * When distributing Covered Code, include this CDDL HEADER in each
14*6cefaae1SJack Meng  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6cefaae1SJack Meng  * If applicable, add the following below this CDDL HEADER, with the
16*6cefaae1SJack Meng  * fields enclosed by brackets "[]" replaced with your own identifying
17*6cefaae1SJack Meng  * information: Portions Copyright [yyyy] [name of copyright owner]
18*6cefaae1SJack Meng  *
19*6cefaae1SJack Meng  * CDDL HEADER END
20*6cefaae1SJack Meng  */
21*6cefaae1SJack Meng 
22*6cefaae1SJack Meng /*
23*6cefaae1SJack Meng  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*6cefaae1SJack Meng  * Use is subject to license terms.
25*6cefaae1SJack Meng  */
26*6cefaae1SJack Meng 
27*6cefaae1SJack Meng #include <sys/t_kuser.h>
28*6cefaae1SJack Meng #include <sys/netconfig.h>
29*6cefaae1SJack Meng #include <netinet/in.h>
30*6cefaae1SJack Meng #include <net/route.h>
31*6cefaae1SJack Meng #include <net/if.h>
32*6cefaae1SJack Meng #include <sys/kstr.h>
33*6cefaae1SJack Meng #include <rpc/clnt.h>
34*6cefaae1SJack Meng #include <sys/stropts.h>
35*6cefaae1SJack Meng #include <sys/socket.h>
36*6cefaae1SJack Meng #include <sys/sockio.h>
37*6cefaae1SJack Meng #include <sys/bootprops.h>
38*6cefaae1SJack Meng 
39*6cefaae1SJack Meng static int
kivoid_to_sock(int af,void * source,void * dest)40*6cefaae1SJack Meng kivoid_to_sock(int af, void *source, void *dest)
41*6cefaae1SJack Meng {
42*6cefaae1SJack Meng 	struct sockaddr_in  *sin    =	NULL;
43*6cefaae1SJack Meng 	struct sockaddr_in6 *sin6   =	NULL;
44*6cefaae1SJack Meng 
45*6cefaae1SJack Meng 	if (source == NULL || dest == NULL) {
46*6cefaae1SJack Meng 		return (-1);
47*6cefaae1SJack Meng 	}
48*6cefaae1SJack Meng 	if (af == AF_INET) {
49*6cefaae1SJack Meng 		sin = (struct sockaddr_in *)dest;
50*6cefaae1SJack Meng 		(void) bcopy(source, &sin->sin_addr,
51*6cefaae1SJack Meng 		    sizeof (struct in_addr));
52*6cefaae1SJack Meng 		sin->sin_family = af;
53*6cefaae1SJack Meng 	} else if (af == AF_INET6) {
54*6cefaae1SJack Meng 		sin6 = (struct sockaddr_in6 *)dest;
55*6cefaae1SJack Meng 		(void) bcopy(source, &sin6->sin6_addr,
56*6cefaae1SJack Meng 		    sizeof (struct in6_addr));
57*6cefaae1SJack Meng 		sin6->sin6_family = af;
58*6cefaae1SJack Meng 	} else {
59*6cefaae1SJack Meng 		return (-1);
60*6cefaae1SJack Meng 	}
61*6cefaae1SJack Meng 	return (0);
62*6cefaae1SJack Meng }
63*6cefaae1SJack Meng 
64*6cefaae1SJack Meng int
kdlifconfig(TIUSER * tiptr,int af,void * myIPaddr,void * mymask,struct in_addr * mybraddr,struct in_addr * gateway,char * ifname)65*6cefaae1SJack Meng kdlifconfig(TIUSER *tiptr, int af, void *myIPaddr, void *mymask,
66*6cefaae1SJack Meng     struct in_addr *mybraddr, struct in_addr *gateway, char *ifname)
67*6cefaae1SJack Meng {
68*6cefaae1SJack Meng 	int			rc;
69*6cefaae1SJack Meng 	struct netbuf		sbuf;
70*6cefaae1SJack Meng 	struct sockaddr_in	sin;
71*6cefaae1SJack Meng 	struct sockaddr_in6	sin6;
72*6cefaae1SJack Meng 	struct rtentry		route;
73*6cefaae1SJack Meng 	struct sockaddr_in	*rt_sin;
74*6cefaae1SJack Meng 
75*6cefaae1SJack Meng 	if (myIPaddr == NULL || mymask == NULL) {
76*6cefaae1SJack Meng 		return (-1);
77*6cefaae1SJack Meng 	}
78*6cefaae1SJack Meng 
79*6cefaae1SJack Meng 	if (af == AF_INET) {
80*6cefaae1SJack Meng 		rc = kivoid_to_sock(af, mymask, &sin);
81*6cefaae1SJack Meng 		if (rc != 0) {
82*6cefaae1SJack Meng 			return (rc);
83*6cefaae1SJack Meng 		}
84*6cefaae1SJack Meng 		sbuf.buf = (caddr_t)&sin;
85*6cefaae1SJack Meng 		sbuf.maxlen = sbuf.len = sizeof (sin);
86*6cefaae1SJack Meng 	} else {
87*6cefaae1SJack Meng 		rc = kivoid_to_sock(af, mymask, &sin6);
88*6cefaae1SJack Meng 		if (rc != 0) {
89*6cefaae1SJack Meng 			return (rc);
90*6cefaae1SJack Meng 		}
91*6cefaae1SJack Meng 		sbuf.buf = (caddr_t)&sin6;
92*6cefaae1SJack Meng 		sbuf.maxlen = sbuf.len = sizeof (sin6);
93*6cefaae1SJack Meng 	}
94*6cefaae1SJack Meng 	if (rc = kifioctl(tiptr, SIOCSLIFNETMASK, &sbuf, ifname)) {
95*6cefaae1SJack Meng 		return (rc);
96*6cefaae1SJack Meng 	}
97*6cefaae1SJack Meng 
98*6cefaae1SJack Meng 	if (af == AF_INET) {
99*6cefaae1SJack Meng 		rc = kivoid_to_sock(af, myIPaddr, &sin);
100*6cefaae1SJack Meng 		if (rc != 0) {
101*6cefaae1SJack Meng 			return (rc);
102*6cefaae1SJack Meng 		}
103*6cefaae1SJack Meng 		sbuf.buf = (caddr_t)&sin;
104*6cefaae1SJack Meng 		sbuf.maxlen = sbuf.len = sizeof (sin);
105*6cefaae1SJack Meng 	} else {
106*6cefaae1SJack Meng 		rc = kivoid_to_sock(af, myIPaddr, &sin6);
107*6cefaae1SJack Meng 		if (rc != 0) {
108*6cefaae1SJack Meng 			return (rc);
109*6cefaae1SJack Meng 		}
110*6cefaae1SJack Meng 		sbuf.buf = (caddr_t)&sin6;
111*6cefaae1SJack Meng 		sbuf.maxlen = sbuf.len = sizeof (sin6);
112*6cefaae1SJack Meng 	}
113*6cefaae1SJack Meng 
114*6cefaae1SJack Meng 	if (rc = kifioctl(tiptr, SIOCSLIFADDR, &sbuf, ifname)) {
115*6cefaae1SJack Meng 		return (rc);
116*6cefaae1SJack Meng 	}
117*6cefaae1SJack Meng 	/*
118*6cefaae1SJack Meng 	 * Only IPv4 has brocadcast address.
119*6cefaae1SJack Meng 	 */
120*6cefaae1SJack Meng 	if (af == AF_INET && mybraddr != NULL) {
121*6cefaae1SJack Meng 		if (mybraddr->s_addr != INADDR_BROADCAST) {
122*6cefaae1SJack Meng 			rc = kivoid_to_sock(af, mybraddr, &sin);
123*6cefaae1SJack Meng 			if (rc != 0) {
124*6cefaae1SJack Meng 				return (rc);
125*6cefaae1SJack Meng 			}
126*6cefaae1SJack Meng 			sbuf.buf = (caddr_t)&sin;
127*6cefaae1SJack Meng 			sbuf.maxlen = sbuf.len = sizeof (sin);
128*6cefaae1SJack Meng 			if (rc = kifioctl(tiptr, SIOCSLIFBRDADDR, &sbuf,
129*6cefaae1SJack Meng 			    ifname)) {
130*6cefaae1SJack Meng 				return (rc);
131*6cefaae1SJack Meng 			}
132*6cefaae1SJack Meng 		}
133*6cefaae1SJack Meng 	}
134*6cefaae1SJack Meng 
135*6cefaae1SJack Meng 	/*
136*6cefaae1SJack Meng 	 * Now turn on the interface.
137*6cefaae1SJack Meng 	 */
138*6cefaae1SJack Meng 	if (rc = ksetifflags(tiptr, IFF_UP, ifname)) {
139*6cefaae1SJack Meng 		return (rc);
140*6cefaae1SJack Meng 	}
141*6cefaae1SJack Meng 
142*6cefaae1SJack Meng 	/*
143*6cefaae1SJack Meng 	 * Set the default gateway.
144*6cefaae1SJack Meng 	 */
145*6cefaae1SJack Meng 	if (af == AF_INET && gateway != NULL) {
146*6cefaae1SJack Meng 		(void) memset(&route, 0, sizeof (route));
147*6cefaae1SJack Meng 		rt_sin = (struct sockaddr_in *)&route.rt_dst;
148*6cefaae1SJack Meng 		rt_sin->sin_family = AF_INET;
149*6cefaae1SJack Meng 
150*6cefaae1SJack Meng 		rt_sin = (struct sockaddr_in *)&route.rt_gateway;
151*6cefaae1SJack Meng 		rt_sin->sin_addr.s_addr = gateway->s_addr;
152*6cefaae1SJack Meng 		route.rt_flags = RTF_GATEWAY | RTF_UP;
153*6cefaae1SJack Meng 		sbuf.buf = (caddr_t)&route;
154*6cefaae1SJack Meng 		sbuf.maxlen = sbuf.len = sizeof (route);
155*6cefaae1SJack Meng 		if (rc = kifioctl(tiptr, SIOCADDRT, &sbuf, ifname)) {
156*6cefaae1SJack Meng 			return (rc);
157*6cefaae1SJack Meng 		}
158*6cefaae1SJack Meng 	}
159*6cefaae1SJack Meng 	return (0);
160*6cefaae1SJack Meng }
161*6cefaae1SJack Meng 
162*6cefaae1SJack Meng int
kifioctl(TIUSER * tiptr,int cmd,struct netbuf * nbuf,char * ifname)163*6cefaae1SJack Meng kifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf, char *ifname)
164*6cefaae1SJack Meng {
165*6cefaae1SJack Meng 	struct strioctl	    iocb;
166*6cefaae1SJack Meng 	struct lifreq	    lifr;
167*6cefaae1SJack Meng 	vnode_t		    *vp	    =	NULL;
168*6cefaae1SJack Meng 	char		    *buf    =	NULL;
169*6cefaae1SJack Meng 	int		    rc	    =	0;
170*6cefaae1SJack Meng 
171*6cefaae1SJack Meng 	(void) memset(&lifr, 0, sizeof (lifr));
172*6cefaae1SJack Meng 	/*
173*6cefaae1SJack Meng 	 * Now do the one requested.
174*6cefaae1SJack Meng 	 */
175*6cefaae1SJack Meng 	if (nbuf->len) {
176*6cefaae1SJack Meng 		if (nbuf->len == sizeof (struct rtentry)) {
177*6cefaae1SJack Meng 			if (cmd != SIOCADDRT) {
178*6cefaae1SJack Meng 				return (-1);
179*6cefaae1SJack Meng 			}
180*6cefaae1SJack Meng 			/*
181*6cefaae1SJack Meng 			 * Set up gateway parameters.
182*6cefaae1SJack Meng 			 */
183*6cefaae1SJack Meng 			iocb.ic_len = nbuf->len;
184*6cefaae1SJack Meng 			iocb.ic_dp = nbuf->buf;
185*6cefaae1SJack Meng 		} else {
186*6cefaae1SJack Meng 			if (nbuf->len != sizeof (struct sockaddr_in) &&
187*6cefaae1SJack Meng 			    nbuf->len != sizeof (struct sockaddr_in6)) {
188*6cefaae1SJack Meng 				return (-1);
189*6cefaae1SJack Meng 			}
190*6cefaae1SJack Meng 			buf = (char *)&lifr.lifr_addr;
191*6cefaae1SJack Meng 			bcopy(nbuf->buf, buf, nbuf->len);
192*6cefaae1SJack Meng 			iocb.ic_len = sizeof (lifr);
193*6cefaae1SJack Meng 			iocb.ic_dp = (caddr_t)&lifr;
194*6cefaae1SJack Meng 		}
195*6cefaae1SJack Meng 	} else {
196*6cefaae1SJack Meng 		iocb.ic_len = sizeof (lifr);
197*6cefaae1SJack Meng 		iocb.ic_dp = (caddr_t)&lifr;
198*6cefaae1SJack Meng 	}
199*6cefaae1SJack Meng 	(void) strncpy((caddr_t)&lifr.lifr_name, ifname,
200*6cefaae1SJack Meng 	    sizeof (lifr.lifr_name));
201*6cefaae1SJack Meng 	iocb.ic_cmd = cmd;
202*6cefaae1SJack Meng 	iocb.ic_timout = 0;
203*6cefaae1SJack Meng 
204*6cefaae1SJack Meng 	vp = tiptr->fp->f_vnode;
205*6cefaae1SJack Meng 	rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb);
206*6cefaae1SJack Meng 	if (rc) {
207*6cefaae1SJack Meng 		return (rc);
208*6cefaae1SJack Meng 	}
209*6cefaae1SJack Meng 
210*6cefaae1SJack Meng 	return (0);
211*6cefaae1SJack Meng }
212*6cefaae1SJack Meng 
213*6cefaae1SJack Meng int
ksetifflags(TIUSER * tiptr,uint_t value,char * ifname)214*6cefaae1SJack Meng ksetifflags(TIUSER *tiptr, uint_t value, char *ifname)
215*6cefaae1SJack Meng {
216*6cefaae1SJack Meng 	int rc;
217*6cefaae1SJack Meng 	struct strioctl iocb;
218*6cefaae1SJack Meng 	struct lifreq lifr;
219*6cefaae1SJack Meng 
220*6cefaae1SJack Meng 	if (ifname == NULL) {
221*6cefaae1SJack Meng 		return (-1);
222*6cefaae1SJack Meng 	}
223*6cefaae1SJack Meng 
224*6cefaae1SJack Meng 	(void) memset(&lifr, 0, sizeof (lifr));
225*6cefaae1SJack Meng 
226*6cefaae1SJack Meng 	(void) strncpy((caddr_t)&lifr.lifr_name, ifname,
227*6cefaae1SJack Meng 	    sizeof (lifr.lifr_name));
228*6cefaae1SJack Meng 	iocb.ic_cmd = SIOCGLIFFLAGS;
229*6cefaae1SJack Meng 	iocb.ic_timout = 0;
230*6cefaae1SJack Meng 	iocb.ic_len = sizeof (lifr);
231*6cefaae1SJack Meng 	iocb.ic_dp = (caddr_t)&lifr;
232*6cefaae1SJack Meng 	if (rc = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb))
233*6cefaae1SJack Meng 		return (rc);
234*6cefaae1SJack Meng 
235*6cefaae1SJack Meng 	lifr.lifr_flags |= value;
236*6cefaae1SJack Meng 	iocb.ic_cmd = SIOCSLIFFLAGS;
237*6cefaae1SJack Meng 	return (kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb));
238*6cefaae1SJack Meng }
239