* Remove (void) casts for discarded return values.
[dragonfly.git] / sys / netproto / ipsec / ipsec.c
1 /*      $FreeBSD: src/sys/netipsec/ipsec.c,v 1.2.2.1 2003/01/24 05:11:35 sam Exp $      */
2 /*      $DragonFly: src/sys/netproto/ipsec/ipsec.c,v 1.13 2006/01/14 13:36:40 swildner Exp $    */
3 /*      $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
4
5 /*
6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * IPsec controller part.
36  */
37
38 #include "opt_inet.h"
39 #include "opt_inet6.h"
40 #include "opt_ipsec.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/domain.h>
47 #include <sys/protosw.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/errno.h>
51 #include <sys/time.h>
52 #include <sys/kernel.h>
53 #include <sys/syslog.h>
54 #include <sys/sysctl.h>
55 #include <sys/proc.h>
56 #include <sys/in_cksum.h>
57
58 #include <net/if.h>
59 #include <net/route.h>
60
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/in_var.h>
66 #include <netinet/udp.h>
67 #include <netinet/udp_var.h>
68 #include <netinet/tcp.h>
69 #include <netinet/udp.h>
70
71 #include <netinet/ip6.h>
72 #ifdef INET6
73 #include <netinet6/ip6_var.h>
74 #endif
75 #include <netinet/in_pcb.h>
76 #ifdef INET6
77 #include <netinet/icmp6.h>
78 #endif
79
80 #include <netproto/ipsec/ipsec.h>
81 #ifdef INET6
82 #include <netproto/ipsec/ipsec6.h>
83 #endif
84 #include <netproto/ipsec/ah_var.h>
85 #include <netproto/ipsec/esp_var.h>
86 #include <netproto/ipsec/ipcomp.h>              /*XXX*/
87 #include <netproto/ipsec/ipcomp_var.h>
88
89 #include <netproto/ipsec/key.h>
90 #include <netproto/ipsec/keydb.h>
91 #include <netproto/ipsec/key_debug.h>
92
93 #include <netproto/ipsec/xform.h>
94
95 #include <net/net_osdep.h>
96
97 #ifdef IPSEC_DEBUG
98 int ipsec_debug = 1;
99 #else
100 int ipsec_debug = 0;
101 #endif
102
103 /* NB: name changed so netstat doesn't use it */
104 struct newipsecstat newipsecstat;
105 int ip4_ah_offsetmask = 0;      /* maybe IP_DF? */
106 int ip4_ipsec_dfbit = 0;        /* DF bit on encap. 0: clear 1: set 2: copy */
107 int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
108 int ip4_esp_net_deflev = IPSEC_LEVEL_USE;
109 int ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
110 int ip4_ah_net_deflev = IPSEC_LEVEL_USE;
111 struct secpolicy ip4_def_policy;
112 int ip4_ipsec_ecn = 0;          /* ECN ignore(-1)/forbidden(0)/allowed(1) */
113 int ip4_esp_randpad = -1;
114 /*
115  * Crypto support requirements:
116  *
117  *  1   require hardware support
118  * -1   require software support
119  *  0   take anything
120  */
121 int     crypto_support = 0;
122
123 SYSCTL_DECL(_net_inet_ipsec);
124
125 /* net.inet.ipsec */
126 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY,
127         def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, "");
128 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
129         CTLFLAG_RW, &ip4_esp_trans_deflev,      0, "");
130 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
131         CTLFLAG_RW, &ip4_esp_net_deflev,        0, "");
132 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
133         CTLFLAG_RW, &ip4_ah_trans_deflev,       0, "");
134 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
135         CTLFLAG_RW, &ip4_ah_net_deflev, 0, "");
136 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
137         ah_cleartos, CTLFLAG_RW,        &ah_cleartos,   0, "");
138 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
139         ah_offsetmask, CTLFLAG_RW,      &ip4_ah_offsetmask,     0, "");
140 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
141         dfbit, CTLFLAG_RW,      &ip4_ipsec_dfbit,       0, "");
142 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
143         ecn, CTLFLAG_RW,        &ip4_ipsec_ecn, 0, "");
144 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
145         debug, CTLFLAG_RW,      &ipsec_debug,   0, "");
146 SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
147         esp_randpad, CTLFLAG_RW,        &ip4_esp_randpad,       0, "");
148 SYSCTL_INT(_net_inet_ipsec, OID_AUTO,
149         crypto_support, CTLFLAG_RW,     &crypto_support,0, "");
150 SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO,
151         ipsecstats,     CTLFLAG_RD,     &newipsecstat,  newipsecstat, "");
152
153 #ifdef INET6
154 int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
155 int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
156 int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
157 int ip6_ah_net_deflev = IPSEC_LEVEL_USE;
158 int ip6_ipsec_ecn = 0;          /* ECN ignore(-1)/forbidden(0)/allowed(1) */
159 int ip6_esp_randpad = -1;
160
161 SYSCTL_DECL(_net_inet6_ipsec6);
162
163 /* net.inet6.ipsec6 */
164 #ifdef COMPAT_KAME
165 SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD,
166         0,0, compat_ipsecstats_sysctl, "S", "");
167 #endif /* COMPAT_KAME */
168 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
169         def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, "");
170 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
171         CTLFLAG_RW, &ip6_esp_trans_deflev,      0, "");
172 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
173         CTLFLAG_RW, &ip6_esp_net_deflev,        0, "");
174 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
175         CTLFLAG_RW, &ip6_ah_trans_deflev,       0, "");
176 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
177         CTLFLAG_RW, &ip6_ah_net_deflev, 0, "");
178 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
179         ecn, CTLFLAG_RW,        &ip6_ipsec_ecn, 0, "");
180 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
181         debug, CTLFLAG_RW,      &ipsec_debug,   0, "");
182 SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
183         esp_randpad, CTLFLAG_RW,        &ip6_esp_randpad,       0, "");
184 #endif /* INET6 */
185
186 static int ipsec4_setspidx_inpcb (struct mbuf *, struct inpcb *pcb);
187 #ifdef INET6
188 static int ipsec6_setspidx_in6pcb (struct mbuf *, struct in6pcb *pcb);
189 #endif
190 static int ipsec_setspidx (struct mbuf *, struct secpolicyindex *, int);
191 static void ipsec4_get_ulp (struct mbuf *m, struct secpolicyindex *, int);
192 static int ipsec4_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *);
193 #ifdef INET6
194 static void ipsec6_get_ulp (struct mbuf *m, struct secpolicyindex *, int);
195 static int ipsec6_setspidx_ipaddr (struct mbuf *, struct secpolicyindex *);
196 #endif
197 static void ipsec_delpcbpolicy (struct inpcbpolicy *);
198 static struct secpolicy *ipsec_deepcopy_policy (struct secpolicy *src);
199 static int ipsec_set_policy (struct secpolicy **pcb_sp,
200         int optname, caddr_t request, size_t len, int priv);
201 static int ipsec_get_policy (struct secpolicy *pcb_sp, struct mbuf **mp);
202 static void vshiftl (unsigned char *, int, int);
203 static size_t ipsec_hdrsiz (struct secpolicy *);
204
205 /*
206  * Return a held reference to the default SP.
207  */
208 static struct secpolicy *
209 key_allocsp_default(const char* where, int tag)
210 {
211         struct secpolicy *sp;
212
213         KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
214                 printf("DP key_allocsp_default from %s:%u\n", where, tag));
215
216         sp = &ip4_def_policy;
217         if (sp->policy != IPSEC_POLICY_DISCARD &&
218             sp->policy != IPSEC_POLICY_NONE) {
219                 ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
220                     sp->policy, IPSEC_POLICY_NONE));
221                 sp->policy = IPSEC_POLICY_NONE;
222         }
223         sp->refcnt++;
224
225         KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
226                 printf("DP key_allocsp_default returns SP:%p (%u)\n",
227                         sp, sp->refcnt));
228         return sp;
229 }
230 #define KEY_ALLOCSP_DEFAULT() \
231         key_allocsp_default(__FILE__, __LINE__)
232
233 /*
234  * For OUTBOUND packet having a socket. Searching SPD for packet,
235  * and return a pointer to SP.
236  * OUT: NULL:   no apropreate SP found, the following value is set to error.
237  *              0       : bypass
238  *              EACCES  : discard packet.
239  *              ENOENT  : ipsec_acquire() in progress, maybe.
240  *              others  : error occured.
241  *      others: a pointer to SP
242  *
243  * NOTE: IPv6 mapped adddress concern is implemented here.
244  */
245 struct secpolicy *
246 ipsec_getpolicy(struct tdb_ident *tdbi, u_int dir)
247 {
248         struct secpolicy *sp;
249
250         KASSERT(tdbi != NULL, ("ipsec_getpolicy: null tdbi"));
251         KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
252                 ("ipsec_getpolicy: invalid direction %u", dir));
253
254         sp = KEY_ALLOCSP2(tdbi->spi, &tdbi->dst, tdbi->proto, dir);
255         if (sp == NULL)                 /*XXX????*/
256                 sp = KEY_ALLOCSP_DEFAULT();
257         KASSERT(sp != NULL, ("ipsec_getpolicy: null SP"));
258         return sp;
259 }
260
261 /*
262  * For OUTBOUND packet having a socket. Searching SPD for packet,
263  * and return a pointer to SP.
264  * OUT: NULL:   no apropreate SP found, the following value is set to error.
265  *              0       : bypass
266  *              EACCES  : discard packet.
267  *              ENOENT  : ipsec_acquire() in progress, maybe.
268  *              others  : error occured.
269  *      others: a pointer to SP
270  *
271  * NOTE: IPv6 mapped adddress concern is implemented here.
272  */
273 struct secpolicy *
274 ipsec_getpolicybysock(struct mbuf *m, u_int dir, struct inpcb *inp,
275                       int *error)
276 {
277         struct inpcbpolicy *pcbsp = NULL;
278         struct secpolicy *currsp = NULL;        /* policy on socket */
279         struct secpolicy *sp;
280         int af;
281
282         KASSERT(m != NULL, ("ipsec_getpolicybysock: null mbuf"));
283         KASSERT(inp != NULL, ("ipsec_getpolicybysock: null inpcb"));
284         KASSERT(error != NULL, ("ipsec_getpolicybysock: null error"));
285         KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
286                 ("ipsec_getpolicybysock: invalid direction %u", dir));
287
288         af = inp->inp_socket->so_proto->pr_domain->dom_family;
289         KASSERT(af == AF_INET || af == AF_INET6,
290                 ("ipsec_getpolicybysock: unexpected protocol family %u", af));
291
292         switch (af) {
293         case AF_INET:
294                 /* set spidx in pcb */
295                 *error = ipsec4_setspidx_inpcb(m, inp);
296                 pcbsp = inp->inp_sp;
297                 break;
298 #ifdef INET6
299         case AF_INET6:
300                 /* set spidx in pcb */
301                 *error = ipsec6_setspidx_in6pcb(m, inp);
302                 pcbsp = inp->in6p_sp;
303                 break;
304 #endif
305         default:
306                 *error = EPFNOSUPPORT;
307                 break;
308         }
309         if (*error)
310                 return NULL;
311
312         KASSERT(pcbsp != NULL, ("ipsec_getpolicybysock: null pcbsp"));
313         switch (dir) {
314         case IPSEC_DIR_INBOUND:
315                 currsp = pcbsp->sp_in;
316                 break;
317         case IPSEC_DIR_OUTBOUND:
318                 currsp = pcbsp->sp_out;
319                 break;
320         }
321         KASSERT(currsp != NULL, ("ipsec_getpolicybysock: null currsp"));
322
323         if (pcbsp->priv) {                      /* when privilieged socket */
324                 switch (currsp->policy) {
325                 case IPSEC_POLICY_BYPASS:
326                 case IPSEC_POLICY_IPSEC:
327                         currsp->refcnt++;
328                         sp = currsp;
329                         break;
330
331                 case IPSEC_POLICY_ENTRUST:
332                         /* look for a policy in SPD */
333                         sp = KEY_ALLOCSP(&currsp->spidx, dir);
334                         if (sp == NULL)         /* no SP found */
335                                 sp = KEY_ALLOCSP_DEFAULT();
336                         break;
337
338                 default:
339                         ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
340                               "Invalid policy for PCB %d\n", currsp->policy));
341                         *error = EINVAL;
342                         return NULL;
343                 }
344         } else {                                /* unpriv, SPD has policy */
345                 sp = KEY_ALLOCSP(&currsp->spidx, dir);
346                 if (sp == NULL) {               /* no SP found */
347                         switch (currsp->policy) {
348                         case IPSEC_POLICY_BYPASS:
349                                 ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
350                                        "Illegal policy for non-priviliged defined %d\n",
351                                         currsp->policy));
352                                 *error = EINVAL;
353                                 return NULL;
354
355                         case IPSEC_POLICY_ENTRUST:
356                                 sp = KEY_ALLOCSP_DEFAULT();
357                                 break;
358
359                         case IPSEC_POLICY_IPSEC:
360                                 currsp->refcnt++;
361                                 sp = currsp;
362                                 break;
363
364                         default:
365                                 ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
366                                    "Invalid policy for PCB %d\n", currsp->policy));
367                                 *error = EINVAL;
368                                 return NULL;
369                         }
370                 }
371         }
372         KASSERT(sp != NULL,
373                 ("ipsec_getpolicybysock: null SP (priv %u policy %u",
374                  pcbsp->priv, currsp->policy));
375         KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
376                 printf("DP ipsec_getpolicybysock (priv %u policy %u) allocates "
377                        "SP:%p (refcnt %u)\n", pcbsp->priv, currsp->policy,
378                        sp, sp->refcnt));
379         return sp;
380 }
381
382 /*
383  * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
384  * and return a pointer to SP.
385  * OUT: positive: a pointer to the entry for security policy leaf matched.
386  *      NULL:   no apropreate SP found, the following value is set to error.
387  *              0       : bypass
388  *              EACCES  : discard packet.
389  *              ENOENT  : ipsec_acquire() in progress, maybe.
390  *              others  : error occured.
391  */
392 struct secpolicy *
393 ipsec_getpolicybyaddr(struct mbuf *m, u_int dir, int flag, int *error)
394 {
395         struct secpolicyindex spidx;
396         struct secpolicy *sp;
397
398         KASSERT(m != NULL, ("ipsec_getpolicybyaddr: null mbuf"));
399         KASSERT(error != NULL, ("ipsec_getpolicybyaddr: null error"));
400         KASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
401                 ("ipsec4_getpolicybaddr: invalid direction %u", dir));
402
403         sp = NULL;
404         if (key_havesp(dir)) {
405                 /* Make an index to look for a policy. */
406                 *error = ipsec_setspidx(m, &spidx,
407                                         (flag & IP_FORWARDING) ? 0 : 1);
408                 if (*error != 0) {
409                         DPRINTF(("ipsec_getpolicybyaddr: setpidx failed,"
410                                 " dir %u flag %u\n", dir, flag));
411                         bzero(&spidx, sizeof (spidx));
412                         return NULL;
413                 }
414                 spidx.dir = dir;
415
416                 sp = KEY_ALLOCSP(&spidx, dir);
417         }
418         if (sp == NULL)                 /* no SP found, use system default */
419                 sp = KEY_ALLOCSP_DEFAULT();
420         KASSERT(sp != NULL, ("ipsec_getpolicybyaddr: null SP"));
421         return sp;
422 }
423
424 struct secpolicy *
425 ipsec4_checkpolicy(struct mbuf *m, u_int dir, u_int flag, int *error,
426                    struct inpcb *inp)
427 {
428         struct secpolicy *sp;
429
430         *error = 0;
431         if (inp == NULL)
432                 sp = ipsec_getpolicybyaddr(m, dir, flag, error);
433         else
434                 sp = ipsec_getpolicybysock(m, dir, inp, error);
435         if (sp == NULL) {
436                 KASSERT(*error != 0,
437                         ("ipsec4_checkpolicy: getpolicy failed w/o error"));
438                 newipsecstat.ips_out_inval++;
439                 return NULL;
440         }
441         KASSERT(*error == 0,
442                 ("ipsec4_checkpolicy: sp w/ error set to %u", *error));
443         switch (sp->policy) {
444         case IPSEC_POLICY_ENTRUST:
445         default:
446                 printf("ipsec4_checkpolicy: invalid policy %u\n", sp->policy);
447                 /* fall thru... */
448         case IPSEC_POLICY_DISCARD:
449                 newipsecstat.ips_out_polvio++;
450                 *error = -EINVAL;       /* packet is discarded by caller */
451                 break;
452         case IPSEC_POLICY_BYPASS:
453         case IPSEC_POLICY_NONE:
454                 KEY_FREESP(&sp);
455                 sp = NULL;              /* NB: force NULL result */
456                 break;
457         case IPSEC_POLICY_IPSEC:
458                 if (sp->req == NULL)    /* acquire an SA */
459                         *error = key_spdacquire(sp);
460                 break;
461         }
462         if (*error != 0) {
463                 KEY_FREESP(&sp);
464                 sp = NULL;
465         }
466         return sp;
467 }
468
469 static int
470 ipsec4_setspidx_inpcb(struct mbuf *m, struct inpcb *pcb)
471 {
472         int error;
473
474         KASSERT(pcb != NULL, ("ipsec4_setspidx_inpcb: null pcb"));
475         KASSERT(pcb->inp_sp != NULL, ("ipsec4_setspidx_inpcb: null inp_sp"));
476         KASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL,
477                 ("ipsec4_setspidx_inpcb: null sp_in || sp_out"));
478
479         error = ipsec_setspidx(m, &pcb->inp_sp->sp_in->spidx, 1);
480         if (error == 0) {
481                 pcb->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND;
482                 pcb->inp_sp->sp_out->spidx = pcb->inp_sp->sp_in->spidx;
483                 pcb->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND;
484         } else {
485                 bzero(&pcb->inp_sp->sp_in->spidx,
486                         sizeof (pcb->inp_sp->sp_in->spidx));
487                 bzero(&pcb->inp_sp->sp_out->spidx,
488                         sizeof (pcb->inp_sp->sp_in->spidx));
489         }
490         return error;
491 }
492
493 #ifdef INET6
494 static int
495 ipsec6_setspidx_in6pcb(struct mbuf *m, struct in6pcb *pcb)
496 {
497         struct secpolicyindex *spidx;
498         int error;
499
500         KASSERT(pcb != NULL, ("ipsec6_setspidx_in6pcb: null pcb"));
501         KASSERT(pcb->in6p_sp != NULL, ("ipsec6_setspidx_in6pcb: null inp_sp"));
502         KASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL,
503                 ("ipsec6_setspidx_in6pcb: null sp_in || sp_out"));
504
505         bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
506         bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
507
508         spidx = &pcb->in6p_sp->sp_in->spidx;
509         error = ipsec_setspidx(m, spidx, 1);
510         if (error)
511                 goto bad;
512         spidx->dir = IPSEC_DIR_INBOUND;
513
514         spidx = &pcb->in6p_sp->sp_out->spidx;
515         error = ipsec_setspidx(m, spidx, 1);
516         if (error)
517                 goto bad;
518         spidx->dir = IPSEC_DIR_OUTBOUND;
519
520         return 0;
521
522 bad:
523         bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
524         bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
525         return error;
526 }
527 #endif
528
529 /*
530  * configure security policy index (src/dst/proto/sport/dport)
531  * by looking at the content of mbuf.
532  * the caller is responsible for error recovery (like clearing up spidx).
533  */
534 static int
535 ipsec_setspidx(struct mbuf *m, struct secpolicyindex *spidx, int needport)
536 {
537         struct ip *ip = NULL;
538         struct ip ipbuf;
539         u_int v;
540         struct mbuf *n;
541         int len;
542         int error;
543
544         KASSERT(m != NULL, ("ipsec_setspidx: null mbuf"));
545
546         /*
547          * validate m->m_pkthdr.len.  we see incorrect length if we
548          * mistakenly call this function with inconsistent mbuf chain
549          * (like 4.4BSD tcp/udp processing).  XXX should we panic here?
550          */
551         len = 0;
552         for (n = m; n; n = n->m_next)
553                 len += n->m_len;
554         if (m->m_pkthdr.len != len) {
555                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
556                         printf("ipsec_setspidx: "
557                                "total of m_len(%d) != pkthdr.len(%d), "
558                                "ignored.\n",
559                                 len, m->m_pkthdr.len));
560                 return EINVAL;
561         }
562
563         if (m->m_pkthdr.len < sizeof(struct ip)) {
564                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
565                         printf("ipsec_setspidx: "
566                             "pkthdr.len(%d) < sizeof(struct ip), ignored.\n",
567                             m->m_pkthdr.len));
568                 return EINVAL;
569         }
570
571         if (m->m_len >= sizeof(*ip))
572                 ip = mtod(m, struct ip *);
573         else {
574                 m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf);
575                 ip = &ipbuf;
576         }
577 #ifdef _IP_VHL
578         v = _IP_VHL_V(ip->ip_vhl);
579 #else
580         v = ip->ip_v;
581 #endif
582         switch (v) {
583         case 4:
584                 error = ipsec4_setspidx_ipaddr(m, spidx);
585                 if (error)
586                         return error;
587                 ipsec4_get_ulp(m, spidx, needport);
588                 return 0;
589 #ifdef INET6
590         case 6:
591                 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
592                         KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
593                                 printf("ipsec_setspidx: "
594                                     "pkthdr.len(%d) < sizeof(struct ip6_hdr), "
595                                     "ignored.\n", m->m_pkthdr.len));
596                         return EINVAL;
597                 }
598                 error = ipsec6_setspidx_ipaddr(m, spidx);
599                 if (error)
600                         return error;
601                 ipsec6_get_ulp(m, spidx, needport);
602                 return 0;
603 #endif
604         default:
605                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
606                         printf("ipsec_setspidx: "
607                             "unknown IP version %u, ignored.\n", v));
608                 return EINVAL;
609         }
610 }
611
612 static void
613 ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport)
614 {
615         u_int8_t nxt;
616         int off;
617
618         /* sanity check */
619         KASSERT(m != NULL, ("ipsec4_get_ulp: null mbuf"));
620         KASSERT(m->m_pkthdr.len >= sizeof(struct ip),
621                 ("ipsec4_get_ulp: packet too short"));
622
623         /* NB: ip_input() flips it into host endian XXX need more checking */
624         if (m->m_len < sizeof (struct ip)) {
625                 struct ip *ip = mtod(m, struct ip *);
626                 if (ip->ip_off & (IP_MF | IP_OFFMASK))
627                         goto done;
628 #ifdef _IP_VHL
629                 off = _IP_VHL_HL(ip->ip_vhl) << 2;
630 #else
631                 off = ip->ip_hl << 2;
632 #endif
633                 nxt = ip->ip_p;
634         } else {
635                 struct ip ih;
636
637                 m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih);
638                 if (ih.ip_off & (IP_MF | IP_OFFMASK))
639                         goto done;
640 #ifdef _IP_VHL
641                 off = _IP_VHL_HL(ih.ip_vhl) << 2;
642 #else
643                 off = ih.ip_hl << 2;
644 #endif
645                 nxt = ih.ip_p;
646         }
647
648         while (off < m->m_pkthdr.len) {
649                 struct ip6_ext ip6e;
650                 struct tcphdr th;
651                 struct udphdr uh;
652
653                 switch (nxt) {
654                 case IPPROTO_TCP:
655                         spidx->ul_proto = nxt;
656                         if (!needport)
657                                 goto done_proto;
658                         if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
659                                 goto done;
660                         m_copydata(m, off, sizeof (th), (caddr_t) &th);
661                         spidx->src.sin.sin_port = th.th_sport;
662                         spidx->dst.sin.sin_port = th.th_dport;
663                         return;
664                 case IPPROTO_UDP:
665                         spidx->ul_proto = nxt;
666                         if (!needport)
667                                 goto done_proto;
668                         if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
669                                 goto done;
670                         m_copydata(m, off, sizeof (uh), (caddr_t) &uh);
671                         spidx->src.sin.sin_port = uh.uh_sport;
672                         spidx->dst.sin.sin_port = uh.uh_dport;
673                         return;
674                 case IPPROTO_AH:
675                         if (m->m_pkthdr.len > off + sizeof(ip6e))
676                                 goto done;
677                         /* XXX sigh, this works but is totally bogus */
678                         m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e);
679                         off += (ip6e.ip6e_len + 2) << 2;
680                         nxt = ip6e.ip6e_nxt;
681                         break;
682                 case IPPROTO_ICMP:
683                 default:
684                         /* XXX intermediate headers??? */
685                         spidx->ul_proto = nxt;
686                         goto done_proto;
687                 }
688         }
689 done:
690         spidx->ul_proto = IPSEC_ULPROTO_ANY;
691 done_proto:
692         spidx->src.sin.sin_port = IPSEC_PORT_ANY;
693         spidx->dst.sin.sin_port = IPSEC_PORT_ANY;
694 }
695
696 /* assumes that m is sane */
697 static int
698 ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx)
699 {
700         static const struct sockaddr_in template = {
701                 sizeof (struct sockaddr_in),
702                 AF_INET,
703                 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }
704         };
705
706         spidx->src.sin = template;
707         spidx->dst.sin = template;
708
709         if (m->m_len < sizeof (struct ip)) {
710                 m_copydata(m, offsetof(struct ip, ip_src),
711                            sizeof (struct  in_addr),
712                            (caddr_t) &spidx->src.sin.sin_addr);
713                 m_copydata(m, offsetof(struct ip, ip_dst),
714                            sizeof (struct  in_addr),
715                            (caddr_t) &spidx->dst.sin.sin_addr);
716         } else {
717                 struct ip *ip = mtod(m, struct ip *);
718                 spidx->src.sin.sin_addr = ip->ip_src;
719                 spidx->dst.sin.sin_addr = ip->ip_dst;
720         }
721
722         spidx->prefs = sizeof(struct in_addr) << 3;
723         spidx->prefd = sizeof(struct in_addr) << 3;
724
725         return 0;
726 }
727
728 #ifdef INET6
729 static void
730 ipsec6_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport)
731 {
732         int off, nxt;
733         struct tcphdr th;
734         struct udphdr uh;
735
736         /* sanity check */
737         if (m == NULL)
738                 panic("ipsec6_get_ulp: NULL pointer was passed.\n");
739
740         KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
741                 printf("ipsec6_get_ulp:\n"); kdebug_mbuf(m));
742
743         /* set default */
744         spidx->ul_proto = IPSEC_ULPROTO_ANY;
745         ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY;
746         ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY;
747
748         nxt = -1;
749         off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
750         if (off < 0 || m->m_pkthdr.len < off)
751                 return;
752
753         switch (nxt) {
754         case IPPROTO_TCP:
755                 spidx->ul_proto = nxt;
756                 if (!needport)
757                         break;
758                 if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
759                         break;
760                 m_copydata(m, off, sizeof(th), (caddr_t)&th);
761                 ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport;
762                 ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport;
763                 break;
764         case IPPROTO_UDP:
765                 spidx->ul_proto = nxt;
766                 if (!needport)
767                         break;
768                 if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
769                         break;
770                 m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
771                 ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport;
772                 ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
773                 break;
774         case IPPROTO_ICMPV6:
775         default:
776                 /* XXX intermediate headers??? */
777                 spidx->ul_proto = nxt;
778                 break;
779         }
780 }
781
782 /* assumes that m is sane */
783 static int
784 ipsec6_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx)
785 {
786         struct ip6_hdr *ip6 = NULL;
787         struct ip6_hdr ip6buf;
788         struct sockaddr_in6 *sin6;
789
790         if (m->m_len >= sizeof(*ip6))
791                 ip6 = mtod(m, struct ip6_hdr *);
792         else {
793                 m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf);
794                 ip6 = &ip6buf;
795         }
796
797         sin6 = (struct sockaddr_in6 *)&spidx->src;
798         bzero(sin6, sizeof(*sin6));
799         sin6->sin6_family = AF_INET6;
800         sin6->sin6_len = sizeof(struct sockaddr_in6);
801         bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src));
802         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
803                 sin6->sin6_addr.s6_addr16[1] = 0;
804                 sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
805         }
806         spidx->prefs = sizeof(struct in6_addr) << 3;
807
808         sin6 = (struct sockaddr_in6 *)&spidx->dst;
809         bzero(sin6, sizeof(*sin6));
810         sin6->sin6_family = AF_INET6;
811         sin6->sin6_len = sizeof(struct sockaddr_in6);
812         bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst));
813         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
814                 sin6->sin6_addr.s6_addr16[1] = 0;
815                 sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
816         }
817         spidx->prefd = sizeof(struct in6_addr) << 3;
818
819         return 0;
820 }
821 #endif
822
823 static void
824 ipsec_delpcbpolicy(struct inpcbpolicy *p)
825 {
826         free(p, M_SECA);
827 }
828
829 /* initialize policy in PCB */
830 int
831 ipsec_init_policy(struct socket *so, struct inpcbpolicy **pcb_sp)
832 {
833         struct inpcbpolicy *new;
834
835         /* sanity check. */
836         if (so == NULL || pcb_sp == NULL)
837                 panic("ipsec_init_policy: NULL pointer was passed.\n");
838
839         new = malloc(sizeof(struct inpcbpolicy),
840                         M_SECA, M_INTWAIT | M_ZERO | M_NULLOK);
841         if (new == NULL) {
842                 ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n"));
843                 return ENOBUFS;
844         }
845
846         if (so->so_cred != 0 && so->so_cred->cr_uid == 0)
847                 new->priv = 1;
848         else
849                 new->priv = 0;
850
851         if ((new->sp_in = KEY_NEWSP()) == NULL) {
852                 ipsec_delpcbpolicy(new);
853                 return ENOBUFS;
854         }
855         new->sp_in->state = IPSEC_SPSTATE_ALIVE;
856         new->sp_in->policy = IPSEC_POLICY_ENTRUST;
857
858         if ((new->sp_out = KEY_NEWSP()) == NULL) {
859                 KEY_FREESP(&new->sp_in);
860                 ipsec_delpcbpolicy(new);
861                 return ENOBUFS;
862         }
863         new->sp_out->state = IPSEC_SPSTATE_ALIVE;
864         new->sp_out->policy = IPSEC_POLICY_ENTRUST;
865
866         *pcb_sp = new;
867
868         return 0;
869 }
870
871 /* copy old ipsec policy into new */
872 int
873 ipsec_copy_policy(struct inpcbpolicy *old, struct inpcbpolicy *new)
874 {
875         struct secpolicy *sp;
876
877         sp = ipsec_deepcopy_policy(old->sp_in);
878         if (sp) {
879                 KEY_FREESP(&new->sp_in);
880                 new->sp_in = sp;
881         } else
882                 return ENOBUFS;
883
884         sp = ipsec_deepcopy_policy(old->sp_out);
885         if (sp) {
886                 KEY_FREESP(&new->sp_out);
887                 new->sp_out = sp;
888         } else
889                 return ENOBUFS;
890
891         new->priv = old->priv;
892
893         return 0;
894 }
895
896 /* deep-copy a policy in PCB */
897 static struct secpolicy *
898 ipsec_deepcopy_policy(struct secpolicy *src)
899 {
900         struct ipsecrequest *newchain = NULL;
901         struct ipsecrequest *p;
902         struct ipsecrequest **q;
903         struct ipsecrequest *r;
904         struct secpolicy *dst;
905
906         if (src == NULL)
907                 return NULL;
908         dst = KEY_NEWSP();
909         if (dst == NULL)
910                 return NULL;
911
912         /*
913          * deep-copy IPsec request chain.  This is required since struct
914          * ipsecrequest is not reference counted.
915          */
916         q = &newchain;
917         for (p = src->req; p; p = p->next) {
918                 *q = malloc(sizeof(struct ipsecrequest),
919                         M_SECA, M_INTWAIT | M_ZERO | M_NULLOK);
920                 if (*q == NULL)
921                         goto fail;
922                 (*q)->next = NULL;
923
924                 (*q)->saidx.proto = p->saidx.proto;
925                 (*q)->saidx.mode = p->saidx.mode;
926                 (*q)->level = p->level;
927                 (*q)->saidx.reqid = p->saidx.reqid;
928
929                 bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
930                 bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
931
932                 (*q)->sav = NULL;
933                 (*q)->sp = dst;
934
935                 q = &((*q)->next);
936         }
937
938         dst->req = newchain;
939         dst->state = src->state;
940         dst->policy = src->policy;
941         /* do not touch the refcnt fields */
942
943         return dst;
944
945 fail:
946         for (p = newchain; p; p = r) {
947                 r = p->next;
948                 free(p, M_SECA);
949                 p = NULL;
950         }
951         return NULL;
952 }
953
954 /* set policy and ipsec request if present. */
955 static int
956 ipsec_set_policy(struct secpolicy **pcb_sp, int optname, caddr_t request,
957                  size_t len, int priv)
958 {
959         struct sadb_x_policy *xpl;
960         struct secpolicy *newsp = NULL;
961         int error;
962
963         /* sanity check. */
964         if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL)
965                 return EINVAL;
966         if (len < sizeof(*xpl))
967                 return EINVAL;
968         xpl = (struct sadb_x_policy *)request;
969
970         KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
971                 printf("ipsec_set_policy: passed policy\n");
972                 kdebug_sadb_x_policy((struct sadb_ext *)xpl));
973
974         /* check policy type */
975         /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */
976         if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD
977          || xpl->sadb_x_policy_type == IPSEC_POLICY_NONE)
978                 return EINVAL;
979
980         /* check privileged socket */
981         if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS)
982                 return EACCES;
983
984         /* allocation new SP entry */
985         if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
986                 return error;
987
988         newsp->state = IPSEC_SPSTATE_ALIVE;
989
990         /* clear old SP and set new SP */
991         KEY_FREESP(pcb_sp);
992         *pcb_sp = newsp;
993         KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
994                 printf("ipsec_set_policy: new policy\n");
995                 kdebug_secpolicy(newsp));
996
997         return 0;
998 }
999
1000 static int
1001 ipsec_get_policy(struct secpolicy *pcb_sp, struct mbuf **mp)
1002 {
1003
1004         /* sanity check. */
1005         if (pcb_sp == NULL || mp == NULL)
1006                 return EINVAL;
1007
1008         *mp = key_sp2msg(pcb_sp);
1009         if (!*mp) {
1010                 ipseclog((LOG_DEBUG, "ipsec_get_policy: No more memory.\n"));
1011                 return ENOBUFS;
1012         }
1013
1014         KKASSERT((*mp)->m_type == MT_DATA);
1015         KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1016                 printf("ipsec_get_policy:\n");
1017                 kdebug_mbuf(*mp));
1018
1019         return 0;
1020 }
1021
1022 int
1023 ipsec4_set_policy(struct inpcb *inp, int optname, caddr_t request,
1024                   size_t len, int priv)
1025 {
1026         struct sadb_x_policy *xpl;
1027         struct secpolicy **pcb_sp;
1028
1029         /* sanity check. */
1030         if (inp == NULL || request == NULL)
1031                 return EINVAL;
1032         if (len < sizeof(*xpl))
1033                 return EINVAL;
1034         xpl = (struct sadb_x_policy *)request;
1035
1036         /* select direction */
1037         switch (xpl->sadb_x_policy_dir) {
1038         case IPSEC_DIR_INBOUND:
1039                 pcb_sp = &inp->inp_sp->sp_in;
1040                 break;
1041         case IPSEC_DIR_OUTBOUND:
1042                 pcb_sp = &inp->inp_sp->sp_out;
1043                 break;
1044         default:
1045                 ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
1046                         xpl->sadb_x_policy_dir));
1047                 return EINVAL;
1048         }
1049
1050         return ipsec_set_policy(pcb_sp, optname, request, len, priv);
1051 }
1052
1053 int
1054 ipsec4_get_policy(struct inpcb *inp, caddr_t request, size_t len,
1055                   struct mbuf **mp)
1056 {
1057         struct sadb_x_policy *xpl;
1058         struct secpolicy *pcb_sp;
1059
1060         /* sanity check. */
1061         if (inp == NULL || request == NULL || mp == NULL)
1062                 return EINVAL;
1063         KASSERT(inp->inp_sp != NULL, ("ipsec4_get_policy: null inp_sp"));
1064         if (len < sizeof(*xpl))
1065                 return EINVAL;
1066         xpl = (struct sadb_x_policy *)request;
1067
1068         /* select direction */
1069         switch (xpl->sadb_x_policy_dir) {
1070         case IPSEC_DIR_INBOUND:
1071                 pcb_sp = inp->inp_sp->sp_in;
1072                 break;
1073         case IPSEC_DIR_OUTBOUND:
1074                 pcb_sp = inp->inp_sp->sp_out;
1075                 break;
1076         default:
1077                 ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
1078                         xpl->sadb_x_policy_dir));
1079                 return EINVAL;
1080         }
1081
1082         return ipsec_get_policy(pcb_sp, mp);
1083 }
1084
1085 /* delete policy in PCB */
1086 int
1087 ipsec4_delete_pcbpolicy(struct inpcb *inp)
1088 {
1089         KASSERT(inp != NULL, ("ipsec4_delete_pcbpolicy: null inp"));
1090
1091         if (inp->inp_sp == NULL)
1092                 return 0;
1093
1094         if (inp->inp_sp->sp_in != NULL)
1095                 KEY_FREESP(&inp->inp_sp->sp_in);
1096
1097         if (inp->inp_sp->sp_out != NULL)
1098                 KEY_FREESP(&inp->inp_sp->sp_out);
1099
1100         ipsec_delpcbpolicy(inp->inp_sp);
1101         inp->inp_sp = NULL;
1102
1103         return 0;
1104 }
1105
1106 #ifdef INET6
1107 int
1108 ipsec6_set_policy(struct in6pcb *in6p, int optname, caddr_t request,
1109                   size_t len, int priv)
1110 {
1111         struct sadb_x_policy *xpl;
1112         struct secpolicy **pcb_sp;
1113
1114         /* sanity check. */
1115         if (in6p == NULL || request == NULL)
1116                 return EINVAL;
1117         if (len < sizeof(*xpl))
1118                 return EINVAL;
1119         xpl = (struct sadb_x_policy *)request;
1120
1121         /* select direction */
1122         switch (xpl->sadb_x_policy_dir) {
1123         case IPSEC_DIR_INBOUND:
1124                 pcb_sp = &in6p->in6p_sp->sp_in;
1125                 break;
1126         case IPSEC_DIR_OUTBOUND:
1127                 pcb_sp = &in6p->in6p_sp->sp_out;
1128                 break;
1129         default:
1130                 ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
1131                         xpl->sadb_x_policy_dir));
1132                 return EINVAL;
1133         }
1134
1135         return ipsec_set_policy(pcb_sp, optname, request, len, priv);
1136 }
1137
1138 int
1139 ipsec6_get_policy(struct in6pcb *in6p, caddr_t request, size_t len,
1140                   struct mbuf **mp)
1141 {
1142         struct sadb_x_policy *xpl;
1143         struct secpolicy *pcb_sp;
1144
1145         /* sanity check. */
1146         if (in6p == NULL || request == NULL || mp == NULL)
1147                 return EINVAL;
1148         KASSERT(in6p->in6p_sp != NULL, ("ipsec6_get_policy: null in6p_sp"));
1149         if (len < sizeof(*xpl))
1150                 return EINVAL;
1151         xpl = (struct sadb_x_policy *)request;
1152
1153         /* select direction */
1154         switch (xpl->sadb_x_policy_dir) {
1155         case IPSEC_DIR_INBOUND:
1156                 pcb_sp = in6p->in6p_sp->sp_in;
1157                 break;
1158         case IPSEC_DIR_OUTBOUND:
1159                 pcb_sp = in6p->in6p_sp->sp_out;
1160                 break;
1161         default:
1162                 ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
1163                         xpl->sadb_x_policy_dir));
1164                 return EINVAL;
1165         }
1166
1167         return ipsec_get_policy(pcb_sp, mp);
1168 }
1169
1170 int
1171 ipsec6_delete_pcbpolicy(struct in6pcb *in6p)
1172 {
1173         KASSERT(in6p != NULL, ("ipsec6_delete_pcbpolicy: null in6p"));
1174
1175         if (in6p->in6p_sp == NULL)
1176                 return 0;
1177
1178         if (in6p->in6p_sp->sp_in != NULL)
1179                 KEY_FREESP(&in6p->in6p_sp->sp_in);
1180
1181         if (in6p->in6p_sp->sp_out != NULL)
1182                 KEY_FREESP(&in6p->in6p_sp->sp_out);
1183
1184         ipsec_delpcbpolicy(in6p->in6p_sp);
1185         in6p->in6p_sp = NULL;
1186
1187         return 0;
1188 }
1189 #endif
1190
1191 /*
1192  * return current level.
1193  * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
1194  */
1195 u_int
1196 ipsec_get_reqlevel(struct ipsecrequest *isr)
1197 {
1198         u_int level = 0;
1199         u_int esp_trans_deflev, esp_net_deflev;
1200         u_int ah_trans_deflev, ah_net_deflev;
1201
1202         KASSERT(isr != NULL && isr->sp != NULL,
1203                 ("ipsec_get_reqlevel: null argument"));
1204         KASSERT(isr->sp->spidx.src.sa.sa_family == isr->sp->spidx.dst.sa.sa_family,
1205                 ("ipsec_get_reqlevel: af family mismatch, src %u, dst %u",
1206                  isr->sp->spidx.src.sa.sa_family,
1207                  isr->sp->spidx.dst.sa.sa_family));
1208
1209 /* XXX note that we have ipseclog() expanded here - code sync issue */
1210 #define IPSEC_CHECK_DEFAULT(lev) \
1211         (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE            \
1212                         && (lev) != IPSEC_LEVEL_UNIQUE)                       \
1213                 ? (ipsec_debug                                                \
1214                         ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
1215                                 (lev), IPSEC_LEVEL_REQUIRE)                   \
1216                         : 0),                                                 \
1217                         (lev) = IPSEC_LEVEL_REQUIRE,                          \
1218                         (lev)                                                 \
1219                 : (lev))
1220
1221         /* set default level */
1222         switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
1223 #ifdef INET
1224         case AF_INET:
1225                 esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
1226                 esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
1227                 ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
1228                 ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
1229                 break;
1230 #endif
1231 #ifdef INET6
1232         case AF_INET6:
1233                 esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
1234                 esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
1235                 ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
1236                 ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
1237                 break;
1238 #endif /* INET6 */
1239         default:
1240                 panic("key_get_reqlevel: unknown af %u",
1241                         isr->sp->spidx.src.sa.sa_family);
1242         }
1243
1244 #undef IPSEC_CHECK_DEFAULT
1245
1246         /* set level */
1247         switch (isr->level) {
1248         case IPSEC_LEVEL_DEFAULT:
1249                 switch (isr->saidx.proto) {
1250                 case IPPROTO_ESP:
1251                         if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
1252                                 level = esp_net_deflev;
1253                         else
1254                                 level = esp_trans_deflev;
1255                         break;
1256                 case IPPROTO_AH:
1257                         if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
1258                                 level = ah_net_deflev;
1259                         else
1260                                 level = ah_trans_deflev;
1261                 case IPPROTO_IPCOMP:
1262                         /*
1263                          * we don't really care, as IPcomp document says that
1264                          * we shouldn't compress small packets
1265                          */
1266                         level = IPSEC_LEVEL_USE;
1267                         break;
1268                 default:
1269                         panic("ipsec_get_reqlevel: "
1270                                 "Illegal protocol defined %u\n",
1271                                 isr->saidx.proto);
1272                 }
1273                 break;
1274
1275         case IPSEC_LEVEL_USE:
1276         case IPSEC_LEVEL_REQUIRE:
1277                 level = isr->level;
1278                 break;
1279         case IPSEC_LEVEL_UNIQUE:
1280                 level = IPSEC_LEVEL_REQUIRE;
1281                 break;
1282
1283         default:
1284                 panic("ipsec_get_reqlevel: Illegal IPsec level %u\n",
1285                         isr->level);
1286         }
1287
1288         return level;
1289 }
1290
1291 /*
1292  * Check security policy requirements against the actual
1293  * packet contents.  Return one if the packet should be
1294  * reject as "invalid"; otherwiser return zero to have the
1295  * packet treated as "valid".
1296  *
1297  * OUT:
1298  *      0: valid
1299  *      1: invalid
1300  */
1301 int
1302 ipsec_in_reject(struct secpolicy *sp, struct mbuf *m)
1303 {
1304         struct ipsecrequest *isr;
1305         int need_auth;
1306
1307         KEYDEBUG(KEYDEBUG_IPSEC_DATA,
1308                 printf("ipsec_in_reject: using SP\n");
1309                 kdebug_secpolicy(sp));
1310
1311         /* check policy */
1312         switch (sp->policy) {
1313         case IPSEC_POLICY_DISCARD:
1314                 return 1;
1315         case IPSEC_POLICY_BYPASS:
1316         case IPSEC_POLICY_NONE:
1317                 return 0;
1318         }
1319
1320         KASSERT(sp->policy == IPSEC_POLICY_IPSEC,
1321                 ("ipsec_in_reject: invalid policy %u", sp->policy));
1322
1323         /* XXX should compare policy against ipsec header history */
1324
1325         need_auth = 0;
1326         for (isr = sp->req; isr != NULL; isr = isr->next) {
1327                 if (ipsec_get_reqlevel(isr) != IPSEC_LEVEL_REQUIRE)
1328                         continue;
1329                 switch (isr->saidx.proto) {
1330                 case IPPROTO_ESP:
1331                         if ((m->m_flags & M_DECRYPTED) == 0) {
1332                                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1333                                     printf("ipsec_in_reject: ESP m_flags:%x\n",
1334                                             m->m_flags));
1335                                 return 1;
1336                         }
1337
1338                         if (!need_auth &&
1339                             isr->sav != NULL &&
1340                             isr->sav->tdb_authalgxform != NULL &&
1341                             (m->m_flags & M_AUTHIPDGM) == 0) {
1342                                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1343                                     printf("ipsec_in_reject: ESP/AH m_flags:%x\n",
1344                                             m->m_flags));
1345                                 return 1;
1346                         }
1347                         break;
1348                 case IPPROTO_AH:
1349                         need_auth = 1;
1350                         if ((m->m_flags & M_AUTHIPHDR) == 0) {
1351                                 KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1352                                     printf("ipsec_in_reject: AH m_flags:%x\n",
1353                                             m->m_flags));
1354                                 return 1;
1355                         }
1356                         break;
1357                 case IPPROTO_IPCOMP:
1358                         /*
1359                          * we don't really care, as IPcomp document
1360                          * says that we shouldn't compress small
1361                          * packets, IPComp policy should always be
1362                          * treated as being in "use" level.
1363                          */
1364                         break;
1365                 }
1366         }
1367         return 0;               /* valid */
1368 }
1369
1370 /*
1371  * Check AH/ESP integrity.
1372  * This function is called from tcp_input(), udp_input(),
1373  * and {ah,esp}4_input for tunnel mode
1374  */
1375 int
1376 ipsec4_in_reject(struct mbuf *m, struct inpcb *inp)
1377 {
1378         struct secpolicy *sp;
1379         int error;
1380         int result;
1381
1382         KASSERT(m != NULL, ("ipsec4_in_reject_so: null mbuf"));
1383
1384         /* get SP for this packet.
1385          * When we are called from ip_forward(), we call
1386          * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
1387          */
1388         if (inp == NULL)
1389                 sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
1390         else
1391                 sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error);
1392
1393         if (sp != NULL) {
1394                 result = ipsec_in_reject(sp, m);
1395                 if (result)
1396                         newipsecstat.ips_in_polvio++;
1397                 KEY_FREESP(&sp);
1398         } else {
1399                 result = 0;     /* XXX should be panic ?
1400                                  * -> No, there may be error. */
1401         }
1402         return result;
1403 }
1404
1405 #ifdef INET6
1406 /*
1407  * Check AH/ESP integrity.
1408  * This function is called from tcp6_input(), udp6_input(),
1409  * and {ah,esp}6_input for tunnel mode
1410  */
1411 int
1412 ipsec6_in_reject(struct mbuf *m, struct inpcb *inp)
1413 {
1414         struct secpolicy *sp = NULL;
1415         int error;
1416         int result;
1417
1418         /* sanity check */
1419         if (m == NULL)
1420                 return 0;       /* XXX should be panic ? */
1421
1422         /* get SP for this packet.
1423          * When we are called from ip_forward(), we call
1424          * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
1425          */
1426         if (inp == NULL)
1427                 sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
1428         else
1429                 sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND, inp, &error);
1430
1431         if (sp != NULL) {
1432                 result = ipsec_in_reject(sp, m);
1433                 if (result)
1434                         newipsecstat.ips_in_polvio++;
1435                 KEY_FREESP(&sp);
1436         } else {
1437                 result = 0;
1438         }
1439         return result;
1440 }
1441 #endif
1442
1443 /*
1444  * compute the byte size to be occupied by IPsec header.
1445  * in case it is tunneled, it includes the size of outer IP header.
1446  * NOTE: SP passed is free in this function.
1447  */
1448 static size_t
1449 ipsec_hdrsiz(struct secpolicy *sp)
1450 {
1451         struct ipsecrequest *isr;
1452         size_t siz;
1453
1454         KEYDEBUG(KEYDEBUG_IPSEC_DATA,
1455                 printf("ipsec_hdrsiz: using SP\n");
1456                 kdebug_secpolicy(sp));
1457
1458         switch (sp->policy) {
1459         case IPSEC_POLICY_DISCARD:
1460         case IPSEC_POLICY_BYPASS:
1461         case IPSEC_POLICY_NONE:
1462                 return 0;
1463         }
1464
1465         KASSERT(sp->policy == IPSEC_POLICY_IPSEC,
1466                 ("ipsec_hdrsiz: invalid policy %u", sp->policy));
1467
1468         siz = 0;
1469         for (isr = sp->req; isr != NULL; isr = isr->next) {
1470                 size_t clen = 0;
1471
1472                 switch (isr->saidx.proto) {
1473                 case IPPROTO_ESP:
1474                         clen = esp_hdrsiz(isr->sav);
1475                         break;
1476                 case IPPROTO_AH:
1477                         clen = ah_hdrsiz(isr->sav);
1478                         break;
1479                 case IPPROTO_IPCOMP:
1480                         clen = sizeof(struct ipcomp);
1481                         break;
1482                 }
1483
1484                 if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
1485                         switch (isr->saidx.dst.sa.sa_family) {
1486                         case AF_INET:
1487                                 clen += sizeof(struct ip);
1488                                 break;
1489 #ifdef INET6
1490                         case AF_INET6:
1491                                 clen += sizeof(struct ip6_hdr);
1492                                 break;
1493 #endif
1494                         default:
1495                                 ipseclog((LOG_ERR, "ipsec_hdrsiz: "
1496                                     "unknown AF %d in IPsec tunnel SA\n",
1497                                     ((struct sockaddr *)&isr->saidx.dst)->sa_family));
1498                                 break;
1499                         }
1500                 }
1501                 siz += clen;
1502         }
1503
1504         return siz;
1505 }
1506
1507 /* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
1508 size_t
1509 ipsec4_hdrsiz(struct mbuf *m, u_int dir, struct inpcb *inp)
1510 {
1511         struct secpolicy *sp;
1512         int error;
1513         size_t size;
1514
1515         KASSERT(m != NULL, ("ipsec4_hdrsiz: null mbuf"));
1516         KASSERT(inp == NULL || inp->inp_socket != NULL,
1517                 ("ipsec4_hdrsize: socket w/o inpcb"));
1518
1519         /* get SP for this packet.
1520          * When we are called from ip_forward(), we call
1521          * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
1522          */
1523         if (inp == NULL)
1524                 sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
1525         else
1526                 sp = ipsec_getpolicybysock(m, dir, inp, &error);
1527
1528         if (sp != NULL) {
1529                 size = ipsec_hdrsiz(sp);
1530                 KEYDEBUG(KEYDEBUG_IPSEC_DATA,
1531                         printf("ipsec4_hdrsiz: size:%lu.\n",
1532                                 (unsigned long)size));
1533
1534                 KEY_FREESP(&sp);
1535         } else {
1536                 size = 0;       /* XXX should be panic ? */
1537         }
1538         return size;
1539 }
1540
1541 #ifdef INET6
1542 /* This function is called from ipsec6_hdrsize_tcp(),
1543  * and maybe from ip6_forward.()
1544  */
1545 size_t
1546 ipsec6_hdrsiz(struct mbuf *m, u_int dir, struct in6pcb *in6p)
1547 {
1548         struct secpolicy *sp;
1549         int error;
1550         size_t size;
1551
1552         KASSERT(m != NULL, ("ipsec6_hdrsiz: null mbuf"));
1553         KASSERT(in6p == NULL || in6p->in6p_socket != NULL,
1554                 ("ipsec6_hdrsize: socket w/o inpcb"));
1555
1556         /* get SP for this packet */
1557         /* XXX Is it right to call with IP_FORWARDING. */
1558         if (in6p == NULL)
1559                 sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
1560         else
1561                 sp = ipsec_getpolicybysock(m, dir, in6p, &error);
1562
1563         if (sp == NULL)
1564                 return 0;
1565         size = ipsec_hdrsiz(sp);
1566         KEYDEBUG(KEYDEBUG_IPSEC_DATA,
1567                 printf("ipsec6_hdrsiz: size:%lu.\n", (unsigned long)size));
1568         KEY_FREESP(&sp);
1569
1570         return size;
1571 }
1572 #endif /*INET6*/
1573
1574 /*
1575  * Check the variable replay window.
1576  * ipsec_chkreplay() performs replay check before ICV verification.
1577  * ipsec_updatereplay() updates replay bitmap.  This must be called after
1578  * ICV verification (it also performs replay check, which is usually done
1579  * beforehand).
1580  * 0 (zero) is returned if packet disallowed, 1 if packet permitted.
1581  *
1582  * based on RFC 2401.
1583  */
1584 int
1585 ipsec_chkreplay(u_int32_t seq, struct secasvar *sav)
1586 {
1587         const struct secreplay *replay;
1588         u_int32_t diff;
1589         int fr;
1590         u_int32_t wsizeb;       /* constant: bits of window size */
1591         int frlast;             /* constant: last frame */
1592
1593         KASSERT(sav != NULL, ("ipsec_chkreplay: Null SA"));
1594         KASSERT(sav->replay != NULL, ("ipsec_chkreplay: Null replay state"));
1595
1596         replay = sav->replay;
1597
1598         if (replay->wsize == 0)
1599                 return 1;       /* no need to check replay. */
1600
1601         /* constant */
1602         frlast = replay->wsize - 1;
1603         wsizeb = replay->wsize << 3;
1604
1605         /* sequence number of 0 is invalid */
1606         if (seq == 0)
1607                 return 0;
1608
1609         /* first time is always okay */
1610         if (replay->count == 0)
1611                 return 1;
1612
1613         if (seq > replay->lastseq) {
1614                 /* larger sequences are okay */
1615                 return 1;
1616         } else {
1617                 /* seq is equal or less than lastseq. */
1618                 diff = replay->lastseq - seq;
1619
1620                 /* over range to check, i.e. too old or wrapped */
1621                 if (diff >= wsizeb)
1622                         return 0;
1623
1624                 fr = frlast - diff / 8;
1625
1626                 /* this packet already seen ? */
1627                 if ((replay->bitmap)[fr] & (1 << (diff % 8)))
1628                         return 0;
1629
1630                 /* out of order but good */
1631                 return 1;
1632         }
1633 }
1634
1635 /*
1636  * check replay counter whether to update or not.
1637  * OUT: 0:      OK
1638  *      1:      NG
1639  */
1640 int
1641 ipsec_updatereplay(u_int32_t seq, struct secasvar *sav)
1642 {
1643         struct secreplay *replay;
1644         u_int32_t diff;
1645         int fr;
1646         u_int32_t wsizeb;       /* constant: bits of window size */
1647         int frlast;             /* constant: last frame */
1648
1649         KASSERT(sav != NULL, ("ipsec_updatereplay: Null SA"));
1650         KASSERT(sav->replay != NULL, ("ipsec_updatereplay: Null replay state"));
1651
1652         replay = sav->replay;
1653
1654         if (replay->wsize == 0)
1655                 goto ok;        /* no need to check replay. */
1656
1657         /* constant */
1658         frlast = replay->wsize - 1;
1659         wsizeb = replay->wsize << 3;
1660
1661         /* sequence number of 0 is invalid */
1662         if (seq == 0)
1663                 return 1;
1664
1665         /* first time */
1666         if (replay->count == 0) {
1667                 replay->lastseq = seq;
1668                 bzero(replay->bitmap, replay->wsize);
1669                 (replay->bitmap)[frlast] = 1;
1670                 goto ok;
1671         }
1672
1673         if (seq > replay->lastseq) {
1674                 /* seq is larger than lastseq. */
1675                 diff = seq - replay->lastseq;
1676
1677                 /* new larger sequence number */
1678                 if (diff < wsizeb) {
1679                         /* In window */
1680                         /* set bit for this packet */
1681                         vshiftl(replay->bitmap, diff, replay->wsize);
1682                         (replay->bitmap)[frlast] |= 1;
1683                 } else {
1684                         /* this packet has a "way larger" */
1685                         bzero(replay->bitmap, replay->wsize);
1686                         (replay->bitmap)[frlast] = 1;
1687                 }
1688                 replay->lastseq = seq;
1689
1690                 /* larger is good */
1691         } else {
1692                 /* seq is equal or less than lastseq. */
1693                 diff = replay->lastseq - seq;
1694
1695                 /* over range to check, i.e. too old or wrapped */
1696                 if (diff >= wsizeb)
1697                         return 1;
1698
1699                 fr = frlast - diff / 8;
1700
1701                 /* this packet already seen ? */
1702                 if ((replay->bitmap)[fr] & (1 << (diff % 8)))
1703                         return 1;
1704
1705                 /* mark as seen */
1706                 (replay->bitmap)[fr] |= (1 << (diff % 8));
1707
1708                 /* out of order but good */
1709         }
1710
1711 ok:
1712         if (replay->count == ~0) {
1713
1714                 /* set overflow flag */
1715                 replay->overflow++;
1716
1717                 /* don't increment, no more packets accepted */
1718                 if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0)
1719                         return 1;
1720
1721                 ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n",
1722                     replay->overflow, ipsec_logsastr(sav)));
1723         }
1724
1725         replay->count++;
1726
1727         return 0;
1728 }
1729
1730 /*
1731  * shift variable length buffer to left.
1732  * IN:  bitmap: pointer to the buffer
1733  *      nbit:   the number of to shift.
1734  *      wsize:  buffer size (bytes).
1735  */
1736 static void
1737 vshiftl(unsigned char *bitmap, int nbit, int wsize)
1738 {
1739         int s, j, i;
1740         unsigned char over;
1741
1742         for (j = 0; j < nbit; j += 8) {
1743                 s = (nbit - j < 8) ? (nbit - j): 8;
1744                 bitmap[0] <<= s;
1745                 for (i = 1; i < wsize; i++) {
1746                         over = (bitmap[i] >> (8 - s));
1747                         bitmap[i] <<= s;
1748                         bitmap[i-1] |= over;
1749                 }
1750         }
1751
1752         return;
1753 }
1754
1755 /* Return a printable string for the address. */
1756 char *
1757 ipsec_address(union sockaddr_union* sa)
1758 {
1759         switch (sa->sa.sa_family) {
1760 #if INET
1761         case AF_INET:
1762                 return inet_ntoa(sa->sin.sin_addr);
1763 #endif /* INET */
1764
1765 #if INET6
1766         case AF_INET6:
1767                 return ip6_sprintf(&sa->sin6.sin6_addr);
1768 #endif /* INET6 */
1769
1770         default:
1771                 return "(unknown address family)";
1772         }
1773 }
1774
1775 const char *
1776 ipsec_logsastr(struct secasvar *sav)
1777 {
1778         static char buf[256];
1779         char *p;
1780         struct secasindex *saidx = &sav->sah->saidx;
1781
1782         KASSERT(saidx->src.sa.sa_family == saidx->dst.sa.sa_family,
1783                 ("ipsec_logsastr: address family mismatch"));
1784
1785         p = buf;
1786         snprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi));
1787         while (p && *p)
1788                 p++;
1789         /* NB: only use ipsec_address on one address at a time */
1790         snprintf(p, sizeof (buf) - (p - buf), "src=%s ",
1791                 ipsec_address(&saidx->src));
1792         while (p && *p)
1793                 p++;
1794         snprintf(p, sizeof (buf) - (p - buf), "dst=%s)",
1795                 ipsec_address(&saidx->dst));
1796
1797         return buf;
1798 }
1799
1800 void
1801 ipsec_dumpmbuf(struct mbuf *m)
1802 {
1803         int totlen;
1804         int i;
1805         u_char *p;
1806
1807         totlen = 0;
1808         printf("---\n");
1809         while (m) {
1810                 p = mtod(m, u_char *);
1811                 for (i = 0; i < m->m_len; i++) {
1812                         printf("%02x ", p[i]);
1813                         totlen++;
1814                         if (totlen % 16 == 0)
1815                                 printf("\n");
1816                 }
1817                 m = m->m_next;
1818         }
1819         if (totlen % 16 != 0)
1820                 printf("\n");
1821         printf("---\n");
1822 }
1823
1824 /* XXX this stuff doesn't belong here... */
1825
1826 static  struct xformsw* xforms = NULL;
1827
1828 /*
1829  * Register a transform; typically at system startup.
1830  */
1831 void
1832 xform_register(struct xformsw* xsp)
1833 {
1834         xsp->xf_next = xforms;
1835         xforms = xsp;
1836 }
1837
1838 /*
1839  * Initialize transform support in an sav.
1840  */
1841 int
1842 xform_init(struct secasvar *sav, int xftype)
1843 {
1844         struct xformsw *xsp;
1845
1846         for (xsp = xforms; xsp; xsp = xsp->xf_next)
1847                 if (xsp->xf_type == xftype)
1848                         return (*xsp->xf_init)(sav, xsp);
1849         return EINVAL;
1850 }