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