1 /* 2 * ng_socket.c 3 */ 4 5 /*- 6 * Copyright (c) 1996-1999 Whistle Communications, Inc. 7 * All rights reserved. 8 * 9 * Subject to the following obligations and disclaimer of warranty, use and 10 * redistribution of this software, in source or object code forms, with or 11 * without modifications are expressly permitted by Whistle Communications; 12 * provided, however, that: 13 * 1. Any and all reproductions of the source or object code must include the 14 * copyright notice above and the following disclaimer of warranties; and 15 * 2. No rights are granted, in any manner or form, to use Whistle 16 * Communications, Inc. trademarks, including the mark "WHISTLE 17 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 18 * such appears in the above copyright notice or in the software. 19 * 20 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 21 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 22 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 23 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 25 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 26 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 27 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 28 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 29 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 30 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36 * OF SUCH DAMAGE. 37 * 38 * Author: Julian Elischer <julian@freebsd.org> 39 * 40 * $FreeBSD$ 41 * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $ 42 */ 43 44 /* 45 * Netgraph socket nodes 46 * 47 * There are two types of netgraph sockets, control and data. 48 * Control sockets have a netgraph node, but data sockets are 49 * parasitic on control sockets, and have no node of their own. 50 */ 51 52 #include <sys/param.h> 53 #include <sys/domain.h> 54 #include <sys/kernel.h> 55 #include <sys/linker.h> 56 #include <sys/lock.h> 57 #include <sys/malloc.h> 58 #include <sys/mbuf.h> 59 #include <sys/mutex.h> 60 #include <sys/priv.h> 61 #include <sys/protosw.h> 62 #include <sys/queue.h> 63 #include <sys/socket.h> 64 #include <sys/socketvar.h> 65 #include <sys/syscallsubr.h> 66 #include <sys/sysctl.h> 67 #ifdef NOTYET 68 #include <sys/vnode.h> 69 #endif 70 71 #include <net/vnet.h> 72 73 #include <netgraph/ng_message.h> 74 #include <netgraph/netgraph.h> 75 #include <netgraph/ng_socketvar.h> 76 #include <netgraph/ng_socket.h> 77 78 #ifdef NG_SEPARATE_MALLOC 79 MALLOC_DEFINE(M_NETGRAPH_PATH, "netgraph_path", "netgraph path info "); 80 MALLOC_DEFINE(M_NETGRAPH_SOCK, "netgraph_sock", "netgraph socket info "); 81 #else 82 #define M_NETGRAPH_PATH M_NETGRAPH 83 #define M_NETGRAPH_SOCK M_NETGRAPH 84 #endif 85 86 /* 87 * It's Ascii-art time! 88 * +-------------+ +-------------+ 89 * |socket (ctl)| |socket (data)| 90 * +-------------+ +-------------+ 91 * ^ ^ 92 * | | 93 * v v 94 * +-----------+ +-----------+ 95 * |pcb (ctl)| |pcb (data)| 96 * +-----------+ +-----------+ 97 * ^ ^ 98 * | | 99 * v v 100 * +--------------------------+ 101 * | Socket type private | 102 * | data | 103 * +--------------------------+ 104 * ^ 105 * | 106 * v 107 * +----------------+ 108 * | struct ng_node | 109 * +----------------+ 110 */ 111 112 /* Netgraph node methods */ 113 static ng_constructor_t ngs_constructor; 114 static ng_rcvmsg_t ngs_rcvmsg; 115 static ng_shutdown_t ngs_shutdown; 116 static ng_newhook_t ngs_newhook; 117 static ng_connect_t ngs_connect; 118 static ng_rcvdata_t ngs_rcvdata; 119 static ng_disconnect_t ngs_disconnect; 120 121 /* Internal methods */ 122 static int ng_attach_data(struct socket *so); 123 static int ng_attach_cntl(struct socket *so); 124 static int ng_attach_common(struct socket *so, int type); 125 static void ng_detach_common(struct ngpcb *pcbp, int type); 126 static void ng_socket_free_priv(struct ngsock *priv); 127 #ifdef NOTYET 128 static int ng_internalize(struct mbuf *m, struct thread *p); 129 #endif 130 static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp); 131 static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp); 132 133 static int ngs_mod_event(module_t mod, int event, void *data); 134 static void ng_socket_item_applied(void *context, int error); 135 136 /* Netgraph type descriptor */ 137 static struct ng_type typestruct = { 138 .version = NG_ABI_VERSION, 139 .name = NG_SOCKET_NODE_TYPE, 140 .mod_event = ngs_mod_event, 141 .constructor = ngs_constructor, 142 .rcvmsg = ngs_rcvmsg, 143 .shutdown = ngs_shutdown, 144 .newhook = ngs_newhook, 145 .connect = ngs_connect, 146 .rcvdata = ngs_rcvdata, 147 .disconnect = ngs_disconnect, 148 }; 149 NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); 150 151 /* Buffer space */ 152 static u_long ngpdg_sendspace = 20 * 1024; /* really max datagram size */ 153 SYSCTL_INT(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW, 154 &ngpdg_sendspace , 0, "Maximum outgoing Netgraph datagram size"); 155 static u_long ngpdg_recvspace = 20 * 1024; 156 SYSCTL_INT(_net_graph, OID_AUTO, recvspace, CTLFLAG_RW, 157 &ngpdg_recvspace , 0, "Maximum space for incoming Netgraph datagrams"); 158 159 #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb) 160 161 /* If getting unexplained errors returned, set this to "kdb_enter("X"); */ 162 #ifndef TRAP_ERROR 163 #define TRAP_ERROR 164 #endif 165 166 /*************************************************************** 167 Control sockets 168 ***************************************************************/ 169 170 static int 171 ngc_attach(struct socket *so, int proto, struct thread *td) 172 { 173 struct ngpcb *const pcbp = sotongpcb(so); 174 int error; 175 176 error = priv_check(td, PRIV_NETGRAPH_CONTROL); 177 if (error) 178 return (error); 179 if (pcbp != NULL) 180 return (EISCONN); 181 return (ng_attach_cntl(so)); 182 } 183 184 static void 185 ngc_detach(struct socket *so) 186 { 187 struct ngpcb *const pcbp = sotongpcb(so); 188 189 KASSERT(pcbp != NULL, ("ngc_detach: pcbp == NULL")); 190 ng_detach_common(pcbp, NG_CONTROL); 191 } 192 193 static int 194 ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 195 struct mbuf *control, struct thread *td) 196 { 197 struct ngpcb *const pcbp = sotongpcb(so); 198 struct ngsock *const priv = NG_NODE_PRIVATE(pcbp->sockdata->node); 199 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; 200 struct ng_mesg *msg; 201 struct mbuf *m0; 202 item_p item; 203 char *path = NULL; 204 int len, error = 0; 205 struct ng_apply_info apply; 206 207 #ifdef NOTYET 208 if (control && (error = ng_internalize(control, td))) { 209 if (pcbp->sockdata == NULL) { 210 error = ENOTCONN; 211 goto release; 212 } 213 } 214 #else /* NOTYET */ 215 if (control) { 216 error = EINVAL; 217 goto release; 218 } 219 #endif /* NOTYET */ 220 221 /* Require destination as there may be >= 1 hooks on this node. */ 222 if (addr == NULL) { 223 error = EDESTADDRREQ; 224 goto release; 225 } 226 227 /* 228 * Allocate an expendable buffer for the path, chop off 229 * the sockaddr header, and make sure it's NUL terminated. 230 */ 231 len = sap->sg_len - 2; 232 path = malloc(len + 1, M_NETGRAPH_PATH, M_WAITOK); 233 bcopy(sap->sg_data, path, len); 234 path[len] = '\0'; 235 236 /* 237 * Move the actual message out of mbufs into a linear buffer. 238 * Start by adding up the size of the data. (could use mh_len?) 239 */ 240 for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next) 241 len += m0->m_len; 242 243 /* 244 * Move the data into a linear buffer as well. 245 * Messages are not delivered in mbufs. 246 */ 247 msg = malloc(len + 1, M_NETGRAPH_MSG, M_WAITOK); 248 m_copydata(m, 0, len, (char *)msg); 249 250 if (msg->header.version != NG_VERSION) { 251 free(msg, M_NETGRAPH_MSG); 252 error = EINVAL; 253 goto release; 254 } 255 256 /* 257 * Hack alert! 258 * We look into the message and if it mkpeers a node of unknown type, we 259 * try to load it. We need to do this now, in syscall thread, because if 260 * message gets queued and applied later we will get panic. 261 */ 262 if (msg->header.typecookie == NGM_GENERIC_COOKIE && 263 msg->header.cmd == NGM_MKPEER) { 264 struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data; 265 266 if (ng_findtype(mkp->type) == NULL) { 267 char filename[NG_TYPESIZ + 3]; 268 int fileid; 269 270 /* Not found, try to load it as a loadable module. */ 271 snprintf(filename, sizeof(filename), "ng_%s", 272 mkp->type); 273 error = kern_kldload(curthread, filename, &fileid); 274 if (error != 0) { 275 free(msg, M_NETGRAPH_MSG); 276 goto release; 277 } 278 279 /* See if type has been loaded successfully. */ 280 if (ng_findtype(mkp->type) == NULL) { 281 free(msg, M_NETGRAPH_MSG); 282 (void)kern_kldunload(curthread, fileid, 283 LINKER_UNLOAD_NORMAL); 284 error = ENXIO; 285 goto release; 286 } 287 } 288 } 289 290 item = ng_package_msg(msg, M_WAITOK); 291 if ((error = ng_address_path((pcbp->sockdata->node), item, path, 0)) 292 != 0) { 293 #ifdef TRACE_MESSAGES 294 printf("ng_address_path: errx=%d\n", error); 295 #endif 296 goto release; 297 } 298 299 #ifdef TRACE_MESSAGES 300 printf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n", 301 item->el_dest->nd_ID, 302 msg->header.typecookie, 303 msg->header.cmd, 304 msg->header.cmdstr, 305 msg->header.flags, 306 msg->header.token, 307 item->el_dest->nd_type->name); 308 #endif 309 SAVE_LINE(item); 310 /* 311 * We do not want to return from syscall until the item 312 * is processed by destination node. We register callback 313 * on the item, which will update priv->error when item 314 * was applied. 315 * If ng_snd_item() has queued item, we sleep until 316 * callback wakes us up. 317 */ 318 bzero(&apply, sizeof(apply)); 319 apply.apply = ng_socket_item_applied; 320 apply.context = priv; 321 item->apply = &apply; 322 priv->error = -1; 323 324 error = ng_snd_item(item, 0); 325 326 mtx_lock(&priv->mtx); 327 if (priv->error == -1) 328 msleep(priv, &priv->mtx, 0, "ngsock", 0); 329 mtx_unlock(&priv->mtx); 330 KASSERT(priv->error != -1, 331 ("ng_socket: priv->error wasn't updated")); 332 error = priv->error; 333 334 release: 335 if (path != NULL) 336 free(path, M_NETGRAPH_PATH); 337 if (control != NULL) 338 m_freem(control); 339 if (m != NULL) 340 m_freem(m); 341 return (error); 342 } 343 344 static int 345 ngc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 346 { 347 struct ngpcb *const pcbp = sotongpcb(so); 348 349 if (pcbp == 0) 350 return (EINVAL); 351 return (ng_bind(nam, pcbp)); 352 } 353 354 static int 355 ngc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 356 { 357 /* 358 * At this time refuse to do this.. it used to 359 * do something but it was undocumented and not used. 360 */ 361 printf("program tried to connect control socket to remote node\n"); 362 return (EINVAL); 363 } 364 365 /*************************************************************** 366 Data sockets 367 ***************************************************************/ 368 369 static int 370 ngd_attach(struct socket *so, int proto, struct thread *td) 371 { 372 struct ngpcb *const pcbp = sotongpcb(so); 373 374 if (pcbp != NULL) 375 return (EISCONN); 376 return (ng_attach_data(so)); 377 } 378 379 static void 380 ngd_detach(struct socket *so) 381 { 382 struct ngpcb *const pcbp = sotongpcb(so); 383 384 KASSERT(pcbp != NULL, ("ngd_detach: pcbp == NULL")); 385 ng_detach_common(pcbp, NG_DATA); 386 } 387 388 static int 389 ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 390 struct mbuf *control, struct thread *td) 391 { 392 struct ngpcb *const pcbp = sotongpcb(so); 393 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; 394 int len, error; 395 hook_p hook = NULL; 396 char hookname[NG_HOOKSIZ]; 397 398 if ((pcbp == NULL) || (control != NULL)) { 399 error = EINVAL; 400 goto release; 401 } 402 if (pcbp->sockdata == NULL) { 403 error = ENOTCONN; 404 goto release; 405 } 406 407 if (sap == NULL) 408 len = 0; /* Make compiler happy. */ 409 else 410 len = sap->sg_len - 2; 411 412 /* 413 * If the user used any of these ways to not specify an address 414 * then handle specially. 415 */ 416 if ((sap == NULL) || (len <= 0) || (*sap->sg_data == '\0')) { 417 if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) { 418 error = EDESTADDRREQ; 419 goto release; 420 } 421 /* 422 * If exactly one hook exists, just use it. 423 * Special case to allow write(2) to work on an ng_socket. 424 */ 425 hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks); 426 } else { 427 if (len >= NG_HOOKSIZ) { 428 error = EINVAL; 429 goto release; 430 } 431 432 /* 433 * chop off the sockaddr header, and make sure it's NUL 434 * terminated 435 */ 436 bcopy(sap->sg_data, hookname, len); 437 hookname[len] = '\0'; 438 439 /* Find the correct hook from 'hookname' */ 440 hook = ng_findhook(pcbp->sockdata->node, hookname); 441 if (hook == NULL) { 442 error = EHOSTUNREACH; 443 goto release; 444 } 445 } 446 447 /* Send data. */ 448 NG_SEND_DATA_FLAGS(error, hook, m, NG_WAITOK); 449 450 release: 451 if (control != NULL) 452 m_freem(control); 453 if (m != NULL) 454 m_freem(m); 455 return (error); 456 } 457 458 static int 459 ngd_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 460 { 461 struct ngpcb *const pcbp = sotongpcb(so); 462 463 if (pcbp == 0) 464 return (EINVAL); 465 return (ng_connect_data(nam, pcbp)); 466 } 467 468 /* 469 * Used for both data and control sockets 470 */ 471 static int 472 ng_getsockaddr(struct socket *so, struct sockaddr **addr) 473 { 474 struct ngpcb *pcbp; 475 struct sockaddr_ng *sg; 476 int sg_len; 477 int error = 0; 478 479 /* Why isn't sg_data a `char[1]' ? :-( */ 480 sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1; 481 482 pcbp = sotongpcb(so); 483 if ((pcbp == NULL) || (pcbp->sockdata == NULL)) 484 /* XXXGL: can this still happen? */ 485 return (EINVAL); 486 487 mtx_lock(&pcbp->sockdata->mtx); 488 if (pcbp->sockdata->node != NULL) { 489 node_p node = pcbp->sockdata->node; 490 int namelen = 0; /* silence compiler! */ 491 492 if (NG_NODE_HAS_NAME(node)) 493 sg_len += namelen = strlen(NG_NODE_NAME(node)); 494 495 sg = malloc(sg_len, M_SONAME, M_WAITOK | M_ZERO); 496 497 if (NG_NODE_HAS_NAME(node)) 498 bcopy(NG_NODE_NAME(node), sg->sg_data, namelen); 499 500 sg->sg_len = sg_len; 501 sg->sg_family = AF_NETGRAPH; 502 *addr = (struct sockaddr *)sg; 503 mtx_unlock(&pcbp->sockdata->mtx); 504 } else { 505 mtx_unlock(&pcbp->sockdata->mtx); 506 error = EINVAL; 507 } 508 509 return (error); 510 } 511 512 /* 513 * Attach a socket to it's protocol specific partner. 514 * For a control socket, actually create a netgraph node and attach 515 * to it as well. 516 */ 517 518 static int 519 ng_attach_cntl(struct socket *so) 520 { 521 struct ngsock *priv; 522 struct ngpcb *pcbp; 523 int error; 524 525 /* Allocate node private info */ 526 priv = malloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO); 527 528 /* Setup protocol control block */ 529 if ((error = ng_attach_common(so, NG_CONTROL)) != 0) { 530 free(priv, M_NETGRAPH_SOCK); 531 return (error); 532 } 533 pcbp = sotongpcb(so); 534 535 /* Link the pcb the private data. */ 536 priv->ctlsock = pcbp; 537 pcbp->sockdata = priv; 538 priv->refs++; 539 540 /* Initialize mutex. */ 541 mtx_init(&priv->mtx, "ng_socket", NULL, MTX_DEF); 542 543 /* Make the generic node components */ 544 if ((error = ng_make_node_common(&typestruct, &priv->node)) != 0) { 545 free(priv, M_NETGRAPH_SOCK); 546 ng_detach_common(pcbp, NG_CONTROL); 547 return (error); 548 } 549 550 /* Link the node and the private data. */ 551 NG_NODE_SET_PRIVATE(priv->node, priv); 552 NG_NODE_REF(priv->node); 553 priv->refs++; 554 555 return (0); 556 } 557 558 static int 559 ng_attach_data(struct socket *so) 560 { 561 return (ng_attach_common(so, NG_DATA)); 562 } 563 564 /* 565 * Set up a socket protocol control block. 566 * This code is shared between control and data sockets. 567 */ 568 static int 569 ng_attach_common(struct socket *so, int type) 570 { 571 struct ngpcb *pcbp; 572 int error; 573 574 /* Standard socket setup stuff. */ 575 error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace); 576 if (error) 577 return (error); 578 579 /* Allocate the pcb. */ 580 pcbp = malloc(sizeof(struct ngpcb), M_PCB, M_WAITOK | M_ZERO); 581 pcbp->type = type; 582 583 /* Link the pcb and the socket. */ 584 so->so_pcb = (caddr_t)pcbp; 585 pcbp->ng_socket = so; 586 587 return (0); 588 } 589 590 /* 591 * Disassociate the socket from it's protocol specific 592 * partner. If it's attached to a node's private data structure, 593 * then unlink from that too. If we were the last socket attached to it, 594 * then shut down the entire node. Shared code for control and data sockets. 595 */ 596 static void 597 ng_detach_common(struct ngpcb *pcbp, int which) 598 { 599 struct ngsock *priv = pcbp->sockdata; 600 601 if (priv != NULL) { 602 mtx_lock(&priv->mtx); 603 604 switch (which) { 605 case NG_CONTROL: 606 priv->ctlsock = NULL; 607 break; 608 case NG_DATA: 609 priv->datasock = NULL; 610 break; 611 default: 612 panic(__func__); 613 } 614 pcbp->sockdata = NULL; 615 616 ng_socket_free_priv(priv); 617 } 618 619 pcbp->ng_socket->so_pcb = NULL; 620 free(pcbp, M_PCB); 621 } 622 623 /* 624 * Remove a reference from node private data. 625 */ 626 static void 627 ng_socket_free_priv(struct ngsock *priv) 628 { 629 mtx_assert(&priv->mtx, MA_OWNED); 630 631 priv->refs--; 632 633 if (priv->refs == 0) { 634 mtx_destroy(&priv->mtx); 635 free(priv, M_NETGRAPH_SOCK); 636 return; 637 } 638 639 if ((priv->refs == 1) && (priv->node != NULL)) { 640 node_p node = priv->node; 641 642 priv->node = NULL; 643 mtx_unlock(&priv->mtx); 644 NG_NODE_UNREF(node); 645 ng_rmnode_self(node); 646 } else 647 mtx_unlock(&priv->mtx); 648 } 649 650 #ifdef NOTYET 651 /* 652 * File descriptors can be passed into an AF_NETGRAPH socket. 653 * Note, that file descriptors cannot be passed OUT. 654 * Only character device descriptors are accepted. 655 * Character devices are useful to connect a graph to a device, 656 * which after all is the purpose of this whole system. 657 */ 658 static int 659 ng_internalize(struct mbuf *control, struct thread *td) 660 { 661 const struct cmsghdr *cm = mtod(control, const struct cmsghdr *); 662 struct file *fp; 663 struct vnode *vn; 664 int oldfds; 665 int fd; 666 667 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || 668 cm->cmsg_len != control->m_len) { 669 TRAP_ERROR; 670 return (EINVAL); 671 } 672 673 /* Check there is only one FD. XXX what would more than one signify? */ 674 oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int); 675 if (oldfds != 1) { 676 TRAP_ERROR; 677 return (EINVAL); 678 } 679 680 /* Check that the FD given is legit. and change it to a pointer to a 681 * struct file. */ 682 fd = CMSG_DATA(cm); 683 if ((error = fget(td, fd, &fp)) != 0) 684 return (error); 685 686 /* Depending on what kind of resource it is, act differently. For 687 * devices, we treat it as a file. For an AF_NETGRAPH socket, 688 * shortcut straight to the node. */ 689 switch (fp->f_type) { 690 case DTYPE_VNODE: 691 vn = fp->f_data; 692 if (vn && (vn->v_type == VCHR)) { 693 /* for a VCHR, actually reference the FILE */ 694 fhold(fp); 695 /* XXX then what :) */ 696 /* how to pass on to other modules? */ 697 } else { 698 fdrop(fp, td); 699 TRAP_ERROR; 700 return (EINVAL); 701 } 702 break; 703 default: 704 fdrop(fp, td); 705 TRAP_ERROR; 706 return (EINVAL); 707 } 708 fdrop(fp, td); 709 return (0); 710 } 711 #endif /* NOTYET */ 712 713 /* 714 * Connect the data socket to a named control socket node. 715 */ 716 static int 717 ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp) 718 { 719 struct sockaddr_ng *sap; 720 node_p farnode; 721 struct ngsock *priv; 722 int error; 723 item_p item; 724 725 /* If we are already connected, don't do it again. */ 726 if (pcbp->sockdata != NULL) 727 return (EISCONN); 728 729 /* 730 * Find the target (victim) and check it doesn't already have 731 * a data socket. Also check it is a 'socket' type node. 732 * Use ng_package_data() and ng_address_path() to do this. 733 */ 734 735 sap = (struct sockaddr_ng *) nam; 736 /* The item will hold the node reference. */ 737 item = ng_package_data(NULL, NG_WAITOK); 738 739 if ((error = ng_address_path(NULL, item, sap->sg_data, 0))) 740 return (error); /* item is freed on failure */ 741 742 /* 743 * Extract node from item and free item. Remember we now have 744 * a reference on the node. The item holds it for us. 745 * when we free the item we release the reference. 746 */ 747 farnode = item->el_dest; /* shortcut */ 748 if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) { 749 NG_FREE_ITEM(item); /* drop the reference to the node */ 750 return (EINVAL); 751 } 752 priv = NG_NODE_PRIVATE(farnode); 753 if (priv->datasock != NULL) { 754 NG_FREE_ITEM(item); /* drop the reference to the node */ 755 return (EADDRINUSE); 756 } 757 758 /* 759 * Link the PCB and the private data struct. and note the extra 760 * reference. Drop the extra reference on the node. 761 */ 762 mtx_lock(&priv->mtx); 763 priv->datasock = pcbp; 764 pcbp->sockdata = priv; 765 priv->refs++; 766 mtx_unlock(&priv->mtx); 767 NG_FREE_ITEM(item); /* drop the reference to the node */ 768 return (0); 769 } 770 771 /* 772 * Binding a socket means giving the corresponding node a name 773 */ 774 static int 775 ng_bind(struct sockaddr *nam, struct ngpcb *pcbp) 776 { 777 struct ngsock *const priv = pcbp->sockdata; 778 struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam; 779 780 if (priv == NULL) { 781 TRAP_ERROR; 782 return (EINVAL); 783 } 784 if ((sap->sg_len < 4) || (sap->sg_len > (NG_NODESIZ + 2)) || 785 (sap->sg_data[0] == '\0') || 786 (sap->sg_data[sap->sg_len - 3] != '\0')) { 787 TRAP_ERROR; 788 return (EINVAL); 789 } 790 return (ng_name_node(priv->node, sap->sg_data)); 791 } 792 793 /*************************************************************** 794 Netgraph node 795 ***************************************************************/ 796 797 /* 798 * You can only create new nodes from the socket end of things. 799 */ 800 static int 801 ngs_constructor(node_p nodep) 802 { 803 return (EINVAL); 804 } 805 806 /* 807 * We allow any hook to be connected to the node. 808 * There is no per-hook private information though. 809 */ 810 static int 811 ngs_newhook(node_p node, hook_p hook, const char *name) 812 { 813 NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node)); 814 return (0); 815 } 816 817 /* 818 * If only one hook, allow read(2) and write(2) to work. 819 */ 820 static int 821 ngs_connect(hook_p hook) 822 { 823 node_p node = NG_HOOK_NODE(hook); 824 struct ngsock *priv = NG_NODE_PRIVATE(node); 825 826 if ((priv->datasock) && (priv->datasock->ng_socket)) { 827 if (NG_NODE_NUMHOOKS(node) == 1) 828 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED; 829 else 830 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED; 831 } 832 return (0); 833 } 834 835 /* 836 * Incoming messages get passed up to the control socket. 837 * Unless they are for us specifically (socket_type) 838 */ 839 static int 840 ngs_rcvmsg(node_p node, item_p item, hook_p lasthook) 841 { 842 struct ngsock *const priv = NG_NODE_PRIVATE(node); 843 struct ngpcb *const pcbp = priv->ctlsock; 844 struct socket *so; 845 struct sockaddr_ng addr; 846 struct ng_mesg *msg; 847 struct mbuf *m; 848 ng_ID_t retaddr = NGI_RETADDR(item); 849 int addrlen; 850 int error = 0; 851 852 NGI_GET_MSG(item, msg); 853 NG_FREE_ITEM(item); 854 855 /* 856 * Only allow mesgs to be passed if we have the control socket. 857 * Data sockets can only support the generic messages. 858 */ 859 if (pcbp == NULL) { 860 TRAP_ERROR; 861 NG_FREE_MSG(msg); 862 return (EINVAL); 863 } 864 so = pcbp->ng_socket; 865 866 #ifdef TRACE_MESSAGES 867 printf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n", 868 retaddr, 869 msg->header.typecookie, 870 msg->header.cmd, 871 msg->header.cmdstr, 872 msg->header.flags, 873 msg->header.token); 874 #endif 875 876 if (msg->header.typecookie == NGM_SOCKET_COOKIE) { 877 switch (msg->header.cmd) { 878 case NGM_SOCK_CMD_NOLINGER: 879 priv->flags |= NGS_FLAG_NOLINGER; 880 break; 881 case NGM_SOCK_CMD_LINGER: 882 priv->flags &= ~NGS_FLAG_NOLINGER; 883 break; 884 default: 885 error = EINVAL; /* unknown command */ 886 } 887 /* Free the message and return. */ 888 NG_FREE_MSG(msg); 889 return (error); 890 } 891 892 /* Get the return address into a sockaddr. */ 893 bzero(&addr, sizeof(addr)); 894 addr.sg_len = sizeof(addr); 895 addr.sg_family = AF_NETGRAPH; 896 addrlen = snprintf((char *)&addr.sg_data, sizeof(addr.sg_data), 897 "[%x]:", retaddr); 898 if (addrlen < 0 || addrlen > sizeof(addr.sg_data)) { 899 printf("%s: snprintf([%x]) failed - %d\n", __func__, retaddr, 900 addrlen); 901 NG_FREE_MSG(msg); 902 return (EINVAL); 903 } 904 905 /* Copy the message itself into an mbuf chain. */ 906 m = m_devget((caddr_t)msg, sizeof(struct ng_mesg) + msg->header.arglen, 907 0, NULL, NULL); 908 909 /* 910 * Here we free the message. We need to do that 911 * regardless of whether we got mbufs. 912 */ 913 NG_FREE_MSG(msg); 914 915 if (m == NULL) { 916 TRAP_ERROR; 917 return (ENOBUFS); 918 } 919 920 /* Send it up to the socket. */ 921 if (sbappendaddr(&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) { 922 TRAP_ERROR; 923 m_freem(m); 924 return (ENOBUFS); 925 } 926 sorwakeup(so); 927 928 return (error); 929 } 930 931 /* 932 * Receive data on a hook 933 */ 934 static int 935 ngs_rcvdata(hook_p hook, item_p item) 936 { 937 struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 938 struct ngpcb *const pcbp = priv->datasock; 939 struct socket *so; 940 struct sockaddr_ng *addr; 941 char *addrbuf[NG_HOOKSIZ + 4]; 942 int addrlen; 943 struct mbuf *m; 944 945 NGI_GET_M(item, m); 946 NG_FREE_ITEM(item); 947 948 /* If there is no data socket, black-hole it. */ 949 if (pcbp == NULL) { 950 NG_FREE_M(m); 951 return (0); 952 } 953 so = pcbp->ng_socket; 954 955 /* Get the return address into a sockaddr. */ 956 addrlen = strlen(NG_HOOK_NAME(hook)); /* <= NG_HOOKSIZ - 1 */ 957 addr = (struct sockaddr_ng *) addrbuf; 958 addr->sg_len = addrlen + 3; 959 addr->sg_family = AF_NETGRAPH; 960 bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen); 961 addr->sg_data[addrlen] = '\0'; 962 963 /* Try to tell the socket which hook it came in on. */ 964 if (sbappendaddr(&so->so_rcv, (struct sockaddr *)addr, m, NULL) == 0) { 965 m_freem(m); 966 TRAP_ERROR; 967 return (ENOBUFS); 968 } 969 sorwakeup(so); 970 return (0); 971 } 972 973 /* 974 * Hook disconnection 975 * 976 * For this type, removal of the last link destroys the node 977 * if the NOLINGER flag is set. 978 */ 979 static int 980 ngs_disconnect(hook_p hook) 981 { 982 node_p node = NG_HOOK_NODE(hook); 983 struct ngsock *const priv = NG_NODE_PRIVATE(node); 984 985 if ((priv->datasock) && (priv->datasock->ng_socket)) { 986 if (NG_NODE_NUMHOOKS(node) == 1) 987 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED; 988 else 989 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED; 990 } 991 992 if ((priv->flags & NGS_FLAG_NOLINGER) && 993 (NG_NODE_NUMHOOKS(node) == 0) && (NG_NODE_IS_VALID(node))) 994 ng_rmnode_self(node); 995 996 return (0); 997 } 998 999 /* 1000 * Do local shutdown processing. 1001 * In this case, that involves making sure the socket 1002 * knows we should be shutting down. 1003 */ 1004 static int 1005 ngs_shutdown(node_p node) 1006 { 1007 struct ngsock *const priv = NG_NODE_PRIVATE(node); 1008 struct ngpcb *const dpcbp = priv->datasock; 1009 struct ngpcb *const pcbp = priv->ctlsock; 1010 1011 if (dpcbp != NULL) 1012 soisdisconnected(dpcbp->ng_socket); 1013 1014 if (pcbp != NULL) 1015 soisdisconnected(pcbp->ng_socket); 1016 1017 mtx_lock(&priv->mtx); 1018 priv->node = NULL; 1019 NG_NODE_SET_PRIVATE(node, NULL); 1020 ng_socket_free_priv(priv); 1021 1022 NG_NODE_UNREF(node); 1023 return (0); 1024 } 1025 1026 static void 1027 ng_socket_item_applied(void *context, int error) 1028 { 1029 struct ngsock *const priv = (struct ngsock *)context; 1030 1031 mtx_lock(&priv->mtx); 1032 priv->error = error; 1033 wakeup(priv); 1034 mtx_unlock(&priv->mtx); 1035 1036 } 1037 1038 static int 1039 dummy_disconnect(struct socket *so) 1040 { 1041 return (0); 1042 } 1043 /* 1044 * Control and data socket type descriptors 1045 * 1046 * XXXRW: Perhaps _close should do something? 1047 */ 1048 1049 static struct pr_usrreqs ngc_usrreqs = { 1050 .pru_abort = NULL, 1051 .pru_attach = ngc_attach, 1052 .pru_bind = ngc_bind, 1053 .pru_connect = ngc_connect, 1054 .pru_detach = ngc_detach, 1055 .pru_disconnect = dummy_disconnect, 1056 .pru_peeraddr = NULL, 1057 .pru_send = ngc_send, 1058 .pru_shutdown = NULL, 1059 .pru_sockaddr = ng_getsockaddr, 1060 .pru_close = NULL, 1061 }; 1062 1063 static struct pr_usrreqs ngd_usrreqs = { 1064 .pru_abort = NULL, 1065 .pru_attach = ngd_attach, 1066 .pru_bind = NULL, 1067 .pru_connect = ngd_connect, 1068 .pru_detach = ngd_detach, 1069 .pru_disconnect = dummy_disconnect, 1070 .pru_peeraddr = NULL, 1071 .pru_send = ngd_send, 1072 .pru_shutdown = NULL, 1073 .pru_sockaddr = ng_getsockaddr, 1074 .pru_close = NULL, 1075 }; 1076 1077 /* 1078 * Definitions of protocols supported in the NETGRAPH domain. 1079 */ 1080 1081 extern struct domain ngdomain; /* stop compiler warnings */ 1082 1083 static struct protosw ngsw[] = { 1084 { 1085 .pr_type = SOCK_DGRAM, 1086 .pr_domain = &ngdomain, 1087 .pr_protocol = NG_CONTROL, 1088 .pr_flags = PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */, 1089 .pr_usrreqs = &ngc_usrreqs 1090 }, 1091 { 1092 .pr_type = SOCK_DGRAM, 1093 .pr_domain = &ngdomain, 1094 .pr_protocol = NG_DATA, 1095 .pr_flags = PR_ATOMIC | PR_ADDR, 1096 .pr_usrreqs = &ngd_usrreqs 1097 } 1098 }; 1099 1100 struct domain ngdomain = { 1101 .dom_family = AF_NETGRAPH, 1102 .dom_name = "netgraph", 1103 .dom_protosw = ngsw, 1104 .dom_protoswNPROTOSW = &ngsw[sizeof(ngsw) / sizeof(ngsw[0])] 1105 }; 1106 1107 /* 1108 * Handle loading and unloading for this node type. 1109 * This is to handle auxiliary linkages (e.g protocol domain addition). 1110 */ 1111 static int 1112 ngs_mod_event(module_t mod, int event, void *data) 1113 { 1114 int error = 0; 1115 1116 switch (event) { 1117 case MOD_LOAD: 1118 break; 1119 case MOD_UNLOAD: 1120 #ifdef NOTYET 1121 /* Unregister protocol domain XXX can't do this yet.. */ 1122 #endif 1123 error = EBUSY; 1124 break; 1125 default: 1126 error = EOPNOTSUPP; 1127 break; 1128 } 1129 return (error); 1130 } 1131 1132 VNET_DOMAIN_SET(ng); 1133 1134 SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, ""); 1135 SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA"); 1136 SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, ""); 1137 SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL"); 1138 SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, ""); 1139 1140