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/errno.h> 55 #include <sys/kdb.h> 56 #include <sys/kernel.h> 57 #include <sys/linker.h> 58 #include <sys/lock.h> 59 #include <sys/malloc.h> 60 #include <sys/mbuf.h> 61 #include <sys/mutex.h> 62 #include <sys/protosw.h> 63 #include <sys/queue.h> 64 #include <sys/signalvar.h> 65 #include <sys/socket.h> 66 #include <sys/socketvar.h> 67 #include <sys/sx.h> 68 #include <sys/sysctl.h> 69 #include <sys/systm.h> 70 #ifdef NOTYET 71 #include <sys/vnode.h> 72 #endif 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 int ng_internalize(struct mbuf *m, struct thread *p); */ 127 128 static int ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp); 129 static int ng_bind(struct sockaddr *nam, struct ngpcb *pcbp); 130 131 static int ngs_mod_event(module_t mod, int event, void *data); 132 static int ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, 133 struct sockaddr_ng *addr); 134 135 /* Netgraph type descriptor */ 136 static struct ng_type typestruct = { 137 .version = NG_ABI_VERSION, 138 .name = NG_SOCKET_NODE_TYPE, 139 .mod_event = ngs_mod_event, 140 .constructor = ngs_constructor, 141 .rcvmsg = ngs_rcvmsg, 142 .shutdown = ngs_shutdown, 143 .newhook = ngs_newhook, 144 .connect = ngs_connect, 145 .rcvdata = ngs_rcvdata, 146 .disconnect = ngs_disconnect, 147 }; 148 NETGRAPH_INIT_ORDERED(socket, &typestruct, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); 149 150 /* Buffer space */ 151 static u_long ngpdg_sendspace = 20 * 1024; /* really max datagram size */ 152 SYSCTL_INT(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW, 153 &ngpdg_sendspace , 0, "Maximum outgoing Netgraph datagram size"); 154 static u_long ngpdg_recvspace = 20 * 1024; 155 SYSCTL_INT(_net_graph, OID_AUTO, recvspace, CTLFLAG_RW, 156 &ngpdg_recvspace , 0, "Maximum space for incoming Netgraph datagrams"); 157 158 /* List of all sockets */ 159 static LIST_HEAD(, ngpcb) ngsocklist; 160 161 static struct mtx ngsocketlist_mtx; 162 MTX_SYSINIT(ngsocketlist, &ngsocketlist_mtx, "ng_socketlist", MTX_DEF); 163 164 #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb) 165 166 /* If getting unexplained errors returned, set this to "kdb_enter("X"); */ 167 #ifndef TRAP_ERROR 168 #define TRAP_ERROR 169 #endif 170 171 /*************************************************************** 172 Control sockets 173 ***************************************************************/ 174 175 static int 176 ngc_attach(struct socket *so, int proto, struct thread *td) 177 { 178 struct ngpcb *const pcbp = sotongpcb(so); 179 180 if (suser(td)) 181 return (EPERM); 182 if (pcbp != NULL) 183 return (EISCONN); 184 return (ng_attach_cntl(so)); 185 } 186 187 static int 188 ngc_detach(struct socket *so) 189 { 190 struct ngpcb *const pcbp = sotongpcb(so); 191 192 if (pcbp == NULL) 193 return (EINVAL); 194 ng_detach_common(pcbp, NG_CONTROL); 195 return (0); 196 } 197 198 static int 199 ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 200 struct mbuf *control, struct thread *td) 201 { 202 struct ngpcb *const pcbp = sotongpcb(so); 203 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; 204 struct ng_mesg *msg; 205 struct mbuf *m0; 206 char *path = NULL; 207 int len, error = 0; 208 209 if (pcbp == NULL) { 210 error = EINVAL; 211 goto release; 212 } 213 #ifdef NOTYET 214 if (control && (error = ng_internalize(control, td))) { 215 if (pcbp->sockdata == NULL) { 216 error = ENOTCONN; 217 goto release; 218 } 219 } 220 #else /* NOTYET */ 221 if (control) { 222 error = EINVAL; 223 goto release; 224 } 225 #endif /* NOTYET */ 226 227 /* Require destination as there may be >= 1 hooks on this node */ 228 if (addr == NULL) { 229 error = EDESTADDRREQ; 230 goto release; 231 } 232 233 /* Allocate an expendable buffer for the path, chop off 234 * the sockaddr header, and make sure it's NUL terminated */ 235 len = sap->sg_len - 2; 236 MALLOC(path, char *, len + 1, M_NETGRAPH_PATH, M_WAITOK); 237 if (path == NULL) { 238 error = ENOMEM; 239 goto release; 240 } 241 bcopy(sap->sg_data, path, len); 242 path[len] = '\0'; 243 244 /* Move the actual message out of mbufs into a linear buffer. 245 * Start by adding up the size of the data. (could use mh_len?) */ 246 for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next) 247 len += m0->m_len; 248 249 /* Move the data into a linear buffer as well. Messages are not 250 * delivered in mbufs. */ 251 MALLOC(msg, struct ng_mesg *, len + 1, M_NETGRAPH_MSG, M_WAITOK); 252 if (msg == NULL) { 253 error = ENOMEM; 254 goto release; 255 } 256 m_copydata(m, 0, len, (char *)msg); 257 258 #ifdef TRACE_MESSAGES 259 do { 260 item_p item; 261 if ((item = ng_package_msg(msg)) == NULL) { 262 (msg) = NULL; 263 (error) = ENOMEM; 264 printf("err=%d\n",error); 265 break; 266 } 267 if (((error) = ng_address_path((pcbp->sockdata->node), (item), 268 (path), (NULL))) == 0) { 269 printf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n", 270 item->el_dest->nd_ID, 271 msg->header.typecookie, 272 msg->header.cmd, 273 msg->header.cmdstr, 274 msg->header.flags, 275 msg->header.token, 276 item->el_dest->nd_type->name); 277 SAVE_LINE(item); 278 (error) = ng_snd_item((item), 0); 279 } 280 else { 281 printf("errx=%d\n",error); 282 } 283 (msg) = NULL; 284 } while (0); 285 286 #else 287 /* 288 * Hack alert! 289 * We look into the message and if it mkpeers a node of unknown type, we 290 * try to load it. We need to do this now, in syscall thread, because if 291 * message gets queued and applied later we will get panic. 292 */ 293 if (msg->header.typecookie == NGM_GENERIC_COOKIE && 294 msg->header.cmd == NGM_MKPEER) { 295 struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data; 296 struct ng_type *type; 297 298 if ((type = ng_findtype(mkp->type)) == NULL) { 299 char filename[NG_TYPESIZ + 3]; 300 linker_file_t lf; 301 int error; 302 303 /* Not found, try to load it as a loadable module */ 304 snprintf(filename, sizeof(filename), "ng_%s", mkp->type); 305 mtx_lock(&Giant); 306 error = linker_load_module(NULL, filename, NULL, NULL, &lf); 307 mtx_unlock(&Giant); 308 if (error != 0) { 309 FREE(msg, M_NETGRAPH_MSG); 310 goto release; 311 } 312 lf->userrefs++; 313 314 /* Try again, as now the type should have linked itself in */ 315 if ((type = ng_findtype(mkp->type)) == NULL) { 316 FREE(msg, M_NETGRAPH_MSG); 317 error = ENXIO; 318 goto release; 319 } 320 } 321 } 322 323 /* The callee will free the msg when done. The path is our business. */ 324 NG_SEND_MSG_PATH(error, pcbp->sockdata->node, msg, path, 0); 325 #endif 326 release: 327 if (path != NULL) 328 FREE(path, M_NETGRAPH_PATH); 329 if (control != NULL) 330 m_freem(control); 331 if (m != NULL) 332 m_freem(m); 333 return (error); 334 } 335 336 static int 337 ngc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 338 { 339 struct ngpcb *const pcbp = sotongpcb(so); 340 341 if (pcbp == 0) 342 return (EINVAL); 343 return (ng_bind(nam, pcbp)); 344 } 345 346 static int 347 ngc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 348 { 349 printf(" program tried to connect control socket to remote node\n "); 350 /* 351 * At this time refuse to do this.. it used to 352 * do something but it was undocumented and not used. 353 */ 354 return (EINVAL); 355 } 356 357 /*************************************************************** 358 Data sockets 359 ***************************************************************/ 360 361 static int 362 ngd_attach(struct socket *so, int proto, struct thread *td) 363 { 364 struct ngpcb *const pcbp = sotongpcb(so); 365 366 if (pcbp != NULL) 367 return (EISCONN); 368 return (ng_attach_data(so)); 369 } 370 371 static int 372 ngd_detach(struct socket *so) 373 { 374 struct ngpcb *const pcbp = sotongpcb(so); 375 376 if (pcbp == NULL) 377 return (EINVAL); 378 ng_detach_common(pcbp, NG_DATA); 379 return (0); 380 } 381 382 static int 383 ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, 384 struct mbuf *control, struct thread *td) 385 { 386 struct ngpcb *const pcbp = sotongpcb(so); 387 struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr; 388 int len, error; 389 hook_p hook = NULL; 390 char hookname[NG_HOOKSIZ]; 391 392 if ((pcbp == NULL) || (control != NULL)) { 393 error = EINVAL; 394 goto release; 395 } 396 if (pcbp->sockdata == NULL) { 397 error = ENOTCONN; 398 goto release; 399 } 400 /* 401 * If the user used any of these ways to not specify an address 402 * then handle specially. 403 */ 404 if ((sap == NULL) 405 || ((len = sap->sg_len - 2) <= 0) 406 || (*sap->sg_data == '\0')) { 407 if (NG_NODE_NUMHOOKS(pcbp->sockdata->node) != 1) { 408 error = EDESTADDRREQ; 409 goto release; 410 } 411 /* 412 * if exactly one hook exists, just use it. 413 * Special case to allow write(2) to work on an ng_socket. 414 */ 415 hook = LIST_FIRST(&pcbp->sockdata->node->nd_hooks); 416 } else { 417 if (len >= NG_HOOKSIZ) { 418 error = EINVAL; 419 goto release; 420 } 421 422 /* 423 * chop off the sockaddr header, and make sure it's NUL 424 * terminated 425 */ 426 bcopy(sap->sg_data, hookname, len); 427 hookname[len] = '\0'; 428 429 /* Find the correct hook from 'hookname' */ 430 LIST_FOREACH(hook, &pcbp->sockdata->node->nd_hooks, hk_hooks) { 431 if (strcmp(hookname, NG_HOOK_NAME(hook)) == 0) { 432 break; 433 } 434 } 435 if (hook == NULL) { 436 error = EHOSTUNREACH; 437 } 438 } 439 440 /* Send data (OK if hook is NULL) */ 441 NG_SEND_DATA_ONLY(error, hook, m); /* makes m NULL */ 442 443 release: 444 if (control != NULL) 445 m_freem(control); 446 if (m != NULL) 447 m_freem(m); 448 return (error); 449 } 450 451 static int 452 ngd_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 453 { 454 struct ngpcb *const pcbp = sotongpcb(so); 455 456 if (pcbp == 0) 457 return (EINVAL); 458 return (ng_connect_data(nam, pcbp)); 459 } 460 461 /* 462 * Used for both data and control sockets 463 */ 464 static int 465 ng_setsockaddr(struct socket *so, struct sockaddr **addr) 466 { 467 struct ngpcb *pcbp; 468 struct sockaddr_ng *sg; 469 int sg_len, namelen, s; 470 471 /* Why isn't sg_data a `char[1]' ? :-( */ 472 sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1; 473 474 s = splnet(); 475 pcbp = sotongpcb(so); 476 if ((pcbp == NULL) || (pcbp->sockdata == NULL)) { 477 splx(s); 478 return (EINVAL); 479 } 480 481 namelen = 0; /* silence compiler ! */ 482 if ( NG_NODE_HAS_NAME(pcbp->sockdata->node)) 483 sg_len += namelen = strlen(NG_NODE_NAME(pcbp->sockdata->node)); 484 485 MALLOC(sg, struct sockaddr_ng *, sg_len, M_SONAME, M_WAITOK | M_ZERO); 486 487 if (NG_NODE_HAS_NAME(pcbp->sockdata->node)) 488 bcopy(NG_NODE_NAME(pcbp->sockdata->node), sg->sg_data, namelen); 489 splx(s); 490 491 sg->sg_len = sg_len; 492 sg->sg_family = AF_NETGRAPH; 493 *addr = (struct sockaddr *)sg; 494 495 return (0); 496 } 497 498 /* 499 * Attach a socket to it's protocol specific partner. 500 * For a control socket, actually create a netgraph node and attach 501 * to it as well. 502 */ 503 504 static int 505 ng_attach_cntl(struct socket *so) 506 { 507 struct ngsock *privdata; 508 struct ngpcb *pcbp; 509 int error; 510 511 /* Setup protocol control block */ 512 if ((error = ng_attach_common(so, NG_CONTROL)) != 0) 513 return (error); 514 pcbp = sotongpcb(so); 515 516 /* Allocate node private info */ 517 MALLOC(privdata, struct ngsock *, 518 sizeof(*privdata), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO); 519 if (privdata == NULL) { 520 ng_detach_common(pcbp, NG_CONTROL); 521 return (ENOMEM); 522 } 523 524 /* Make the generic node components */ 525 if ((error = ng_make_node_common(&typestruct, &privdata->node)) != 0) { 526 FREE(privdata, M_NETGRAPH_SOCK); 527 ng_detach_common(pcbp, NG_CONTROL); 528 return (error); 529 } 530 NG_NODE_SET_PRIVATE(privdata->node, privdata); 531 532 /* Link the pcb and the node private data */ 533 privdata->ctlsock = pcbp; 534 pcbp->sockdata = privdata; 535 privdata->refs++; 536 return (0); 537 } 538 539 static int 540 ng_attach_data(struct socket *so) 541 { 542 return(ng_attach_common(so, NG_DATA)); 543 } 544 545 /* 546 * Set up a socket protocol control block. 547 * This code is shared between control and data sockets. 548 */ 549 static int 550 ng_attach_common(struct socket *so, int type) 551 { 552 struct ngpcb *pcbp; 553 int error; 554 555 /* Standard socket setup stuff */ 556 error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace); 557 if (error) 558 return (error); 559 560 /* Allocate the pcb */ 561 MALLOC(pcbp, struct ngpcb *, sizeof(*pcbp), M_PCB, M_WAITOK | M_ZERO); 562 if (pcbp == NULL) 563 return (ENOMEM); 564 pcbp->type = type; 565 566 /* Link the pcb and the socket */ 567 so->so_pcb = (caddr_t) pcbp; 568 pcbp->ng_socket = so; 569 570 /* Add the socket to linked list */ 571 mtx_lock(&ngsocketlist_mtx); 572 LIST_INSERT_HEAD(&ngsocklist, pcbp, socks); 573 mtx_unlock(&ngsocketlist_mtx); 574 return (0); 575 } 576 577 /* 578 * Disassociate the socket from it's protocol specific 579 * partner. If it's attached to a node's private data structure, 580 * then unlink from that too. If we were the last socket attached to it, 581 * then shut down the entire node. Shared code for control and data sockets. 582 */ 583 static void 584 ng_detach_common(struct ngpcb *pcbp, int which) 585 { 586 struct ngsock *priv; 587 588 if (pcbp->sockdata) { 589 priv = pcbp->sockdata; 590 pcbp->sockdata = NULL; 591 switch (which) { 592 case NG_CONTROL: 593 priv->ctlsock = NULL; 594 break; 595 case NG_DATA: 596 priv->datasock = NULL; 597 break; 598 default: 599 panic(__func__); 600 } 601 if ((--priv->refs == 0) && (priv->node != NULL)) 602 ng_rmnode_self(priv->node); 603 } 604 pcbp->ng_socket->so_pcb = NULL; 605 pcbp->ng_socket = NULL; 606 mtx_lock(&ngsocketlist_mtx); 607 LIST_REMOVE(pcbp, socks); 608 mtx_unlock(&ngsocketlist_mtx); 609 FREE(pcbp, M_PCB); 610 } 611 612 #ifdef NOTYET 613 /* 614 * File descriptors can be passed into an AF_NETGRAPH socket. 615 * Note, that file descriptors cannot be passed OUT. 616 * Only character device descriptors are accepted. 617 * Character devices are useful to connect a graph to a device, 618 * which after all is the purpose of this whole system. 619 */ 620 static int 621 ng_internalize(struct mbuf *control, struct thread *td) 622 { 623 const struct cmsghdr *cm = mtod(control, const struct cmsghdr *); 624 struct file *fp; 625 struct vnode *vn; 626 int oldfds; 627 int fd; 628 629 if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET || 630 cm->cmsg_len != control->m_len) { 631 TRAP_ERROR; 632 return (EINVAL); 633 } 634 635 /* Check there is only one FD. XXX what would more than one signify? */ 636 oldfds = ((caddr_t)cm + cm->cmsg_len - (caddr_t)data) / sizeof (int); 637 if (oldfds != 1) { 638 TRAP_ERROR; 639 return (EINVAL); 640 } 641 642 /* Check that the FD given is legit. and change it to a pointer to a 643 * struct file. */ 644 fd = CMSG_DATA(cm); 645 if ((error = fget(td, fd, &fp)) != 0) 646 return (error); 647 648 /* Depending on what kind of resource it is, act differently. For 649 * devices, we treat it as a file. For an AF_NETGRAPH socket, 650 * shortcut straight to the node. */ 651 switch (fp->f_type) { 652 case DTYPE_VNODE: 653 vn = fp->f_data; 654 if (vn && (vn->v_type == VCHR)) { 655 /* for a VCHR, actually reference the FILE */ 656 fp->f_count++; 657 /* XXX then what :) */ 658 /* how to pass on to other modules? */ 659 } else { 660 fdrop(fp, td); 661 TRAP_ERROR; 662 return (EINVAL); 663 } 664 break; 665 default: 666 fdrop(fp, td); 667 TRAP_ERROR; 668 return (EINVAL); 669 } 670 fdrop(fp, td); 671 return (0); 672 } 673 #endif /* NOTYET */ 674 675 /* 676 * Connect the data socket to a named control socket node. 677 */ 678 static int 679 ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp) 680 { 681 struct sockaddr_ng *sap; 682 node_p farnode; 683 struct ngsock *priv; 684 int error; 685 item_p item; 686 687 /* If we are already connected, don't do it again */ 688 if (pcbp->sockdata != NULL) 689 return (EISCONN); 690 691 /* Find the target (victim) and check it doesn't already have a data 692 * socket. Also check it is a 'socket' type node. 693 * Use ng_package_data() and address_path() to do this. 694 */ 695 696 sap = (struct sockaddr_ng *) nam; 697 /* The item will hold the node reference */ 698 item = ng_package_data(NULL, NULL); 699 if (item == NULL) { 700 return (ENOMEM); 701 } 702 if ((error = ng_address_path(NULL, item, sap->sg_data, 0))) 703 return (error); /* item is freed on failure */ 704 705 /* 706 * Extract node from item and free item. Remember we now have 707 * a reference on the node. The item holds it for us. 708 * when we free the item we release the reference. 709 */ 710 farnode = item->el_dest; /* shortcut */ 711 if (strcmp(farnode->nd_type->name, NG_SOCKET_NODE_TYPE) != 0) { 712 NG_FREE_ITEM(item); /* drop the reference to the node */ 713 return (EINVAL); 714 } 715 priv = NG_NODE_PRIVATE(farnode); 716 if (priv->datasock != NULL) { 717 NG_FREE_ITEM(item); /* drop the reference to the node */ 718 return (EADDRINUSE); 719 } 720 721 /* 722 * Link the PCB and the private data struct. and note the extra 723 * reference. Drop the extra reference on the node. 724 */ 725 priv->datasock = pcbp; 726 pcbp->sockdata = priv; 727 priv->refs++; /* XXX possible race if it's being freed */ 728 NG_FREE_ITEM(item); /* drop the reference to the node */ 729 return (0); 730 } 731 732 /* 733 * Binding a socket means giving the corresponding node a name 734 */ 735 static int 736 ng_bind(struct sockaddr *nam, struct ngpcb *pcbp) 737 { 738 struct ngsock *const priv = pcbp->sockdata; 739 struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam; 740 741 if (priv == NULL) { 742 TRAP_ERROR; 743 return (EINVAL); 744 } 745 if ((sap->sg_len < 4) 746 || (sap->sg_len > (NG_NODESIZ + 2)) 747 || (sap->sg_data[0] == '\0') 748 || (sap->sg_data[sap->sg_len - 3] != '\0')) { 749 TRAP_ERROR; 750 return (EINVAL); 751 } 752 return (ng_name_node(priv->node, sap->sg_data)); 753 } 754 755 /* 756 * Take a message and pass it up to the control socket associated 757 * with the node. 758 */ 759 static int 760 ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr) 761 { 762 struct socket *const so = pcbp->ng_socket; 763 struct mbuf *mdata; 764 int msglen; 765 766 /* Copy the message itself into an mbuf chain */ 767 msglen = sizeof(struct ng_mesg) + msg->header.arglen; 768 mdata = m_devget((caddr_t) msg, msglen, 0, NULL, NULL); 769 770 /* Here we free the message, as we are the end of the line. 771 * We need to do that regardless of whether we got mbufs. */ 772 NG_FREE_MSG(msg); 773 774 if (mdata == NULL) { 775 TRAP_ERROR; 776 return (ENOBUFS); 777 } 778 779 /* Send it up to the socket */ 780 if (sbappendaddr(&so->so_rcv, 781 (struct sockaddr *) addr, mdata, NULL) == 0) { 782 TRAP_ERROR; 783 m_freem(mdata); 784 return (ENOBUFS); 785 } 786 sorwakeup(so); 787 return (0); 788 } 789 790 /* 791 * You can only create new nodes from the socket end of things. 792 */ 793 static int 794 ngs_constructor(node_p nodep) 795 { 796 return (EINVAL); 797 } 798 799 /* 800 * We allow any hook to be connected to the node. 801 * There is no per-hook private information though. 802 */ 803 static int 804 ngs_newhook(node_p node, hook_p hook, const char *name) 805 { 806 NG_HOOK_SET_PRIVATE(hook, NG_NODE_PRIVATE(node)); 807 return (0); 808 } 809 810 /* 811 * if only one hook, allow read(2) and write(2) to work. 812 */ 813 static int 814 ngs_connect(hook_p hook) 815 { 816 node_p node = NG_HOOK_NODE(hook); 817 struct ngsock *priv = NG_NODE_PRIVATE(node); 818 819 if ((priv->datasock) 820 && (priv->datasock->ng_socket)) { 821 if (NG_NODE_NUMHOOKS(node) == 1) { 822 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED; 823 } else { 824 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED; 825 } 826 } 827 return (0); 828 } 829 830 /* 831 * Incoming messages get passed up to the control socket. 832 * Unless they are for us specifically (socket_type) 833 */ 834 static int 835 ngs_rcvmsg(node_p node, item_p item, hook_p lasthook) 836 { 837 struct ngsock *const priv = NG_NODE_PRIVATE(node); 838 struct ngpcb *const pcbp = priv->ctlsock; 839 struct sockaddr_ng *addr; 840 int addrlen; 841 int error = 0; 842 struct ng_mesg *msg; 843 ng_ID_t retaddr = NGI_RETADDR(item); 844 char retabuf[32]; 845 846 NGI_GET_MSG(item, msg); 847 NG_FREE_ITEM(item); /* we have all we need */ 848 849 /* Only allow mesgs to be passed if we have the control socket. 850 * Data sockets can only support the generic messages. */ 851 if (pcbp == NULL) { 852 TRAP_ERROR; 853 return (EINVAL); 854 } 855 #ifdef TRACE_MESSAGES 856 printf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n", 857 retaddr, 858 msg->header.typecookie, 859 msg->header.cmd, 860 msg->header.cmdstr, 861 msg->header.flags, 862 msg->header.token); 863 864 #endif 865 866 if (msg->header.typecookie == NGM_SOCKET_COOKIE) { 867 switch (msg->header.cmd) { 868 case NGM_SOCK_CMD_NOLINGER: 869 priv->flags |= NGS_FLAG_NOLINGER; 870 break; 871 case NGM_SOCK_CMD_LINGER: 872 priv->flags &= ~NGS_FLAG_NOLINGER; 873 break; 874 default: 875 error = EINVAL; /* unknown command */ 876 } 877 /* Free the message and return */ 878 NG_FREE_MSG(msg); 879 return(error); 880 881 } 882 /* Get the return address into a sockaddr */ 883 sprintf(retabuf,"[%x]:", retaddr); 884 addrlen = strlen(retabuf); 885 MALLOC(addr, struct sockaddr_ng *, addrlen + 4, M_NETGRAPH_PATH, M_NOWAIT); 886 if (addr == NULL) { 887 TRAP_ERROR; 888 return (ENOMEM); 889 } 890 addr->sg_len = addrlen + 3; 891 addr->sg_family = AF_NETGRAPH; 892 bcopy(retabuf, addr->sg_data, addrlen); 893 addr->sg_data[addrlen] = '\0'; 894 895 /* Send it up */ 896 error = ship_msg(pcbp, msg, addr); 897 FREE(addr, M_NETGRAPH_PATH); 898 return (error); 899 } 900 901 /* 902 * Receive data on a hook 903 */ 904 static int 905 ngs_rcvdata(hook_p hook, item_p item) 906 { 907 struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 908 struct ngpcb *const pcbp = priv->datasock; 909 struct socket *so; 910 struct sockaddr_ng *addr; 911 char *addrbuf[NG_HOOKSIZ + 4]; 912 int addrlen; 913 struct mbuf *m; 914 915 NGI_GET_M(item, m); 916 NG_FREE_ITEM(item); 917 /* If there is no data socket, black-hole it */ 918 if (pcbp == NULL) { 919 NG_FREE_M(m); 920 return (0); 921 } 922 so = pcbp->ng_socket; 923 924 /* Get the return address into a sockaddr. */ 925 addrlen = strlen(NG_HOOK_NAME(hook)); /* <= NG_HOOKSIZ - 1 */ 926 addr = (struct sockaddr_ng *) addrbuf; 927 addr->sg_len = addrlen + 3; 928 addr->sg_family = AF_NETGRAPH; 929 bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen); 930 addr->sg_data[addrlen] = '\0'; 931 932 /* Try to tell the socket which hook it came in on */ 933 if (sbappendaddr(&so->so_rcv, (struct sockaddr *) addr, m, NULL) == 0) { 934 m_freem(m); 935 TRAP_ERROR; 936 return (ENOBUFS); 937 } 938 sorwakeup(so); 939 return (0); 940 } 941 942 /* 943 * Hook disconnection 944 * 945 * For this type, removal of the last link destroys the node 946 * if the NOLINGER flag is set. 947 */ 948 static int 949 ngs_disconnect(hook_p hook) 950 { 951 node_p node = NG_HOOK_NODE(hook); 952 struct ngsock *const priv = NG_NODE_PRIVATE(node); 953 954 if ((priv->datasock) 955 && (priv->datasock->ng_socket)) { 956 if (NG_NODE_NUMHOOKS(node) == 1) { 957 priv->datasock->ng_socket->so_state |= SS_ISCONNECTED; 958 } else { 959 priv->datasock->ng_socket->so_state &= ~SS_ISCONNECTED; 960 } 961 } 962 963 if ((priv->flags & NGS_FLAG_NOLINGER ) 964 && (NG_NODE_NUMHOOKS(node) == 0) 965 && (NG_NODE_IS_VALID(node))) { 966 ng_rmnode_self(node); 967 } 968 return (0); 969 } 970 971 /* 972 * Do local shutdown processing. 973 * In this case, that involves making sure the socket 974 * knows we should be shutting down. 975 */ 976 static int 977 ngs_shutdown(node_p node) 978 { 979 struct ngsock *const priv = NG_NODE_PRIVATE(node); 980 struct ngpcb *const dpcbp = priv->datasock; 981 struct ngpcb *const pcbp = priv->ctlsock; 982 983 if (dpcbp != NULL) { 984 soisdisconnected(dpcbp->ng_socket); 985 dpcbp->sockdata = NULL; 986 priv->datasock = NULL; 987 priv->refs--; 988 } 989 if (pcbp != NULL) { 990 soisdisconnected(pcbp->ng_socket); 991 pcbp->sockdata = NULL; 992 priv->ctlsock = NULL; 993 priv->refs--; 994 } 995 NG_NODE_SET_PRIVATE(node, NULL); 996 NG_NODE_UNREF(node); 997 FREE(priv, M_NETGRAPH_SOCK); 998 return (0); 999 } 1000 1001 static int 1002 dummy_disconnect(struct socket *so) 1003 { 1004 return (0); 1005 } 1006 /* 1007 * Control and data socket type descriptors 1008 */ 1009 1010 static struct pr_usrreqs ngc_usrreqs = { 1011 .pru_abort = NULL, 1012 .pru_attach = ngc_attach, 1013 .pru_bind = ngc_bind, 1014 .pru_connect = ngc_connect, 1015 .pru_detach = ngc_detach, 1016 .pru_disconnect = dummy_disconnect, 1017 .pru_peeraddr = NULL, 1018 .pru_send = ngc_send, 1019 .pru_shutdown = NULL, 1020 .pru_sockaddr = ng_setsockaddr, 1021 }; 1022 1023 static struct pr_usrreqs ngd_usrreqs = { 1024 .pru_abort = NULL, 1025 .pru_attach = ngd_attach, 1026 .pru_bind = NULL, 1027 .pru_connect = ngd_connect, 1028 .pru_detach = ngd_detach, 1029 .pru_disconnect = dummy_disconnect, 1030 .pru_peeraddr = NULL, 1031 .pru_send = ngd_send, 1032 .pru_shutdown = NULL, 1033 .pru_sockaddr ng_setsockaddr, 1034 }; 1035 1036 /* 1037 * Definitions of protocols supported in the NETGRAPH domain. 1038 */ 1039 1040 extern struct domain ngdomain; /* stop compiler warnings */ 1041 1042 static struct protosw ngsw[] = { 1043 { 1044 SOCK_DGRAM, /* protocol type */ 1045 &ngdomain, /* backpointer to domain */ 1046 NG_CONTROL, 1047 PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */, /* flags */ 1048 0, 0, 0, 0, /* input, output, ctlinput, ctloutput */ 1049 NULL, /* ousrreq */ 1050 0, 0, 0, 0, /* init, fasttimeo, slowtimo, drain */ 1051 &ngc_usrreqs, /* usrreq table (above) */ 1052 /*{NULL}*/ /* pffh (protocol filter head?) */ 1053 }, 1054 { 1055 SOCK_DGRAM, /* protocol type */ 1056 &ngdomain, /* backpointer to domain */ 1057 NG_DATA, 1058 PR_ATOMIC | PR_ADDR, /* flags */ 1059 0, 0, 0, 0, /* input, output, ctlinput, ctloutput */ 1060 NULL, /* ousrreq() */ 1061 0, 0, 0, 0, /* init, fasttimeo, slowtimo, drain */ 1062 &ngd_usrreqs, /* usrreq table (above) */ 1063 /*{NULL}*/ /* pffh (protocol filter head?) */ 1064 } 1065 }; 1066 1067 struct domain ngdomain = { 1068 AF_NETGRAPH, 1069 "netgraph", 1070 NULL, /* init() */ 1071 NULL, /* externalise() */ 1072 NULL, /* dispose() */ 1073 ngsw, /* protosw entry */ 1074 &ngsw[sizeof(ngsw) / sizeof(ngsw[0])], /* Number of protosw entries */ 1075 NULL, /* next domain in list */ 1076 NULL, /* rtattach() */ 1077 0, /* arg to rtattach in bits */ 1078 0 /* maxrtkey */ 1079 }; 1080 1081 /* 1082 * Handle loading and unloading for this node type 1083 * This is to handle auxiliary linkages (e.g protocol domain addition). 1084 */ 1085 static int 1086 ngs_mod_event(module_t mod, int event, void *data) 1087 { 1088 int error = 0; 1089 1090 switch (event) { 1091 case MOD_LOAD: 1092 /* Register protocol domain */ 1093 net_add_domain(&ngdomain); 1094 break; 1095 case MOD_UNLOAD: 1096 /* Insure there are no open netgraph sockets */ 1097 if (!LIST_EMPTY(&ngsocklist)) { 1098 error = EBUSY; 1099 break; 1100 } 1101 1102 #ifdef NOTYET 1103 if ((LIST_EMPTY(&ngsocklist)) && (typestruct.refs == 0)) { 1104 /* Unregister protocol domain XXX can't do this yet.. */ 1105 if ((error = net_rm_domain(&ngdomain)) != 0) 1106 break; 1107 } else 1108 #endif 1109 error = EBUSY; 1110 break; 1111 default: 1112 error = EOPNOTSUPP; 1113 break; 1114 } 1115 return (error); 1116 } 1117 1118 SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, ""); 1119 SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA"); 1120 SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, ""); 1121 SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL"); 1122 SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, ""); 1123 1124