]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_event.c
xnu-344.49.tar.gz
[apple/xnu.git] / bsd / kern / kern_event.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
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>
9bccf70c
A
37#include <sys/sys_domain.h>
38#include <sys/syslog.h>
1c79356b
A
39
40
41int raw_usrreq();
42struct pr_usrreqs event_usrreqs;
43
44struct 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
54static
55struct kern_event_head kern_event_head;
56
57static u_long static_event_id = 0;
58
9bccf70c
A
59/*
60 * Install the protosw's for the NKE manager. Invoked at
61 * extension load time
62 */
63int
64kern_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
1c79356b
A
75int 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
97int 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
109int 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;
1c79356b
A
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
180int 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
221struct 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