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