1d62bc4baSyz /*
2d62bc4baSyz  * CDDL HEADER START
3d62bc4baSyz  *
4d62bc4baSyz  * The contents of this file are subject to the terms of the
5d62bc4baSyz  * Common Development and Distribution License (the "License").
6d62bc4baSyz  * You may not use this file except in compliance with the License.
7d62bc4baSyz  *
8d62bc4baSyz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d62bc4baSyz  * or http://www.opensolaris.org/os/licensing.
10d62bc4baSyz  * See the License for the specific language governing permissions
11d62bc4baSyz  * and limitations under the License.
12d62bc4baSyz  *
13d62bc4baSyz  * When distributing Covered Code, include this CDDL HEADER in each
14d62bc4baSyz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d62bc4baSyz  * If applicable, add the following below this CDDL HEADER, with the
16d62bc4baSyz  * fields enclosed by brackets "[]" replaced with your own identifying
17d62bc4baSyz  * information: Portions Copyright [yyyy] [name of copyright owner]
18d62bc4baSyz  *
19d62bc4baSyz  * CDDL HEADER END
20d62bc4baSyz  */
21d62bc4baSyz /*
22*5d460eafSCathy Zhou  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23d62bc4baSyz  * Use is subject to license terms.
24d62bc4baSyz  */
25d62bc4baSyz 
26d62bc4baSyz #include <sys/stropts.h>
27da14cebeSEric Cheng #include <sys/strsubr.h>
28da14cebeSEric Cheng #include <sys/callb.h>
29d62bc4baSyz #include <sys/softmac_impl.h>
30d62bc4baSyz 
31d62bc4baSyz int
softmac_send_notify_req(softmac_lower_t * slp,uint32_t notifications)32d62bc4baSyz softmac_send_notify_req(softmac_lower_t *slp, uint32_t notifications)
33d62bc4baSyz {
34d62bc4baSyz 	mblk_t		*reqmp;
35d62bc4baSyz 
36d62bc4baSyz 	/*
37d62bc4baSyz 	 * create notify req message and send it down
38d62bc4baSyz 	 */
39d62bc4baSyz 	reqmp = mexchange(NULL, NULL, DL_NOTIFY_REQ_SIZE, M_PROTO,
40d62bc4baSyz 	    DL_NOTIFY_REQ);
41d62bc4baSyz 	if (reqmp == NULL)
42d62bc4baSyz 		return (ENOMEM);
43d62bc4baSyz 
44d62bc4baSyz 	((dl_notify_req_t *)reqmp->b_rptr)->dl_notifications = notifications;
45d62bc4baSyz 
46d62bc4baSyz 	return (softmac_proto_tx(slp, reqmp, NULL));
47d62bc4baSyz }
48d62bc4baSyz 
49d62bc4baSyz int
softmac_send_bind_req(softmac_lower_t * slp,uint_t sap)50d62bc4baSyz softmac_send_bind_req(softmac_lower_t *slp, uint_t sap)
51d62bc4baSyz {
52d62bc4baSyz 	dl_bind_req_t	*bind;
53d62bc4baSyz 	mblk_t		*reqmp;
54d62bc4baSyz 
55d62bc4baSyz 	/*
56d62bc4baSyz 	 * create bind req message and send it down
57d62bc4baSyz 	 */
58d62bc4baSyz 	reqmp = mexchange(NULL, NULL, DL_BIND_REQ_SIZE, M_PROTO, DL_BIND_REQ);
59d62bc4baSyz 	if (reqmp == NULL)
60d62bc4baSyz 		return (ENOMEM);
61d62bc4baSyz 
62d62bc4baSyz 	bind = (dl_bind_req_t *)reqmp->b_rptr;
63d62bc4baSyz 	bind->dl_sap = sap;
64d62bc4baSyz 	bind->dl_conn_mgmt = 0;
65d62bc4baSyz 	bind->dl_max_conind = 0;
66d62bc4baSyz 	bind->dl_xidtest_flg = 0;
67d62bc4baSyz 	bind->dl_service_mode = DL_CLDLS;
68d62bc4baSyz 
69d62bc4baSyz 	return (softmac_proto_tx(slp, reqmp, NULL));
70d62bc4baSyz }
71d62bc4baSyz 
72*5d460eafSCathy Zhou int
softmac_send_unbind_req(softmac_lower_t * slp)73*5d460eafSCathy Zhou softmac_send_unbind_req(softmac_lower_t *slp)
74*5d460eafSCathy Zhou {
75*5d460eafSCathy Zhou 	mblk_t			*reqmp;
76*5d460eafSCathy Zhou 
77*5d460eafSCathy Zhou 	/*
78*5d460eafSCathy Zhou 	 * create unbind req message and send it down
79*5d460eafSCathy Zhou 	 */
80*5d460eafSCathy Zhou 	reqmp = mexchange(NULL, NULL, DL_UNBIND_REQ_SIZE, M_PROTO,
81*5d460eafSCathy Zhou 	    DL_UNBIND_REQ);
82*5d460eafSCathy Zhou 	if (reqmp == NULL)
83*5d460eafSCathy Zhou 		return (ENOMEM);
84*5d460eafSCathy Zhou 
85*5d460eafSCathy Zhou 	return (softmac_proto_tx(slp, reqmp, NULL));
86*5d460eafSCathy Zhou }
87*5d460eafSCathy Zhou 
88d62bc4baSyz int
softmac_send_promisc_req(softmac_lower_t * slp,t_uscalar_t level,boolean_t on)89d62bc4baSyz softmac_send_promisc_req(softmac_lower_t *slp, t_uscalar_t level, boolean_t on)
90d62bc4baSyz {
91d62bc4baSyz 	mblk_t		*reqmp;
92d62bc4baSyz 	size_t		size;
93d62bc4baSyz 	t_uscalar_t	dl_prim;
94d62bc4baSyz 
95d62bc4baSyz 	/*
96d62bc4baSyz 	 * create promisc message and send it down
97d62bc4baSyz 	 */
98d62bc4baSyz 	if (on) {
99d62bc4baSyz 		dl_prim = DL_PROMISCON_REQ;
100d62bc4baSyz 		size = DL_PROMISCON_REQ_SIZE;
101d62bc4baSyz 	} else {
102d62bc4baSyz 		dl_prim = DL_PROMISCOFF_REQ;
103d62bc4baSyz 		size = DL_PROMISCOFF_REQ_SIZE;
104d62bc4baSyz 	}
105d62bc4baSyz 
106d62bc4baSyz 	reqmp = mexchange(NULL, NULL, size, M_PROTO, dl_prim);
107d62bc4baSyz 	if (reqmp == NULL)
108d62bc4baSyz 		return (ENOMEM);
109d62bc4baSyz 
110d62bc4baSyz 	if (on)
111d62bc4baSyz 		((dl_promiscon_req_t *)reqmp->b_rptr)->dl_level = level;
112d62bc4baSyz 	else
113d62bc4baSyz 		((dl_promiscoff_req_t *)reqmp->b_rptr)->dl_level = level;
114d62bc4baSyz 
115d62bc4baSyz 	return (softmac_proto_tx(slp, reqmp, NULL));
116d62bc4baSyz }
117d62bc4baSyz 
118d62bc4baSyz int
softmac_m_promisc(void * arg,boolean_t on)119d62bc4baSyz softmac_m_promisc(void *arg, boolean_t on)
120d62bc4baSyz {
121d62bc4baSyz 	softmac_t		*softmac = arg;
122d62bc4baSyz 	softmac_lower_t		*slp = softmac->smac_lower;
123d62bc4baSyz 
124*5d460eafSCathy Zhou 	ASSERT(MAC_PERIM_HELD(softmac->smac_mh));
125d62bc4baSyz 	ASSERT(slp != NULL);
126d62bc4baSyz 	return (softmac_send_promisc_req(slp, DL_PROMISC_PHYS, on));
127d62bc4baSyz }
128d62bc4baSyz 
129d62bc4baSyz int
softmac_m_multicst(void * arg,boolean_t add,const uint8_t * mca)130d62bc4baSyz softmac_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
131d62bc4baSyz {
132d62bc4baSyz 	softmac_t		*softmac = arg;
133d62bc4baSyz 	softmac_lower_t		*slp;
134d62bc4baSyz 	dl_enabmulti_req_t	*enabmulti;
135d62bc4baSyz 	dl_disabmulti_req_t	*disabmulti;
136d62bc4baSyz 	mblk_t			*reqmp;
137d62bc4baSyz 	t_uscalar_t		dl_prim;
138d62bc4baSyz 	uint32_t		size, addr_length;
139d62bc4baSyz 
140*5d460eafSCathy Zhou 	ASSERT(MAC_PERIM_HELD(softmac->smac_mh));
141d62bc4baSyz 	/*
142d62bc4baSyz 	 * create multicst message and send it down
143d62bc4baSyz 	 */
144d62bc4baSyz 	addr_length = softmac->smac_addrlen;
145d62bc4baSyz 	if (add) {
146d62bc4baSyz 		size = sizeof (dl_enabmulti_req_t) + addr_length;
147d62bc4baSyz 		dl_prim = DL_ENABMULTI_REQ;
148d62bc4baSyz 	} else {
149d62bc4baSyz 		size = sizeof (dl_disabmulti_req_t) + addr_length;
150d62bc4baSyz 		dl_prim = DL_DISABMULTI_REQ;
151d62bc4baSyz 	}
152d62bc4baSyz 
153d62bc4baSyz 	reqmp = mexchange(NULL, NULL, size, M_PROTO, dl_prim);
154d62bc4baSyz 	if (reqmp == NULL)
155d62bc4baSyz 		return (ENOMEM);
156d62bc4baSyz 
157d62bc4baSyz 	if (add) {
158d62bc4baSyz 		enabmulti = (dl_enabmulti_req_t *)reqmp->b_rptr;
159d62bc4baSyz 		enabmulti->dl_addr_offset = sizeof (dl_enabmulti_req_t);
160d62bc4baSyz 		enabmulti->dl_addr_length = addr_length;
161d62bc4baSyz 		(void) memcpy(&enabmulti[1], mca, addr_length);
162d62bc4baSyz 	} else {
163d62bc4baSyz 		disabmulti = (dl_disabmulti_req_t *)reqmp->b_rptr;
164d62bc4baSyz 		disabmulti->dl_addr_offset = sizeof (dl_disabmulti_req_t);
165d62bc4baSyz 		disabmulti->dl_addr_length = addr_length;
166d62bc4baSyz 		(void) memcpy(&disabmulti[1], mca, addr_length);
167d62bc4baSyz 	}
168d62bc4baSyz 
169d62bc4baSyz 	slp = softmac->smac_lower;
170d62bc4baSyz 	ASSERT(slp != NULL);
171d62bc4baSyz 	return (softmac_proto_tx(slp, reqmp, NULL));
172d62bc4baSyz }
173d62bc4baSyz 
174d62bc4baSyz int
softmac_m_unicst(void * arg,const uint8_t * macaddr)175d62bc4baSyz softmac_m_unicst(void *arg, const uint8_t *macaddr)
176d62bc4baSyz {
177d62bc4baSyz 	softmac_t		*softmac = arg;
178d62bc4baSyz 	softmac_lower_t		*slp;
179d62bc4baSyz 	dl_set_phys_addr_req_t	*phyaddr;
180d62bc4baSyz 	mblk_t			*reqmp;
181d62bc4baSyz 	size_t			size;
182d62bc4baSyz 
183*5d460eafSCathy Zhou 	ASSERT(MAC_PERIM_HELD(softmac->smac_mh));
184d62bc4baSyz 	/*
185d62bc4baSyz 	 * create set_phys_addr message and send it down
186d62bc4baSyz 	 */
187d62bc4baSyz 	size = DL_SET_PHYS_ADDR_REQ_SIZE + softmac->smac_addrlen;
188d62bc4baSyz 	reqmp = mexchange(NULL, NULL, size, M_PROTO, DL_SET_PHYS_ADDR_REQ);
189d62bc4baSyz 	if (reqmp == NULL)
190d62bc4baSyz 		return (ENOMEM);
191d62bc4baSyz 
192d62bc4baSyz 	phyaddr = (dl_set_phys_addr_req_t *)reqmp->b_rptr;
193d62bc4baSyz 	phyaddr->dl_addr_offset = sizeof (dl_set_phys_addr_req_t);
194d62bc4baSyz 	phyaddr->dl_addr_length = softmac->smac_addrlen;
195d62bc4baSyz 	(void) memcpy(&phyaddr[1], macaddr, softmac->smac_addrlen);
196d62bc4baSyz 
197d62bc4baSyz 	slp = softmac->smac_lower;
198d62bc4baSyz 	ASSERT(slp != NULL);
199d62bc4baSyz 	return (softmac_proto_tx(slp, reqmp, NULL));
200d62bc4baSyz }
201d62bc4baSyz 
202d62bc4baSyz void
softmac_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)203d62bc4baSyz softmac_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
204d62bc4baSyz {
205d62bc4baSyz 	softmac_lower_t *slp = ((softmac_t *)arg)->smac_lower;
206d62bc4baSyz 	mblk_t *ackmp;
207d62bc4baSyz 
208d62bc4baSyz 	ASSERT(slp != NULL);
209d62bc4baSyz 	softmac_ioctl_tx(slp, mp, &ackmp);
210d62bc4baSyz 	qreply(wq, ackmp);
211d62bc4baSyz }
212d62bc4baSyz 
213d62bc4baSyz static void
softmac_process_notify_ind(softmac_t * softmac,mblk_t * mp)214