This source file includes following definitions.
- pfkey_register
- pfkey_unregister
- pfkey_sendup
- pfkey_output
- pfkey_attach
- pfkey_detach
- pfkey_usrreq
- pfkey_buildprotosw
- pfkey_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 #include <sys/types.h>
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/socket.h>
75 #include <sys/mbuf.h>
76 #include <sys/socketvar.h>
77 #include <net/route.h>
78 #include <netinet/ip_ipsp.h>
79 #include <net/pfkeyv2.h>
80
81 #include <sys/protosw.h>
82 #include <sys/domain.h>
83 #include <net/raw_cb.h>
84
85 #define PFKEY_PROTOCOL_MAX 3
86 static struct pfkey_version *pfkey_versions[PFKEY_PROTOCOL_MAX+1] =
87 { NULL, NULL, NULL, NULL };
88
89 #define PFKEY_MSG_MAXSZ 4096
90
91 struct sockaddr pfkey_addr = { 2, PF_KEY, };
92
93
94 static int pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
95 struct mbuf *nam, struct mbuf *control);
96 static int pfkey_output(struct mbuf *mbuf, struct socket *socket);
97
98 int pfkey_register(struct pfkey_version *version);
99 int pfkey_unregister(struct pfkey_version *version);
100 int pfkey_sendup(struct socket *socket, struct mbuf *packet, int more);
101 void pfkey_init(void);
102 int pfkey_buildprotosw(void);
103
104 int
105 pfkey_register(struct pfkey_version *version)
106 {
107 int rval;
108
109 if ((version->protocol > PFKEY_PROTOCOL_MAX) ||
110 (version->protocol < 0))
111 return (EPROTONOSUPPORT);
112
113 if (pfkey_versions[version->protocol])
114 return (EADDRINUSE);
115
116 pfkey_versions[version->protocol] = version;
117
118 if ((rval = pfkey_buildprotosw()) != 0) {
119 pfkey_versions[version->protocol] = NULL;
120 return (rval);
121 }
122
123 return (0);
124 }
125
126 int
127 pfkey_unregister(struct pfkey_version *version)
128 {
129 int rval;
130
131 if ((rval = pfkey_buildprotosw()) != 0)
132 return (rval);
133
134 pfkey_versions[version->protocol] = NULL;
135 return (0);
136 }
137
138 int
139 pfkey_sendup(struct socket *socket, struct mbuf *packet, int more)
140 {
141 struct mbuf *packet2;
142 int s;
143
144 if (more) {
145 if (!(packet2 = m_copym2(packet, 0, M_COPYALL, M_DONTWAIT)))
146 return (ENOMEM);
147 } else
148 packet2 = packet;
149
150 s = spltdb();
151 if (!sbappendaddr(&socket->so_rcv, &pfkey_addr, packet2, NULL)) {
152 m_freem(packet2);
153 splx(s);
154 return (ENOBUFS);
155 }
156 splx(s);
157
158 sorwakeup(socket);
159 return (0);
160 }
161
162 static int
163 pfkey_output(struct mbuf *mbuf, struct socket *socket)
164 {
165 void *message;
166 int error = 0;
167
168 #ifdef DIAGNOSTIC
169 if (!mbuf || !(mbuf->m_flags & M_PKTHDR)) {
170 error = EINVAL;
171 goto ret;
172 }
173 #endif
174
175 if (mbuf->m_pkthdr.len > PFKEY_MSG_MAXSZ) {
176 error = EMSGSIZE;
177 goto ret;
178 }
179
180 if (!(message = malloc((unsigned long) mbuf->m_pkthdr.len,
181 M_PFKEY, M_DONTWAIT))) {
182 error = ENOMEM;
183 goto ret;
184 }
185
186 m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message);
187
188 error = pfkey_versions[socket->so_proto->pr_protocol]->send(socket,
189 message, mbuf->m_pkthdr.len);
190
191 ret:
192 if (mbuf)
193 m_freem (mbuf);
194 return (error);
195 }
196
197 static int
198 pfkey_attach(struct socket *socket, struct mbuf *proto)
199 {
200 int rval;
201 int s;
202
203 if (!(socket->so_pcb = malloc(sizeof(struct rawcb),
204 M_PCB, M_DONTWAIT)))
205 return (ENOMEM);
206 bzero(socket->so_pcb, sizeof(struct rawcb));
207
208 s = splnet();
209 rval = raw_usrreq(socket, PRU_ATTACH, NULL, proto, NULL);
210 splx(s);
211 if (rval)
212 goto ret;
213
214 ((struct rawcb *)socket->so_pcb)->rcb_faddr = &pfkey_addr;
215 soisconnected(socket);
216
217 socket->so_options |= SO_USELOOPBACK;
218 if ((rval =
219 pfkey_versions[socket->so_proto->pr_protocol]->create(socket)) != 0)
220 goto ret;
221
222 return (0);
223
224 ret:
225 free(socket->so_pcb, M_PCB);
226 return (rval);
227 }
228
229 static int
230 pfkey_detach(struct socket *socket)
231 {
232 int rval, i, s;
233
234 rval = pfkey_versions[socket->so_proto->pr_protocol]->release(socket);
235 s = splnet();
236 i = raw_usrreq(socket, PRU_DETACH, NULL, NULL, NULL);
237 splx(s);
238
239 if (!rval)
240 rval = i;
241
242 return (rval);
243 }
244
245 static int
246 pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
247 struct mbuf *nam, struct mbuf *control)
248 {
249 int rval;
250 int s;
251
252 if ((socket->so_proto->pr_protocol > PFKEY_PROTOCOL_MAX) ||
253 (socket->so_proto->pr_protocol < 0) ||
254 !pfkey_versions[socket->so_proto->pr_protocol])
255 return (EPROTONOSUPPORT);
256
257 switch (req) {
258 case PRU_ATTACH:
259 return (pfkey_attach(socket, nam));
260
261 case PRU_DETACH:
262 return (pfkey_detach(socket));
263
264 default:
265 s = splnet();
266 rval = raw_usrreq(socket, req, mbuf, nam, control);
267 splx(s);
268 }
269
270 return (rval);
271 }
272
273 static struct domain pfkey_domain = {
274 PF_KEY,
275 "PF_KEY",
276 NULL,
277 NULL,
278 NULL,
279 NULL,
280 NULL,
281 NULL,
282 rn_inithead,
283 16,
284 sizeof(struct sockaddr_encap)
285 };
286
287 static struct protosw pfkey_protosw_template = {
288 SOCK_RAW,
289 &pfkey_domain,
290 -1,
291 PR_ATOMIC | PR_ADDR,
292 (void *) raw_input,
293 (void *) pfkey_output,
294 (void *) raw_ctlinput,
295 NULL,
296 pfkey_usrreq,
297 NULL,
298 NULL,
299 NULL,
300 NULL,
301 NULL
302 };
303
304 int
305 pfkey_buildprotosw(void)
306 {
307 struct protosw *protosw, *p;
308 int i, j;
309
310 for (i = j = 0; i <= PFKEY_PROTOCOL_MAX; i++)
311 if (pfkey_versions[i])
312 j++;
313
314 if (j) {
315 if (!(protosw = malloc(j * sizeof(struct protosw),
316 M_PFKEY, M_DONTWAIT)))
317 return (ENOMEM);
318
319 for (i = 0, p = protosw; i <= PFKEY_PROTOCOL_MAX; i++)
320 if (pfkey_versions[i]) {
321 bcopy(&pfkey_protosw_template, p,
322 sizeof(struct protosw));
323 p->pr_protocol = pfkey_versions[i]->protocol;
324 p->pr_sysctl = pfkey_versions[i]->sysctl;
325 p++;
326 }
327
328 if (pfkey_domain.dom_protosw)
329 free(pfkey_domain.dom_protosw, M_PFKEY);
330
331 pfkey_domain.dom_protosw = protosw;
332 pfkey_domain.dom_protoswNPROTOSW = p;
333 } else {
334 if (!(protosw = malloc(sizeof(struct protosw), M_PFKEY,
335 M_DONTWAIT)))
336 return (ENOMEM);
337
338 bcopy(&pfkey_protosw_template, protosw,
339 sizeof(struct protosw));
340
341 if (pfkey_domain.dom_protosw)
342 free(pfkey_domain.dom_protosw, M_PFKEY);
343
344 pfkey_domain.dom_protosw = protosw;
345 pfkey_domain.dom_protoswNPROTOSW = protosw;
346 }
347
348 return (0);
349 }
350
351 void
352 pfkey_init(void)
353 {
354 if (pfkey_buildprotosw() != 0)
355 return;
356
357 pfkey_domain.dom_next = domains;
358 domains = &pfkey_domain;
359 pfkeyv2_init();
360 }