1/* $KAME: keysock.c,v 1.13 2000/03/25 07:24:13 sumikawa Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32/* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ 33 34#include <sys/types.h> 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/kernel.h> 38#include <sys/sysctl.h> 39#include <sys/mbuf.h> 40#include <sys/malloc.h> 41#include <sys/socket.h> 42#include <sys/socketvar.h> 43#include <sys/domain.h> 44#include <sys/protosw.h> 45#include <sys/errno.h> 46 47#include <kern/locks.h> 48 49#include <net/raw_cb.h> 50#include <net/route.h> 51 52#include <net/pfkeyv2.h> 53#include <netkey/keydb.h> 54#include <netkey/key.h> 55#include <netkey/keysock.h> 56#include <netkey/key_debug.h> 57 58extern lck_mtx_t *raw_mtx; 59extern void key_init(void) __attribute__((section("__TEXT, initcode"))); 60 61struct sockaddr key_dst = { 2, PF_KEY, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} }; 62struct sockaddr key_src = { 2, PF_KEY, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,} }; 63 64static int key_sendup0(struct rawcb *, struct mbuf *, int); 65 66struct pfkeystat pfkeystat; 67 68 69extern lck_mtx_t *pfkey_stat_mutex; 70 71/* 72 * key_output() 73 */ 74int 75#ifdef __APPLE__ 76/* No variable argument support? */ 77key_output(struct mbuf *m, struct socket *so) 78#else 79#if __STDC__ 80key_output(struct mbuf *m, ...) 81#else 82key_output(m, va_alist) 83 struct mbuf *m; 84 va_dcl 85#endif 86#endif 87{ 88 struct sadb_msg *msg; 89 int len, error = 0; 90#ifndef __APPLE__ 91 struct socket *so; 92 va_list ap; 93 94 va_start(ap, m); 95 so = va_arg(ap, struct socket *); 96 va_end(ap); 97#endif 98 99 if (m == 0) 100 panic("key_output: NULL pointer was passed.\n"); 101 102 socket_unlock(so, 0); 103 lck_mtx_lock(pfkey_stat_mutex); 104 pfkeystat.out_total++; 105 pfkeystat.out_bytes += m->m_pkthdr.len; 106 lck_mtx_unlock(pfkey_stat_mutex); 107 108 len = m->m_pkthdr.len; 109 if (len < sizeof(struct sadb_msg)) { 110#if IPSEC_DEBUG 111 printf("key_output: Invalid message length.\n"); 112#endif 113 PFKEY_STAT_INCREMENT(pfkeystat.out_tooshort); 114 error = EINVAL; 115 goto end; 116 } 117 118 if (m->m_len < sizeof(struct sadb_msg)) { 119 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { 120#if IPSEC_DEBUG 121 printf("key_output: can't pullup mbuf\n"); 122#endif 123 PFKEY_STAT_INCREMENT(pfkeystat.out_nomem); 124 error = ENOBUFS; 125 goto end; 126 } 127 } 128 129 if ((m->m_flags & M_PKTHDR) == 0) 130 panic("key_output: not M_PKTHDR ??"); 131 132#if IPSEC_DEBUG 133 KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); 134#endif /* defined(IPSEC_DEBUG) */ 135 136 msg = mtod(m, struct sadb_msg *); 137 PFKEY_STAT_INCREMENT(pfkeystat.out_msgtype[msg->sadb_msg_type]); 138 if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 139#if IPSEC_DEBUG 140 printf("key_output: Invalid message length.\n"); 141#endif 142 PFKEY_STAT_INCREMENT(pfkeystat.out_invlen); 143 error = EINVAL; 144 goto end; 145 } 146 147 error = key_parse(m, so); 148 m = NULL; 149 150end: 151 if (m) 152 m_freem(m); 153 socket_lock(so, 0); 154 return error; 155} 156 157/* 158 * send message to the socket. 159 */ 160static int 161key_sendup0(rp, m, promisc) 162 struct rawcb *rp; 163 struct mbuf *m; 164 int promisc; 165{ 166 int error; 167 168 if (promisc) { 169 struct sadb_msg *pmsg; 170 171 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); 172 if (m && m->m_len < sizeof(struct sadb_msg)) 173 m = m_pullup(m, sizeof(struct sadb_msg)); 174 if (!m) { 175#if IPSEC_DEBUG 176 printf("key_sendup0: cannot pullup\n"); 177#endif 178 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem); 179 m_freem(m); 180 return ENOBUFS; 181 } 182 m->m_pkthdr.len += sizeof(*pmsg); 183 184 pmsg = mtod(m, struct sadb_msg *); 185 bzero(pmsg, sizeof(*pmsg)); 186 pmsg->sadb_msg_version = PF_KEY_V2; 187 pmsg->sadb_msg_type = SADB_X_PROMISC; 188 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 189 /* pid and seq? */ 190 191 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtype[pmsg->sadb_msg_type]); 192 } 193 194 if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, 195 m, NULL, &error)) { 196#if IPSEC_DEBUG 197 printf("key_sendup0: sbappendaddr failed\n"); 198#endif 199 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem); 200 } 201 else { 202 sorwakeup(rp->rcb_socket); 203 } 204 return error; 205} 206 207 208/* so can be NULL if target != KEY_SENDUP_ONE */ 209int 210key_sendup_mbuf(so, m, target) 211 struct socket *so; 212 struct mbuf *m; 213 int target; 214{ 215 struct mbuf *n; 216 struct keycb *kp; 217 int sendup; 218 struct rawcb *rp; 219 int error = 0; 220 221 if (m == NULL) 222 panic("key_sendup_mbuf: NULL pointer was passed.\n"); 223 if (so == NULL && target == KEY_SENDUP_ONE) 224 panic("key_sendup_mbuf: NULL pointer was passed.\n"); 225 226 lck_mtx_lock(pfkey_stat_mutex); 227 pfkeystat.in_total++; 228 pfkeystat.in_bytes += m->m_pkthdr.len; 229 lck_mtx_unlock(pfkey_stat_mutex); 230 if (m->m_len < sizeof(struct sadb_msg)) { 231#if 1 232 m = m_pullup(m, sizeof(struct sadb_msg)); 233 if (m == NULL) { 234 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem); 235 return ENOBUFS; 236 } 237#else 238 /* don't bother pulling it up just for stats */ 239#endif 240 } 241 if (m->m_len >= sizeof(struct sadb_msg)) { 242 struct sadb_msg *msg; 243 msg = mtod(m, struct sadb_msg *); 244 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtype[msg->sadb_msg_type]); 245 } 246 247 lck_mtx_lock(raw_mtx); 248 LIST_FOREACH(rp, &rawcb_list, list) 249 { 250 if (rp->rcb_proto.sp_family != PF_KEY) 251 continue; 252 if (rp->rcb_proto.sp_protocol 253 && rp->rcb_proto.sp_protocol != PF_KEY_V2) { 254 continue; 255 } 256 257 kp = (struct keycb *)rp; 258 259 socket_lock(rp->rcb_socket, 1); 260 /* 261 * If you are in promiscuous mode, and when you get broadcasted 262 * reply, you'll get two PF_KEY messages. 263 * (based on pf_key@inner.net message on 14 Oct 1998) 264 */ 265 if (((struct keycb *)rp)->kp_promisc) { 266 if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 267 (void)key_sendup0(rp, n, 1); 268 n = NULL; 269 } 270 } 271 272 /* the exact target will be processed later */ 273 if (so && sotorawcb(so) == rp) { 274 socket_unlock(rp->rcb_socket, 1); 275 continue; 276 } 277 278 sendup = 0; 279 switch (target) { 280 case KEY_SENDUP_ONE: 281 /* the statement has no effect */ 282 break; 283 case KEY_SENDUP_ALL: 284 sendup++; 285 break; 286 case KEY_SENDUP_REGISTERED: 287 if (kp->kp_registered) 288 sendup++; 289 break; 290 } 291 PFKEY_STAT_INCREMENT(pfkeystat.in_msgtarget[target]); 292 293 if (!sendup) { 294 socket_unlock(rp->rcb_socket, 1); 295 continue; 296 } 297 else 298 sendup = 0; // clear for next iteration 299 300 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { 301#if IPSEC_DEBUG 302 printf("key_sendup: m_copy fail\n"); 303#endif 304 m_freem(m); 305 PFKEY_STAT_INCREMENT(pfkeystat.in_nomem); 306 socket_unlock(rp->rcb_socket, 1); 307 lck_mtx_unlock(raw_mtx); 308 return ENOBUFS; 309 } 310 311 /* 312 * ignore error even if queue is full. PF_KEY does not 313 * guarantee the delivery of the message. 314 * this is important when target == KEY_SENDUP_ALL. 315 */ 316 key_sendup0(rp, n, 0); 317 socket_unlock(rp->rcb_socket, 1); 318 n = NULL; 319 } 320 321 lck_mtx_unlock(raw_mtx); 322 if (so) { 323 socket_lock(so, 1); 324 error = key_sendup0(sotorawcb(so), m, 0); 325 socket_unlock(so, 1); 326 m = NULL; 327 } else { 328 error = 0; 329 m_freem(m); 330 } 331 return error; 332} 333 334/* 335 * key_abort() 336 * derived from net/rtsock.c:rts_abort() 337 */ 338static int 339key_abort(struct socket *so) 340{ 341 int error; 342 error = raw_usrreqs.pru_abort(so); 343 return error; 344} 345 346/* 347 * key_attach() 348 * derived from net/rtsock.c:rts_attach() 349 */ 350static int 351key_attach(struct socket *so, int proto, struct proc *p) 352{ 353 struct keycb *kp; 354 int error; 355 356 if (sotorawcb(so) != 0) 357 return EISCONN; /* XXX panic? */ 358 kp = (struct keycb *)_MALLOC(sizeof *kp, M_PCB, M_WAITOK); /* XXX */ 359 if (kp == 0) 360 return ENOBUFS; 361 bzero(kp, sizeof *kp); 362 363 so->so_pcb = (caddr_t)kp; 364 kp->kp_promisc = kp->kp_registered = 0; 365 kp->kp_raw.rcb_laddr = &key_src; 366 kp->kp_raw.rcb_faddr = &key_dst; 367 368 error = raw_usrreqs.pru_attach(so, proto, p); 369 kp = (struct keycb *)sotorawcb(so); 370 if (error) { 371 _FREE(kp, M_PCB); 372 so->so_pcb = (caddr_t) 0; 373 so->so_flags |= SOF_PCBCLEARING; 374 printf("key_usrreq: key_usrreq results %d\n", error); 375 return error; 376 } 377 378 /* so is already locked when calling key_attach */ 379 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ 380 key_cb.key_count++; 381 key_cb.any_count++; 382 soisconnected(so); 383 so->so_options |= SO_USELOOPBACK; 384 385 return 0; 386} 387 388/* 389 * key_bind() 390 * derived from net/rtsock.c:rts_bind() 391 */ 392static int 393key_bind(struct socket *so, struct sockaddr *nam, struct proc *p) 394{ 395 int error; 396 error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */ 397 return error; 398} 399 400/* 401 * key_connect() 402 * derived from net/rtsock.c:rts_connect() 403 */ 404static int 405key_connect(struct socket *so, struct sockaddr *nam, struct proc *p) 406{ 407 int error; 408 error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */ 409 return error; 410} 411 412/* 413 * key_detach() 414 * derived from net/rtsock.c:rts_detach() 415 */ 416static int 417key_detach(struct socket *so) 418{ 419 struct keycb *kp = (struct keycb *)sotorawcb(so); 420 int error; 421 422 if (kp != 0) { 423 if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ 424 key_cb.key_count--; 425 key_cb.any_count--; 426 socket_unlock(so, 0); 427 key_freereg(so); 428 socket_lock(so, 0); 429 } 430 error = raw_usrreqs.pru_detach(so); 431 return error; 432} 433 434/* 435 * key_disconnect() 436 * derived from net/rtsock.c:key_disconnect() 437 */ 438static int 439key_disconnect(struct socket *so) 440{ 441 int error; 442 error = raw_usrreqs.pru_disconnect(so); 443 return error; 444} 445 446/* 447 * key_peeraddr() 448 * derived from net/rtsock.c:rts_peeraddr() 449 */ 450static int 451key_peeraddr(struct socket *so, struct sockaddr **nam) 452{ 453 int error; 454 error = raw_usrreqs.pru_peeraddr(so, nam); 455 return error; 456} 457 458/* 459 * key_send() 460 * derived from net/rtsock.c:rts_send() 461 */ 462static int 463key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 464 struct mbuf *control, struct proc *p) 465{ 466 int error; 467 error = raw_usrreqs.pru_send(so, flags, m, nam, control, p); 468 return error; 469} 470 471/* 472 * key_shutdown() 473 * derived from net/rtsock.c:rts_shutdown() 474 */ 475static int 476key_shutdown(struct socket *so) 477{ 478 int error; 479 error = raw_usrreqs.pru_shutdown(so); 480 return error; 481} 482 483/* 484 * key_sockaddr() 485 * derived from net/rtsock.c:rts_sockaddr() 486 */ 487static int 488key_sockaddr(struct socket *so, struct sockaddr **nam) 489{ 490 int error; 491 error = raw_usrreqs.pru_sockaddr(so, nam); 492 return error; 493} 494 495struct pr_usrreqs key_usrreqs = { 496 key_abort, pru_accept_notsupp, key_attach, key_bind, 497 key_connect, 498 pru_connect2_notsupp, pru_control_notsupp, key_detach, 499 key_disconnect, pru_listen_notsupp, key_peeraddr, 500 pru_rcvd_notsupp, 501 pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown, 502 key_sockaddr, sosend, soreceive, pru_sopoll_notsupp 503}; 504 505/* sysctl */ 506SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Key Family"); 507 508/* 509 * Definitions of protocols supported in the KEY domain. 510 */ 511 512extern struct domain keydomain; 513 514struct protosw keysw[] = { 515{ SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, 516 NULL, key_output, raw_ctlinput, NULL, 517 NULL, 518 key_init, NULL, NULL, NULL, 519 NULL, 520 &key_usrreqs, 521 NULL, NULL, NULL, 522 { NULL, NULL }, NULL, { 0 } 523} 524}; 525 526struct domain keydomain = { PF_KEY, "key", key_domain_init, NULL, NULL, 527 keysw, NULL, 528 NULL, 0, 529 sizeof(struct key_cb), 0, 0, 530 NULL, 0, { 0, 0} 531}; 532 533DOMAIN_SET(key); 534