1 /* $NetBSD: ipsec_netbsd.c,v 1.10 2004/05/07 00:55:14 jonathan 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.10 2004/05/07 00:55:14 jonathan 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 366 sysctl_createv(clog, 0, NULL, NULL, 367 CTLFLAG_PERMANENT, 368 CTLTYPE_NODE, "net", NULL, 369 NULL, 0, NULL, 0, 370 CTL_NET, CTL_EOL); 371 sysctl_createv(clog, 0, NULL, NULL, 372 CTLFLAG_PERMANENT, 373 CTLTYPE_NODE, "inet", NULL, 374 NULL, 0, NULL, 0, 375 CTL_NET, PF_INET, CTL_EOL); 376 377 /* create net.inet.ah subtree under IPPROTO_AH */ 378 sysctl_createv(clog, 0, NULL, NULL, 379 CTLFLAG_PERMANENT, 380 CTLTYPE_NODE, "ah", NULL, 381 NULL, 0, NULL, 0, 382 CTL_NET, PF_INET, IPPROTO_AH, CTL_EOL); 383 384 sysctl_createv(clog, 0, NULL, NULL, 385 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 386 CTLTYPE_STRUCT, "stats", NULL, 387 NULL, 0, &ahstat, sizeof(ahstat), 388 CTL_NET, PF_INET, IPPROTO_AH, 389 IPSECCTL_STATS, CTL_EOL); 390 391 sysctl_createv(clog, 0, NULL, NULL, 392 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 393 CTLTYPE_INT, "cleartos", NULL, 394 NULL, 0, &/*ip4_*/ah_cleartos, 0, 395 CTL_NET, PF_INET, IPPROTO_AH, 396 IPSECCTL_AH_CLEARTOS, CTL_EOL); 397 sysctl_createv(clog, 0, NULL, NULL, 398 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 399 CTLTYPE_INT, "offsetmask", NULL, 400 NULL, 0, &ip4_ah_offsetmask, 0, 401 CTL_NET, PF_INET, IPPROTO_AH, 402 IPSECCTL_AH_OFFSETMASK, CTL_EOL); 403 sysctl_createv(clog, 0, NULL, NULL, 404 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 405 CTLTYPE_INT, "trans_deflev", NULL, 406 sysctl_fast_ipsec, 0, &ip4_ah_trans_deflev, 0, 407 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 408 IPSECCTL_DEF_AH_TRANSLEV, CTL_EOL); 409 sysctl_createv(clog, 0, NULL, NULL, 410 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 411 CTLTYPE_INT, "net_deflev", NULL, 412 sysctl_fast_ipsec, 0, &ip4_ah_net_deflev, 0, 413 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 414 IPSECCTL_DEF_AH_NETLEV, CTL_EOL); 415 416 /* create net.inet.esp subtree under IPPROTO_ESP */ 417 sysctl_createv(clog, 0, NULL, NULL, 418 CTLFLAG_PERMANENT, 419 CTLTYPE_NODE, "esp", NULL, 420 NULL, 0, NULL, 0, 421 CTL_NET, PF_INET, IPPROTO_ESP, CTL_EOL); 422 423 sysctl_createv(clog, 0, NULL, NULL, 424 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 425 CTLTYPE_STRUCT, "stats", NULL, 426 NULL, 0, &espstat, sizeof(espstat), 427 CTL_NET, PF_INET, IPPROTO_ESP, 428 IPSECCTL_STATS, CTL_EOL); 429 430 sysctl_createv(clog, 0, NULL, NULL, 431 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 432 CTLTYPE_INT, "trans_deflev", NULL, 433 sysctl_fast_ipsec, 0, &ip4_esp_trans_deflev, 0, 434 CTL_NET, PF_INET, IPPROTO_ESP, 435 IPSECCTL_DEF_ESP_TRANSLEV, CTL_EOL); 436 sysctl_createv(clog, 0, NULL, NULL, 437 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 438 CTLTYPE_INT, "net_deflev", NULL, 439 sysctl_fast_ipsec, 0, &ip4_esp_net_deflev, 0, 440 CTL_NET, PF_INET, IPPROTO_ESP, 441 IPSECCTL_DEF_ESP_NETLEV, CTL_EOL); 442 443 /* create net.inet.ipcomp */ 444 sysctl_createv(clog, 0, NULL, NULL, 445 CTLFLAG_PERMANENT, 446 CTLTYPE_NODE, "ipcomp", NULL, 447 NULL, 0, NULL, 0, 448 CTL_NET, PF_INET, IPPROTO_IPCOMP, CTL_EOL); 449 450 sysctl_createv(clog, 0, NULL, NULL, 451 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 452 CTLTYPE_STRUCT, "stats", NULL, 453 NULL, 0, &ipcompstat, sizeof(ipcompstat), 454 CTL_NET, PF_INET, IPPROTO_IPCOMP, 455 IPSECCTL_STATS, CTL_EOL); 456 457 /* create net.inet.ipip */ 458 sysctl_createv(clog, 0, NULL, NULL, 459 CTLFLAG_PERMANENT, 460 CTLTYPE_NODE, "ipip", NULL, 461 NULL, 0, NULL, 0, 462 CTL_NET, PF_INET, IPPROTO_IPIP, CTL_EOL); 463 464 sysctl_createv(clog, 0, NULL, NULL, 465 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 466 CTLTYPE_STRUCT, "stats", NULL, 467 NULL, 0, &ipipstat, sizeof(ipipstat), 468 CTL_NET, PF_INET, IPPROTO_IPIP, 469 IPSECCTL_STATS, CTL_EOL); 470 471 472 /* create net.inet.ipsec subtree under CTL_IPPROTO_IPSEC */ 473 sysctl_createv(clog, 0, NULL, NULL, 474 CTLFLAG_PERMANENT, 475 CTLTYPE_NODE, "ipsec", NULL, 476 NULL, 0, NULL, 0, 477 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, CTL_EOL); 478 479 sysctl_createv(clog, 0, NULL, NULL, 480 CTLFLAG_PERMANENT|CTLFLAG_READONLY, 481 CTLTYPE_STRUCT, "stats", NULL, 482 NULL, 0, &ipsecstat, sizeof(ipsecstat), 483 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 484 IPSECCTL_STATS, CTL_EOL); 485 486 sysctl_createv(clog, 0, NULL, NULL, 487 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 488 CTLTYPE_INT, "def_policy", NULL, 489 sysctl_fast_ipsec, 0, &ip4_def_policy.policy, 0, 490 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 491 IPSECCTL_DEF_POLICY, CTL_EOL); 492 sysctl_createv(clog, 0, NULL, NULL, 493 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 494 CTLTYPE_INT, "dfbit", NULL, 495 NULL, 0, &ip4_ipsec_dfbit, 0, 496 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 497 IPSECCTL_DFBIT, CTL_EOL); 498 sysctl_createv(clog, 0, NULL, NULL, 499 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 500 CTLTYPE_INT, "ecn", NULL, 501 NULL, 0, &ip4_ipsec_ecn, 0, 502 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 503 IPSECCTL_ECN, CTL_EOL); 504 sysctl_createv(clog, 0, NULL, NULL, 505 CTLFLAG_PERMANENT|CTLFLAG_READWRITE, 506 CTLTYPE_INT, "debug", NULL, 507 NULL, 0, &ipsec_debug, 0, 508 CTL_NET, PF_INET, CTL_IPPROTO_IPSEC, 509 IPSECCTL_DEBUG, CTL_EOL); 510 511 #if 0 512 /* 513 * "aliases" for the fast ipsec subtree 514 */ 515 sysctl_createv(clog, 0, NULL, NULL, 516 CTLFLAG_PERMANENT|CTLFLAG_ALIAS, 517 CTLTYPE_NODE, "fast_esp", NULL, 518 NULL, IPPROTO_AH, NULL, 0, 519 CTL_NET, PF_INET, IPPROTO_ESP, CTL_EOL); 520 sysctl_createv(clog, 0, NULL, NULL, 521 CTLFLAG_PERMANENT|CTLFLAG_ALIAS, 522 CTLTYPE_NODE, "fast_ipcomp", NULL, 523 NULL, IPPROTO_AH, NULL, 0, 524 CTL_NET, PF_INET, IPPROTO_IPCOMP, CTL_EOL); 525 sysctl_createv(clog, 0, NULL, NULL, 526 CTLFLAG_PERMANENT|CTLFLAG_ALIAS, 527 CTLTYPE_NODE, "fast_ah", NULL, 528 NULL, IPPROTO_AH, NULL, 0, 529 CTL_NET, PF_INET, CTL_CREATE, CTL_EOL); 530 #endif 531 } 532