]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_event.c
a431f36b257b9549e6d3d05d91b973bfa7a0db37
[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
35
36 extern struct domain systemdomain;
37
38
39
40 int raw_usrreq();
41 struct pr_usrreqs event_usrreqs;
42
43 struct protosw eventsw[] = {
44 {
45 SOCK_RAW, &systemdomain, SYSPROTO_EVENT, PR_ATOMIC,
46 0, 0, 0, 0,
47 0,
48 0, 0, 0, 0,
49 0, &event_usrreqs
50 }
51 };
52
53 static
54 struct kern_event_head kern_event_head;
55
56 static u_long static_event_id = 0;
57
58 int kev_attach(struct socket *so, int proto, struct proc *p)
59 {
60 int error;
61 struct kern_event_pcb *ev_pcb;
62
63 ev_pcb = _MALLOC(sizeof(struct kern_event_pcb), M_PCB, M_WAITOK);
64 if (ev_pcb == 0)
65 return ENOBUFS;
66
67 ev_pcb->ev_socket = so;
68 ev_pcb->vendor_code_filter = 0xffffffff;
69
70 so->so_pcb = (caddr_t) ev_pcb;
71 LIST_INSERT_HEAD(&kern_event_head, ev_pcb, ev_link);
72 error = soreserve(so, KEV_SNDSPACE, KEV_RECVSPACE);
73 if (error)
74 return error;
75
76 return 0;
77 }
78
79
80 int kev_detach(struct socket *so)
81 {
82 struct kern_event_pcb *ev_pcb = (struct kern_event_pcb *) so->so_pcb;
83
84 LIST_REMOVE(ev_pcb, ev_link);
85 if (ev_pcb)
86 FREE(ev_pcb, M_PCB);
87
88 return 0;
89 }
90
91
92 int kev_post_msg(struct kev_msg *event_msg)
93 {
94 struct mbuf *m, *m2;
95 struct kern_event_pcb *ev_pcb;
96 struct kern_event_msg *ev;
97 char *tmp;
98 int total_size;
99 int i;
100
101
102 m = m_get(M_DONTWAIT, MT_DATA);
103 if (m == 0)
104 return ENOBUFS;
105
106 ev = mtod(m, struct kern_event_msg *);
107 total_size = KEV_MSG_HEADER_SIZE;
108
109 tmp = (char *) &ev->event_data[0];
110 for (i = 0; i < 5; i++) {
111 if (event_msg->dv[i].data_length == 0)
112 break;
113
114 total_size += event_msg->dv[i].data_length;
115 bcopy(event_msg->dv[i].data_ptr, tmp,
116 event_msg->dv[i].data_length);
117 tmp += event_msg->dv[i].data_length;
118 }
119
120
121 ev->id = ++static_event_id;
122 ev->total_size = total_size;
123 ev->vendor_code = event_msg->vendor_code;
124 ev->kev_class = event_msg->kev_class;
125 ev->kev_subclass = event_msg->kev_subclass;
126 ev->event_code = event_msg->event_code;
127
128 m->m_len = total_size;
129 ev_pcb = LIST_FIRST(&kern_event_head);
130 for (ev_pcb = LIST_FIRST(&kern_event_head);
131 ev_pcb;
132 ev_pcb = LIST_NEXT(ev_pcb, ev_link)) {
133
134 if (ev_pcb->vendor_code_filter != KEV_ANY_VENDOR) {
135 if (ev_pcb->vendor_code_filter != ev->vendor_code)
136 continue;
137
138 if (ev_pcb->class_filter != KEV_ANY_CLASS) {
139 if (ev_pcb->class_filter != ev->kev_class)
140 continue;
141
142 if ((ev_pcb->subclass_filter != KEV_ANY_SUBCLASS) &&
143 (ev_pcb->subclass_filter != ev->kev_subclass))
144 continue;
145 }
146 }
147
148 m2 = m_copym(m, 0, m->m_len, M_NOWAIT);
149 if (m2 == 0) {
150 m_free(m);
151 return ENOBUFS;
152 }
153
154 sbappendrecord(&ev_pcb->ev_socket->so_rcv, m2);
155 sorwakeup(ev_pcb->ev_socket);
156 }
157
158
159 m_free(m);
160 return 0;
161 }
162
163
164 int kev_control(so, cmd, data, ifp, p)
165 struct socket *so;
166 u_long cmd;
167 caddr_t data;
168 register struct ifnet *ifp;
169 struct proc *p;
170 {
171 struct kev_request *kev_req = (struct kev_request *) data;
172 int stat = 0;
173 struct kern_event_pcb *ev_pcb;
174 u_long *id_value = (u_long *) data;
175
176
177 switch (cmd) {
178
179 case SIOCGKEVID:
180 *id_value = static_event_id;
181 break;
182
183 case SIOCSKEVFILT:
184 ev_pcb = (struct kern_event_pcb *) so->so_pcb;
185 ev_pcb->vendor_code_filter = kev_req->vendor_code;
186 ev_pcb->class_filter = kev_req->kev_class;
187 ev_pcb->subclass_filter = kev_req->kev_subclass;
188 break;
189
190 case SIOCGKEVFILT:
191 ev_pcb = (struct kern_event_pcb *) so->so_pcb;
192 kev_req->vendor_code = ev_pcb->vendor_code_filter;
193 kev_req->kev_class = ev_pcb->class_filter;
194 kev_req->kev_subclass = ev_pcb->subclass_filter;
195 break;
196
197 default:
198 return EOPNOTSUPP;
199 }
200
201 return 0;
202 }
203
204
205 struct pr_usrreqs event_usrreqs = {
206 pru_abort_notsupp, pru_accept_notsupp, kev_attach, pru_bind_notsupp, pru_connect_notsupp,
207 pru_connect2_notsupp, kev_control, kev_detach, pru_disconnect_notsupp,
208 pru_listen_notsupp, pru_peeraddr_notsupp, pru_rcvd_notsupp, pru_rcvoob_notsupp,
209 pru_send_notsupp, pru_sense_null, pru_shutdown_notsupp, pru_sockaddr_notsupp,
210 pru_sosend_notsupp, soreceive, sopoll
211 };
212
213
214