1 /* $NetBSD: ipsec_netbsd.c,v 1.12 2004/08/15 19:10:26 atatat Exp $ */ 2 /* $KAME: esp_input.c,v 1.60 2001/09/04 08:43:19 itojun Exp $ */ 3 /* $KAME: ah_input.c,v 1.64 2001/09/04 08:43:19 itojun 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 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: ipsec_netbsd.c,v 1.12 2004/08/15 19:10:26 atatat Exp $"); 36 37 #include "opt_inet.h" 38 #include "opt_ipsec.h" 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/malloc.h> 43 #include <sys/mbuf.h> 44 #include <sys/domain.h> 45 #include <sys/protosw.h> 46 #include <sys/socket.h> 47 #include <sys/errno.h> 48 #include <sys/time.h> 49 #include <sys/kernel.h> 50 #include <sys/sysctl.h> 51 52 #include <net/if.h> 53 #include <net/route.h> 54 #include <net/netisr.h> 55 #include <machine/cpu.h> 56 57 #include <netinet/in.h> 58 #include <netinet/in_systm.h> 59 #include <netinet/in_var.h> 60 #include <netinet/ip.h> 61 #include <netinet/ip_var.h> 62 #include <netinet/ip_ecn.h> 63 #include <netinet/ip_icmp.h> 64 65 66 #include <netipsec/ipsec.h> 67 #include <netipsec/ipsec_var.h> 68 #include <netipsec/key.h> 69 #include <netipsec/keydb.h> 70 #include <netipsec/key_debug.h> 71 #include <netipsec/ah_var.h> 72 #include <netipsec/esp.h> 73 #include <netipsec/esp_var.h> 74 #include <netipsec/ipip_var.h> 75 #include <netipsec/ipcomp_var.h> 76 77 #ifdef INET6 78 #include <netipsec/ipsec6.h> 79 #include <netinet6/ip6protosw.h> 80 #include <netinet/icmp6.h> 81 #endif 82 83 #include <machine/stdarg.h> 84 85 86 87 #include <netipsec/key.h> 88 89 /* assumes that ip header and ah header are contiguous on mbuf */ 90 void * 91 ah4_ctlinput(cmd, sa, v) 92 int cmd; 93 struct sockaddr *sa; 94 void *v; 95 { 96 struct ip *ip = v; 97 struct ah *ah; 98 struct icmp *icp; 99 struct secasvar *sav; 100 101 if (sa->sa_family != AF_INET || 102 sa->sa_len != sizeof(struct sockaddr_in)) 103 return NULL; 104 if ((unsigned)cmd >= PRC_NCMDS) 105 return NULL; 106 #ifndef notyet 107 /* jonathan@NetBSD.org: XXX FIXME */ 108 (void) ip; (void) ah; (void) icp; (void) sav; 109 #else 110 if (cmd == PRC_MSGSIZE && ip_mtudisc && ip && ip->ip_v == 4) { 111 /* 112 * Check to see if we have a valid SA corresponding to 113 * the address in the ICMP message payload. 114 */ 115 ah = (struct ah *)((caddr_t)ip + (ip->ip_hl << 2)); 116 if ((sav = key_allocsa(AF_INET, 117 (caddr_t) &ip->ip_src, 118 (caddr_t) &ip->ip_dst, 119 IPPROTO_AH, ah->ah_spi)) == NULL) 120 return NULL; 121 if (sav->state != SADB_SASTATE_MATURE && 122 sav->state != SADB_SASTATE_DYING) { 123 key_freesav(sav); 124 return NULL; 125 } 126 127 /* XXX Further validation? */ 128 129 key_freesav(sav); 130 131 /* 132 * Now that we've validated that we are actually communicating 133 * with the host indicated in the ICMP message, locate the 134 * ICMP header, recalculate the new MTU, and create the 135 * corresponding routing entry. 136 */ 137 icp = (struct icmp *)((caddr_t)ip - 138 offsetof(struct icmp, icmp_ip)); 139 icmp_mtudisc(icp, ip->ip_dst); 140 141 return NULL; 142 } 143 #endif 144 145 return NULL; 146 } 147 148 /* assumes that ip header and esp header are contiguous on mbuf */ 149 void * 150 esp4_ctlinput(cmd, sa, v) 151 int cmd; 152 struct sockaddr *sa; 153 void *v; 154 { 155 struct ip *ip = v; 156 struct esp *esp; 157 struct icmp *icp; 158 struct secasvar *sav; 159 160 if (sa->sa_family != AF_INET || 161 sa->sa_len != sizeof(struct sockaddr_in)) 162 return NULL; 163 if ((unsigned)cmd >= PRC_NCMDS) 164 return NULL; 165 #ifndef notyet 166 /* jonathan@NetBSD.org: XXX FIXME */ 167 (void) ip; (void) esp; (void) icp; (void) sav; 168 #else 169 if (cmd == PRC_MSGSIZE && ip_mtudisc && ip && ip->ip_v == 4) { 170 /* 171 * Check to see if we have a valid SA corresponding to 172 * the address in the ICMP message payload. 173 */ 174 esp = (struct esp *)((caddr_t)ip + (ip->ip_hl << 2)); 175 if ((sav = key_allocsa(AF_INET, 176 (caddr_t) &ip->ip_src, 177 (caddr_t) &ip->ip_dst, 178 IPPROTO_ESP, esp->esp_spi)) == NULL) 179 return NULL; 180 if (sav->state != SADB_SASTATE_MATURE && 181 sav->state != SADB_SASTATE_DYING) { 182 key_freesav(sav); 183 return NULL; 184 } 185 186 /* XXX Further validation? */ 187 188 key_freesav(sav); 189 190 /* 191 * Now that we've validated that we are actually communicating 192 * with the host indicated in the ICMP message, locate the 193 * ICMP header, recalculate the new MTU, and create the 194 * corresponding routing entry. 195 */ 196 icp = (struct icmp *)((caddr_t)ip - 197 offsetof(struct icmp, icmp_ip)); 198 icmp_mtudisc(icp, ip->ip_dst); 199 200 return NULL; 201 } 202 #endif 203 204 return NULL; 205 } 206 207 #ifdef INET6 208 void 209 esp6_ctlinput(cmd, sa, d) 210 int cmd; 211 struct sockaddr *sa; 212 void *d; 213 { 214 const struct newesp *espp; 215 struct newesp esp; 216 struct ip6ctlparam *ip6cp = NULL, ip6cp1; 217 struct secasvar *sav; 218 struct ip6_hdr *ip6; 219 struct mbuf *m; 220 int off; 221 struct sockaddr_in6 *sa6_src, *sa6_dst; 222 223 if (sa->sa_family != AF_INET6 || 224 sa->sa_len != sizeof(struct sockaddr_in6)) 225 return; 226 if ((unsigned)cmd >= PRC_NCMDS) 227 return; 228 229 /* if the parameter is from icmp6, decode it. */ 230 if (d != NULL) { 231 ip6cp = (struct ip6ctlparam *)d; 232 m = ip6cp->ip6c_m; 233 ip6 = ip6cp->ip6c_ip6; 234 off = ip6cp->ip6c_off; 235 } else { 236 m = NULL; 237 ip6 = NULL; 238 off = 0; 239 } 240 241 if (ip6) { 242 /* 243 * Notify the error to all possible sockets via pfctlinput2. 244 * Since the upper layer information (such as protocol type, 245 * source and destination ports) is embedded in the encrypted 246 * data and might have been cut, we can't directly call 247 * an upper layer ctlinput function. However, the pcbnotify 248 * function will consider source and destination addresses 249 * as well as the flow info value, and may be able to find 250 * some PCB that should be notified. 251 * Although pfctlinput2 will call esp6_ctlinput(), there is 252 * no possibility of an infinite loop of function calls, 253 * because we don't pass the inner IPv6 header. 254 */ 255 bzero(&ip6cp1, sizeof(ip6cp1)); 256 ip6cp1.ip6c_src = ip6cp->ip6c_src; 257 pfctlinput2(cmd, sa, (void *)&ip6cp1); 258 259 /* 260 * Then go to special cases that need ESP header information. 261 * XXX: We assume that when ip6 is non NULL, 262 * M and OFF are valid. 263 */ 264 265 /* check if we can safely examine src and dst ports */ 266 if (m->m_pkthdr.len < off + sizeof(esp)) 267 return; 268 269 if (m->m_len < off + sizeof(esp)) { 270 /* 271 * this should be rare case, 272 * so we compromise on this copy... 273 */ 274 m_copydata(m, off, sizeof(esp), (caddr_t)&esp); 275 espp = &esp; 276 } else 277 espp = (struct newesp*)(mtod(m, caddr_t) + off); 278 279 if (cmd == PRC_MSGSIZE) { 280 int valid = 0; 281 282 /* 283 * Check to see if we have a valid SA corresponding to 284 * the address in the ICMP message payload. 285 */ 286 sa6_src = ip6cp->ip6c_src; 287 sa6_dst = (struct sockaddr_in6 *)sa; 288 #ifdef KAME 289 sav = key_allocsa(AF_INET6, 290 (caddr_t)&sa6_src->sin6_addr, 291 (caddr_t)&sa6_dst->sin6_addr, 292 IPPROTO_ESP, espp->esp_spi); 293 #else 294 /* jonathan@NetBSD.org: XXX FIXME */ 295 (void)sa6_src; (void)sa6_dst; 296 sav = KEY_ALLOCSA((union sockaddr_union*)sa, 297 IPPROTO_ESP, espp->esp_spi); 298 299 #endif 300 if (sav) { 301 if (sav->state == SADB_SASTATE_MATURE || 302 sav->state == SADB_SASTATE_DYING) 303 valid++; 304 KEY_FREESAV(&sav); 305 } 306 307 /* XXX Further validation? */ 308 309 /* 310 * Depending on the value of "valid" and routing table 311 * size (mtudisc_{hi,lo}wat), we will: 312 * - recalcurate the new MTU and create the 313 * corresponding routing entry, or 314 * - ignore the MTU change notification. 315 */ 316 icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); 317 } 318 } else { 319 /* we normally notify any pcb here */ 320 } 321 } 322 #endif /* INET6 */ 323 324 static int 325 sysctl_fast_ipsec(SYSCTLFN_ARGS) 326 { 327 int error, t; 328 struct sysctlnode node; 329 330 node = *rnode; 331 t = *(int*)rnode->sysctl_data; 332 node.sysctl_data = &t; 333 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 334 if (error || newp == NULL) 335 return (error); 336 337 switch (rnode->sysctl_num) { 338 case IPSECCTL_DEF_ESP_TRANSLEV: 339 case IPSECCTL_DEF_ESP_NETLEV: 340 case IPSECCTL_DEF_AH_TRANSLEV: 341 case IPSECCTL_DEF_AH_NETLEV: 342 if (t != IPSEC_LEVEL_USE && 343 t != IPSEC_LEVEL_REQUIRE) 344 return (EINVAL); 345 ipsec_invalpcbcacheall(); 346 break; 347 case IPSECCTL_DEF_POLICY: 348 if (t != IPSEC_POLICY_DISCARD && 349 t != IPSEC_POLICY_NONE) 350 return (EINVAL); 351 ipsec_invalpcbcacheall(); 352 break; 353 default: 354 return (EINVAL); 355 } 356 357 *(int*)rnode->sysctl_data = t; 358 359 return (0); 360 } 361 362 /* XXX will need a different oid at parent */ 363 SYSCTL_SETUP(sysctl_net_inet_fast_ipsec_setup, "sysctl net.inet.ipsec subtree setup") 364 { 365 struct sysctlnode *_ipsec; 366 int ipproto_ipsec; 367 368 sysctl_createv(clog, 0, NULL, NULL, 369 CTLFLAG_PERMANENT, 370 CTLTYPE_NODE, "net", NULL, 371 NULL, 0, NULL, 0, 372 CTL_NET, CTL_EOL); 373 sysctl_createv(clog, 0, NULL, NULL, 374 CTLFLAG_PERMANENT, 375 CTLTYPE_NODE, "inet", NULL, 376 NULL, 0, NULL, 0, 377 CTL_NET, PF_INET, CTL_EOL); 378 379 /* 380 * in numerical order: 381 * 382 * net.inet.ipip: CTL_NET.PF_INET.IPPROTO_IPIP 383 * net.inet.esp: CTL_NET.PF_INET.IPPROTO_ESP 384 * net.inet.ah: CTL_NET.PF_INET.IPPROTO_AH 385 * net.inet.ipcomp: CTL_NET.PF_INET.IPPROTO_IPCOMP 386 * net.inet.ipsec: CTL_NET.PF_INET.CTL_CREATE 387 * 388 * this creates separate trees by name, but maintains that the 389 * ipsec name leads to all the old leaves. 390 */ 391 392 /* create net.inet.ipip */ 393 sysctl_createv(clog, 0, NULL, NULL, 394 CTLFLAG_PERMANENT, 395 CTLTYPE_NODE, "ipip", NULL, 396 NULL, 0, NULL, 0, 397 CTL_NET, PF_INET, IPPROTO_IPIP, CTL_EOL); 398 sysctl_createv(clog, 0, NULL, NULL, 399 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 400 CTLTYPE_STRUCT, "ipip_stats", NULL, 401 NULL, 0, &ipipstat, sizeof(ipipstat), 402 CTL_NET, PF_INET, IPPROTO_IPIP, 403 CTL_CREATE, CTL_EOL); 404 405 /* create net.inet.esp subtree under IPPROTO_ESP */ 406 sysctl_createv(clog, 0, NULL, NULL, 407 CTLFLAG_PERMANENT, 408 CTLTYPE_NODE, "esp", NULL, 409 NULL, 0, NULL, 0, 410 CTL_NET, PF_INET, IPPROTO_ESP, CTL_EOL); 411 sysctl_createv(clog, 0, NULL, NULL, 412 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 413 CTLTYPE_INT, "trans_deflev", NULL, 414 sysctl_fast_ipsec, 0, &ip4_esp_trans_deflev, 0, 415 CTL_NET, PF_INET, IPPROTO_ESP, 416 IPSECCTL_DEF_ESP_TRANSLEV, CTL_EOL); 417 sysctl_createv(clog, 0, NULL, NULL, 418 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 419 CTLTYPE_INT, "net_deflev", NULL, 420 sysctl_fast_ipsec, 0, &ip4_esp_net_deflev, 0, 421 CTL_NET, PF_INET, IPPROTO_ESP, 422 IPSECCTL_DEF_ESP_NETLEV, CTL_EOL); 423 sysctl_createv(clog, 0, NULL, NULL, 424 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 425 CTLTYPE_STRUCT, "esp_stats", NULL, 426 NULL, 0, &espstat, sizeof(espstat), 427 CTL_NET, PF_INET, IPPROTO_ESP, 428 CTL_CREATE, CTL_EOL); 429 430 /* create net.inet.ah subtree under IPPROTO_AH */ 431 sysctl_createv(clog, 0, NULL, NULL, 432 CTLFLAG_PERMANENT, 433 CTLTYPE_NODE, "ah", NULL, 434 NULL, 0, NULL, 0, 435 CTL_NET, PF_INET, IPPROTO_AH, CTL_EOL); 436 sysctl_createv(clog, 0, NULL, NULL, 437 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 438 CTLTYPE_INT, "cleartos", NULL, 439 NULL, 0, &/*ip4_*/ah_cleartos, 0, 440 CTL_NET, PF_INET, IPPROTO_AH, 441 IPSECCTL_AH_CLEARTOS, CTL_EOL); 442 sysctl_createv(clog, 0, NULL, NULL, 443 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 444 CTLTYPE_INT, "offsetmask", NULL, 445 NULL, 0, &ip4_ah_offsetmask, 0, 446 CTL_NET, PF_INET, IPPROTO_AH, 447 IPSECCTL_AH_OFFSETMASK, CTL_EOL); 448 sysctl_createv(clog, 0, NULL, NULL, 449 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 450 CTLTYPE_INT, "trans_deflev", NULL, 451 sysctl_fast_ipsec, 0, &ip4_ah_trans_deflev, 0, 452 CTL_NET, PF_INET, IPPROTO_AH, 453 IPSECCTL_DEF_AH_TRANSLEV, CTL_EOL); 454 sysctl_createv(clog, 0, NULL, NULL, 455 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 456 CTLTYPE_INT, "net_deflev", NULL, 457 sysctl_fast_ipsec, 0, &ip4_ah_net_deflev, 0, 458 CTL_NET, PF_INET, IPPROTO_AH, 459 IPSECCTL_DEF_AH_NETLEV, CTL_EOL); 460 sysctl_createv(clog, 0, NULL, NULL, 461 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 462 CTLTYPE_STRUCT, "ah_stats", NULL, 463 NULL, 0, &ahstat, sizeof(ahstat), 464 CTL_NET, PF_INET, IPPROTO_AH, 465 CTL_CREATE, CTL_EOL); 466 467 /* create net.inet.ipcomp */ 468 sysctl_createv(clog, 0, NULL, NULL, 469 CTLFLAG_PERMANENT, 470 CTLTYPE_NODE, "ipcomp", NULL, 471 NULL, 0, NULL, 0, 472 CTL_NET, PF_INET, IPPROTO_IPCOMP, CTL_EOL); 473 sysctl_createv(clog, 0, NULL, NULL, 474 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 475 CTLTYPE_STRUCT, "ipcomp_stats", NULL, 476 NULL, 0, &ipcompstat, sizeof(ipcompstat), 477 CTL_NET, PF_INET, IPPROTO_IPCOMP, 478 CTL_CREATE, CTL_EOL); 479 480 /* create net.inet.ipsec subtree under dynamic oid */ 481 sysctl_createv(clog, 0, NULL, &_ipsec, 482 CTLFLAG_PERMANENT, 483 CTLTYPE_NODE, "ipsec", NULL, 484 NULL, 0, NULL, 0, 485 CTL_NET, PF_INET, CTL_CREATE, CTL_EOL); 486 ipproto_ipsec = (_ipsec != NULL) ? _ipsec->sysctl_num : 0; 487 488 sysctl_createv(clog, 0, NULL, NULL, 489 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 490 CTLTYPE_INT, "def_policy", NULL, 491 sysctl_fast_ipsec, 0, &ip4_def_policy.policy, 0, 492 CTL_NET, PF_INET, ipproto_ipsec, 493 IPSECCTL_DEF_POLICY, CTL_EOL); 494 sysctl_createv(clog, 0, NULL, NULL, 495 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 496 CTLTYPE_INT, "esp_trans_deflev", NULL, 497 sysctl_fast_ipsec, 0, &ip4_esp_trans_deflev, 0, 498 CTL_NET, PF_INET, ipproto_ipsec, 499 IPSECCTL_DEF_ESP_TRANSLEV, CTL_EOL); 500 sysctl_createv(clog, 0, NULL, NULL, 501 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 502 CTLTYPE_INT, "esp_net_deflev", NULL, 503 sysctl_fast_ipsec, 0, &ip4_esp_net_deflev, 0, 504 CTL_NET, PF_INET, ipproto_ipsec, 505 IPSECCTL_DEF_ESP_NETLEV, CTL_EOL); 506 sysctl_createv(clog, 0, NULL, NULL, 507 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 508 CTLTYPE_INT, "ah_trans_deflev", NULL, 509 sysctl_fast_ipsec, 0, &ip4_ah_trans_deflev, 0, 510 CTL_NET, PF_INET, ipproto_ipsec, 511 IPSECCTL_DEF_AH_TRANSLEV, CTL_EOL); 512 sysctl_createv(clog, 0, NULL, NULL, 513 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 514 CTLTYPE_INT, "ah_net_deflev", NULL, 515 sysctl_fast_ipsec, 0, &ip4_ah_net_deflev, 0, 516 CTL_NET, PF_INET, ipproto_ipsec, 517 IPSECCTL_DEF_AH_NETLEV, CTL_EOL); 518 sysctl_createv(clog, 0, NULL, NULL, 519 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 520 CTLTYPE_INT, "ah_cleartos", NULL, 521 NULL, 0, &/*ip4_*/ah_cleartos, 0, 522 CTL_NET, PF_INET, ipproto_ipsec, 523 IPSECCTL_AH_CLEARTOS, CTL_EOL); 524 sysctl_createv(clog, 0, NULL, NULL, 525 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 526 CTLTYPE_INT, "ah_offsetmask", NULL, 527 NULL, 0, &ip4_ah_offsetmask, 0, 528 CTL_NET, PF_INET, ipproto_ipsec, 529 IPSECCTL_AH_OFFSETMASK, CTL_EOL); 530 sysctl_createv(clog, 0, NULL, NULL, 531 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 532 CTLTYPE_INT, "dfbit", NULL, 533 NULL, 0, &ip4_ipsec_dfbit, 0, 534 CTL_NET, PF_INET, ipproto_ipsec, 535 IPSECCTL_DFBIT, CTL_EOL); 536 sysctl_createv(clog, 0, NULL, NULL, 537 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 538 CTLTYPE_INT, "ecn", NULL, 539 NULL, 0, &ip4_ipsec_ecn, 0, 540 CTL_NET, PF_INET, ipproto_ipsec, 541 IPSECCTL_ECN, CTL_EOL); 542 sysctl_createv(clog, 0, NULL, NULL, 543 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 544 CTLTYPE_INT, "debug", NULL, 545 NULL, 0, &ipsec_debug, 0, 546 CTL_NET, PF_INET, ipproto_ipsec, 547 IPSECCTL_DEBUG, CTL_EOL); 548 sysctl_createv(clog, 0, NULL, NULL, 549 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 550 CTLTYPE_STRUCT, "ipsecstats", NULL, 551 NULL, 0, &ipsecstat, sizeof(ipsecstat), 552 CTL_NET, PF_INET, ipproto_ipsec, 553 CTL_CREATE, CTL_EOL); 554 } 555