]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_event.c
f298f525b42f3098def80ad2e23816dd3e6bc989
[apple/xnu.git] / bsd / kern / kern_event.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 *
25 */
26 /*
27 * @(#)kern_event.c 1.0 (3/31/2000)
28 */
29
30 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <sys/protosw.h>
33 #include <sys/domain.h>
34 #include <sys/mbuf.h>
35 #include <sys/kern_event.h>
36 #include <sys/malloc.h>
37 #include <sys/sys_domain.h>
38 #include <sys/syslog.h>
39
40
41 int raw_usrreq();
42 struct pr_usrreqs event_usrreqs;
43
44 struct protosw eventsw[] = {
45 {
46 SOCK_RAW, &systemdomain, SYSPROTO_EVENT, PR_ATOMIC,
47 0, 0, 0, 0,
48 0,
49 0, 0, 0, 0,
50 0, &event_usrreqs
51 }
52 };
53
54 static
55 struct kern_event_head kern_event_head;
56
57 static u_long static_event_id = 0;
58
59 /*
60 * Install the protosw's for the NKE manager. Invoked at
61 * extension load time
62 */
63 int
64 kern_event_init(void)
65 {
66 int retval;
67
68 if ((retval = net_add_proto(eventsw, &systemdomain)) == 0)
69 return(KERN_SUCCESS);
70
71 log(LOG_WARNING, "Can't install kernel events protocol (%d)\n", retval);
72 return(retval);
73 }
74
75 int kev_attach(struct socket *so, int proto, struct proc *p)
76 {
77 int error;
78 struct kern_event_pcb *ev_pcb;
79
80 ev_pcb = _MALLOC(sizeof(struct kern_event_pcb), M_PCB, M_WAITOK);
81 if (ev_pcb == 0)
82 return ENOBUFS;
83
84 ev_pcb->ev_socket = so;
85 ev_pcb->vendor_code_filter = 0xffffffff;
86
87 so->so_pcb = (caddr_t) ev_pcb;
88 LIST_INSERT_HEAD(&kern_event_head, ev_pcb, ev_link);
89 error = soreserve(so, KEV_SNDSPACE, KEV_RECVSPACE);
90 if (error)
91 return error;
92
93 return 0;
94 }
95
96
97 int kev_detach(struct socket *so)
98 {
99 struct kern_event_pcb *ev_pcb = (struct kern_event_pcb *) so->so_pcb;
100
101 LIST_REMOVE(ev_pcb, ev_link);
102 if (ev_pcb)
103 FREE(ev_pcb, M_PCB);
104
105 return 0;
106 }
107
108
109 int kev_post_msg(struct kev_msg *event_msg)
110 {
111 struct mbuf *m, *m2;
112 struct kern_event_pcb *ev_pcb;
113 struct kern_event_msg *ev;
114 char *tmp;
115 int total_size;
116 int i;
117
118
119 m = m_get(M_DONTWAIT, MT_DATA);
120 if (m == 0)
121 return ENOBUFS;
122
123 ev = mtod(m, struct kern_event_msg *);
124 total_size = KEV_MSG_HEADER_SIZE;
125
126 tmp = (char *) &ev->event_data[0];
127 for (i = 0; i < 5; i++) {
128 if (event_msg->dv[i].data_length == 0)
129 break;
130
131 total_size += event_msg->dv[i].data_length;
132 bcopy(event_msg->dv[i].data_ptr, tmp,
133 event_msg->dv[i].data_length);
134 tmp += event_msg->dv[i].data_length;
135 }
136
137
138 ev->id = ++static_event_id;
139 ev->total_size = total_size;
140 ev->vendor_code = event_msg->vendor_code;
141 ev->kev_class = event_msg->kev_class;
142 ev->kev_subclass = event_msg->kev_subclass;
143 ev->event_code = event_msg->event_code;
144
145 m->m_len = total_size;
146 for (ev_pcb = LIST_FIRST(&kern_event_head);
147 ev_pcb;
148 ev_pcb = LIST_NEXT(ev_pcb, ev_link)) {
149
150 if (ev_pcb->vendor_code_filter != KEV_ANY_VENDOR) {
151 if (ev_pcb->vendor_code_filter != ev->vendor_code)
152 continue;
153
154 if (ev_pcb->class_filter != KEV_ANY_CLASS) {
155 if (ev_pcb->class_filter != ev->kev_class)
156 continue;
157
158 if ((ev_pcb->subclass_filter != KEV_ANY_SUBCLASS) &&
159 (ev_pcb->subclass_filter != ev->kev_subclass))
160 continue;
161 }
162 }
163
164 m2 = m_copym(m, 0, m->m_len, M_NOWAIT);
165 if (m2 == 0) {
166 m_free(m);
167 return ENOBUFS;
168 }
169
170 sbappendrecord(&ev_pcb->ev_socket->so_rcv, m2);
171 sorwakeup(ev_pcb->ev_socket);
172 }
173
174
175 m_free(m);
176 return 0;
177 }
178
179
180 int kev_control(so, cmd, data, ifp, p)
181 struct socket *so;
182 u_long cmd;
183 caddr_t data;
184 register struct ifnet *ifp;
185 struct proc *p;
186 {
187 struct kev_request *kev_req = (struct kev_request *) data;
188 int stat = 0;
189 struct kern_event_pcb *ev_pcb;
190 u_long *id_value = (u_long *) data;
191
192
193 switch (cmd) {
194
195 case SIOCGKEVID:
196 *id_value = static_event_id;
197 break;
198
199 case SIOCSKEVFILT:
200 ev_pcb = (struct kern_event_pcb *) so->so_pcb;
201 ev_pcb->vendor_code_filter = kev_req->vendor_code;
202 ev_pcb->class_filter = kev_req->kev_class;
203 ev_pcb->subclass_filter = kev_req->kev_subclass;
204 break;
205
206 case SIOCGKEVFILT:
207 ev_pcb = (struct kern_event_pcb *) so->so_pcb;
208 kev_req->vendor_code = ev_pcb->vendor_code_filter;
209 kev_req->kev_class = ev_pcb->class_filter;
210 kev_req->kev_subclass = ev_pcb->subclass_filter;
211 break;
212
213 default:
214 return EOPNOTSUPP;
215 }
216
217 return 0;
218 }
219
220
221 struct pr_usrreqs event_usrreqs = {
222 pru_abort_notsupp, pru_accept_notsupp, kev_attach, pru_bind_notsupp, pru_connect_notsupp,
223 pru_connect2_notsupp, kev_control, kev_detach, pru_disconnect_notsupp,
224 pru_listen_notsupp, pru_peeraddr_notsupp, pru_rcvd_notsupp, pru_rcvoob_notsupp,
225 pru_send_notsupp, pru_sense_null, pru_shutdown_notsupp, pru_sockaddr_notsupp,
226 pru_sosend_notsupp, soreceive, sopoll
227 };
228
229
230