1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2002 Mark Santcroos <marks@ripe.net> 5 * Copyright (c) 2004-2005 Gleb Smirnoff <glebius@FreeBSD.org> 6 * Copyright (c) 2025 Quentin Thébault <quentin.thebault@defenso.fr> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Netgraph "device" node 29 * 30 * This node presents a /dev/ngd%d device that interfaces to an other 31 * netgraph node. 32 * 33 */ 34 35 #if 0 36 #define DBG do { printf("ng_device: %s\n", __func__); } while (0) 37 #else 38 #define DBG do {} while (0) 39 #endif 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/conf.h> 44 #include <sys/epoch.h> 45 #include <sys/fcntl.h> 46 #include <sys/filio.h> 47 #include <sys/ioccom.h> 48 #include <sys/kernel.h> 49 #include <sys/malloc.h> 50 #include <sys/mbuf.h> 51 #include <sys/poll.h> 52 #include <sys/proc.h> 53 #include <sys/queue.h> 54 #include <sys/selinfo.h> 55 #include <sys/socket.h> 56 #include <sys/syslog.h> 57 #include <sys/uio.h> 58 59 #include <net/ethernet.h> 60 #include <net/if.h> 61 #include <net/if_var.h> 62 #include <netinet/in.h> 63 #include <netinet/in_systm.h> 64 #include <netinet/ip.h> 65 66 #include <netgraph/ng_message.h> 67 #include <netgraph/netgraph.h> 68 #include <netgraph/ng_device.h> 69 #include <netgraph/ng_parse.h> 70 71 #define ERROUT(x) do { error = (x); goto done; } while (0) 72 73 /* Netgraph methods */ 74 static int ng_device_mod_event(module_t, int, void *); 75 static ng_constructor_t ng_device_constructor; 76 static ng_rcvmsg_t ng_device_rcvmsg; 77 static ng_shutdown_t ng_device_shutdown; 78 static ng_newhook_t ng_device_newhook; 79 static ng_rcvdata_t ng_device_rcvdata; 80 static ng_disconnect_t ng_device_disconnect; 81 82 /* List of commands and how to convert arguments to/from ASCII. */ 83 static const struct ng_cmdlist ng_device_cmds[] = { 84 { 85 NGM_DEVICE_COOKIE, 86 NGM_DEVICE_GET_DEVNAME, 87 "getdevname", 88 NULL, 89 &ng_parse_string_type 90 }, 91 { 92 NGM_DEVICE_COOKIE, 93 NGM_DEVICE_ETHERALIGN, 94 "etheralign", 95 NULL, 96 NULL 97 }, 98 { 0 } 99 }; 100 101 /* Netgraph type */ 102 static struct ng_type ngd_typestruct = { 103 .version = NG_ABI_VERSION, 104 .name = NG_DEVICE_NODE_TYPE, 105 .mod_event = ng_device_mod_event, 106 .constructor = ng_device_constructor, 107 .rcvmsg = ng_device_rcvmsg, 108 .shutdown = ng_device_shutdown, 109 .newhook = ng_device_newhook, 110 .rcvdata = ng_device_rcvdata, 111 .disconnect = ng_device_disconnect, 112 .cmdlist = ng_device_cmds, 113 }; 114 NETGRAPH_INIT(device, &ngd_typestruct); 115 116 /* per node data */ 117 struct ngd_private { 118 struct ifqueue readq; 119 struct ng_node *node; 120 struct ng_hook *hook; 121 struct cdev *ngddev; 122 struct selinfo rsel; 123 struct selinfo wsel; 124 struct mtx ngd_mtx; 125 int unit; 126 int ether_align; 127 uint16_t flags; 128 #define NGDF_OPEN 0x0001 129 #define NGDF_RWAIT 0x0002 130 #define NGDF_DYING 0x0004 131 }; 132 typedef struct ngd_private *priv_p; 133 134 /* unit number allocator entity */ 135 static struct unrhdr *ngd_unit; 136 137 /* Maximum number of NGD devices */ 138 #define MAX_NGD 999 139 140 static d_close_t ngdclose; 141 static d_open_t ngdopen; 142 static d_read_t ngdread; 143 static d_write_t ngdwrite; 144 static d_ioctl_t ngdioctl; 145 static d_poll_t ngdpoll; 146 static d_kqfilter_t ngdkqfilter; 147 148 static int ngd_kqread_event(struct knote *, long); 149 static int ngd_kqwrite_event(struct knote *, long); 150 static void ngd_kqread_detach(struct knote *); 151 static void ngd_kqwrite_detach(struct knote *); 152 153 static const struct filterops ngd_read_filterops = { 154 .f_isfd = 1, 155 .f_detach = ngd_kqread_detach, 156 .f_event = ngd_kqread_event 157 }; 158 159 static const struct filterops ngd_write_filterops = { 160 .f_isfd = 1, 161 .f_detach = ngd_kqwrite_detach, 162 .f_event = ngd_kqwrite_event 163 }; 164 165 static struct cdevsw ngd_cdevsw = { 166 .d_version = D_VERSION, 167 .d_open = ngdopen, 168 .d_close = ngdclose, 169 .d_read = ngdread, 170 .d_write = ngdwrite, 171 .d_ioctl = ngdioctl, 172 .d_kqfilter = ngdkqfilter, 173 .d_poll = ngdpoll, 174 .d_name = NG_DEVICE_DEVNAME, 175 }; 176 177 /* 178 ***************************************************************************** 179 * Netgraph methods 180 ***************************************************************************** 181 */ 182 183 /* 184 * Handle loading and unloading for this node type. 185 */ 186 static int 187 ng_device_mod_event(module_t mod, int event, void *data) 188 { 189 int error = 0; 190 191 switch (event) { 192 case MOD_LOAD: 193 ngd_unit = new_unrhdr(0, MAX_NGD, NULL); 194 break; 195 case MOD_UNLOAD: 196 delete_unrhdr(ngd_unit); 197 break; 198 default: 199 error = EOPNOTSUPP; 200 break; 201 } 202 return (error); 203 } 204 205 /* 206 * create new node 207 */ 208 static int 209 ng_device_constructor(node_p node) 210 { 211 priv_p priv; 212 213 DBG; 214 215 priv = malloc(sizeof(*priv), M_NETGRAPH, M_WAITOK | M_ZERO); 216 217 /* Allocate unit number */ 218 priv->unit = alloc_unr(ngd_unit); 219 220 /* Initialize mutexes and queue */ 221 mtx_init(&priv->ngd_mtx, "ng_device", NULL, MTX_DEF); 222 mtx_init(&priv->readq.ifq_mtx, "ng_device queue", NULL, MTX_DEF); 223 IFQ_SET_MAXLEN(&priv->readq, ifqmaxlen); 224 225 knlist_init_mtx(&priv->rsel.si_note, &priv->ngd_mtx); 226 knlist_init_mtx(&priv->wsel.si_note, &priv->ngd_mtx); 227 228 /* Link everything together */ 229 NG_NODE_SET_PRIVATE(node, priv); 230 priv->node = node; 231 232 priv->ngddev = make_dev(&ngd_cdevsw, priv->unit, UID_ROOT, 233 GID_WHEEL, 0600, NG_DEVICE_DEVNAME "%d", priv->unit); 234 if (priv->ngddev == NULL) { 235 printf("%s(): make_dev() failed\n", __func__); 236 knlist_destroy(&priv->rsel.si_note); 237 knlist_destroy(&priv->wsel.si_note); 238 mtx_destroy(&priv->ngd_mtx); 239 mtx_destroy(&priv->readq.ifq_mtx); 240 free_unr(ngd_unit, priv->unit); 241 free(priv, M_NETGRAPH); 242 return (EINVAL); 243 } 244 /* XXX: race here? */ 245 priv->ngddev->si_drv1 = priv; 246 247 /* Give this node the same name as the device (if possible). */ 248 if (ng_name_node(node, devtoname(priv->ngddev)) != 0) 249 log(LOG_WARNING, "%s: can't acquire netgraph name\n", 250 devtoname(priv->ngddev)); 251 252 return (0); 253 } 254 255 /* 256 * Process control message. 257 */ 258 259 static int 260 ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook) 261 { 262 const priv_p priv = NG_NODE_PRIVATE(node); 263 struct ng_mesg *msg; 264 struct ng_mesg *resp = NULL; 265 const char *dn; 266 int error = 0; 267 268 NGI_GET_MSG(item, msg); 269 270 if (msg->header.typecookie == NGM_DEVICE_COOKIE) { 271 switch (msg->header.cmd) { 272 case NGM_DEVICE_GET_DEVNAME: 273 /* XXX: Fix when MAX_NGD us bigger */ 274 NG_MKRESPONSE(resp, msg, 275 strlen(NG_DEVICE_DEVNAME) + 4, M_NOWAIT); 276 277 if (resp == NULL) 278 ERROUT(ENOMEM); 279 280 dn = devtoname(priv->ngddev); 281 strlcpy((char *)resp->data, dn, strlen(dn) + 1); 282 break; 283 284 case NGM_DEVICE_ETHERALIGN: 285 /* Use ETHER_ALIGN on arches that require it. */ 286 #ifndef __NO_STRICT_ALIGNMENT 287 priv->ether_align = ETHER_ALIGN; 288 #endif 289 break; 290 291 default: 292 error = EINVAL; 293 break; 294 } 295 } else 296 error = EINVAL; 297 298 done: 299 NG_RESPOND_MSG(error, node, item, resp); 300 NG_FREE_MSG(msg); 301 return (error); 302 } 303 304 /* 305 * Accept incoming hook. We support only one hook per node. 306 */ 307 static int 308 ng_device_newhook(node_p node, hook_p hook, const char *name) 309 { 310 priv_p priv = NG_NODE_PRIVATE(node); 311 312 DBG; 313 314 /* We have only one hook per node */ 315 if (priv->hook != NULL) 316 return (EISCONN); 317 318 priv->hook = hook; 319 320 return (0); 321 } 322 323 /* 324 * Receive data from hook, write it to device. 325 */ 326 static int 327 ng_device_rcvdata(hook_p hook, item_p item) 328 { 329 priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 330 struct mbuf *m; 331 332 DBG; 333 334 NGI_GET_M(item, m); 335 NG_FREE_ITEM(item); 336 337 IF_LOCK(&priv->readq); 338 if (_IF_QFULL(&priv->readq)) { 339 IF_UNLOCK(&priv->readq); 340 NG_FREE_M(m); 341 return (ENOBUFS); 342 } 343 344 _IF_ENQUEUE(&priv->readq, m); 345 IF_UNLOCK(&priv->readq); 346 mtx_lock(&priv->ngd_mtx); 347 if (priv->flags & NGDF_RWAIT) { 348 priv->flags &= ~NGDF_RWAIT; 349 wakeup(priv); 350 } 351 selwakeup(&priv->rsel); 352 KNOTE_LOCKED(&priv->rsel.si_note, 0); 353 mtx_unlock(&priv->ngd_mtx); 354 355 return (0); 356 } 357 358 /* 359 * Removal of the hook destroys the node. 360 */ 361 static int 362 ng_device_disconnect(hook_p hook) 363 { 364 priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 365 366 DBG; 367 368 mtx_lock(&priv->ngd_mtx); 369 priv->flags |= NGDF_DYING; 370 wakeup(priv); 371 mtx_unlock(&priv->ngd_mtx); 372 373 destroy_dev(priv->ngddev); 374 375 knlist_clear(&priv->rsel.si_note, 0); 376 knlist_clear(&priv->wsel.si_note, 0); 377 knlist_destroy(&priv->rsel.si_note); 378 knlist_destroy(&priv->wsel.si_note); 379 mtx_destroy(&priv->ngd_mtx); 380 381 seldrain(&priv->rsel); 382 seldrain(&priv->wsel); 383 384 IF_DRAIN(&priv->readq); 385 mtx_destroy(&(priv)->readq.ifq_mtx); 386 387 free_unr(ngd_unit, priv->unit); 388 389 free(priv, M_NETGRAPH); 390 391 ng_rmnode_self(NG_HOOK_NODE(hook)); 392 393 return (0); 394 } 395 396 /* 397 * Node shutdown. Everything is already done in disconnect method. 398 */ 399 static int 400 ng_device_shutdown(node_p node) 401 { 402 NG_NODE_UNREF(node); 403 return (0); 404 } 405 406 /* 407 ***************************************************************************** 408 * Device methods 409 ***************************************************************************** 410 */ 411 412 /* 413 * the device is opened 414 */ 415 static int 416 ngdopen(struct cdev *dev, int flag, int mode, struct thread *td) 417 { 418 priv_p priv = (priv_p)dev->si_drv1; 419 420 DBG; 421 422 mtx_lock(&priv->ngd_mtx); 423 priv->flags |= NGDF_OPEN; 424 mtx_unlock(&priv->ngd_mtx); 425 426 return (0); 427 } 428 429 /* 430 * the device is closed 431 */ 432 static int 433 ngdclose(struct cdev *dev, int flag, int mode, struct thread *td) 434 { 435 priv_p priv = (priv_p)dev->si_drv1; 436 437 DBG; 438 mtx_lock(&priv->ngd_mtx); 439 priv->flags &= ~NGDF_OPEN; 440 mtx_unlock(&priv->ngd_mtx); 441 442 return (0); 443 } 444 445 /* 446 * Process IOCTLs 447 * 448 * At this stage we only return success on FIONBIO to allow setting the device 449 * as non-blocking. 450 * 451 */ 452 static int 453 ngdioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, 454 struct thread *td) 455 { 456 int error; 457 458 switch (cmd) { 459 case FIONBIO: 460 error = 0; 461 break; 462 case FIOASYNC: 463 if (*(int *)data != 0) 464 error = EINVAL; 465 else 466 error = 0; 467 break; 468 default: 469 error = ENOTTY; 470 } 471 472 return (error); 473 } 474 475 #if 0 /* 476 * The ioctl is transformed into netgraph control message. 477 * We do not process them, yet. 478 */ 479 /* 480 * process ioctl 481 * 482 * they are translated into netgraph messages and passed on 483 * 484 */ 485 static int 486 ngdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, 487 struct thread *td) 488 { 489 struct ngd_softc *sc = &ngd_softc; 490 struct ngd_connection *connection = NULL; 491 struct ngd_connection *tmp; 492 int error = 0; 493 struct ng_mesg *msg; 494 struct ngd_param_s *datap; 495 496 DBG; 497 498 NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s), 499 M_NOWAIT); 500 if (msg == NULL) { 501 printf("%s(): msg == NULL\n", __func__); 502 goto nomsg; 503 } 504 505 /* pass the ioctl data into the ->data area */ 506 datap = (struct ngd_param_s *)msg->data; 507 datap->p = addr; 508 509 NG_SEND_MSG_HOOK(error, sc->node, msg, connection->active_hook, 0); 510 if (error) 511 printf("%s(): NG_SEND_MSG_HOOK error: %d\n", __func__, error); 512 513 nomsg: 514 515 return (0); 516 } 517 #endif /* if 0 */ 518 519 /* 520 * This function is called when a read(2) is done to our device. 521 * We process one mbuf from queue. 522 */ 523 static int 524 ngdread(struct cdev *dev, struct uio *uio, int flag) 525 { 526 priv_p priv = (priv_p)dev->si_drv1; 527 struct mbuf *m; 528 int len, error = 0; 529 530 DBG; 531 532 /* get an mbuf */ 533 do { 534 IF_DEQUEUE(&priv->readq, m); 535 if (m == NULL) { 536 if (flag & O_NONBLOCK) 537 return (EWOULDBLOCK); 538 mtx_lock(&priv->ngd_mtx); 539 priv->flags |= NGDF_RWAIT; 540 if (priv->flags & NGDF_DYING) { 541 mtx_unlock(&priv->ngd_mtx); 542 error = ENXIO; 543 } else 544 error = mtx_sleep(priv, &priv->ngd_mtx, 545 PDROP | PCATCH, "ngdread", 0); 546 if (error != 0) 547 return (error); 548 } 549 } while (m == NULL); 550 551 while (m && uio->uio_resid > 0 && error == 0) { 552 len = MIN(uio->uio_resid, m->m_len); 553 if (len != 0) 554 error = uiomove(mtod(m, void *), len, uio); 555 m = m_free(m); 556 } 557 558 if (m) 559 m_freem(m); 560 561 return (error); 562 } 563 564 /* 565 * This function is called when our device is written to. 566 * We read the data from userland into mbuf chain and pass it to the remote 567 * hook. 568 */ 569 static int 570 ngdwrite(struct cdev *dev, struct uio *uio, int flag) 571 { 572 struct epoch_tracker et; 573 priv_p priv = (priv_p)dev->si_drv1; 574 struct mbuf *m; 575 int error = 0; 576 577 DBG; 578 579 if (uio->uio_resid == 0) 580 return (0); 581 582 if (uio->uio_resid < 0 || uio->uio_resid > IP_MAXPACKET) 583 return (EIO); 584 585 m = m_uiotombuf(uio, M_NOWAIT, 0, priv->ether_align, M_PKTHDR); 586 if (m == NULL) 587 return (ENOBUFS); 588 589 /* Setting VNET is required if connecting to a ng_bridge. */ 590 CURVNET_SET(priv->node->nd_vnet); 591 NET_EPOCH_ENTER(et); 592 NG_SEND_DATA_ONLY(error, priv->hook, m); 593 NET_EPOCH_EXIT(et); 594 CURVNET_RESTORE(); 595 596 return (error); 597 } 598 599 /* 600 * we are being polled/selected 601 * check if there is data available for read 602 */ 603 static int 604 ngdpoll(struct cdev *dev, int events, struct thread *td) 605 { 606 priv_p priv = (priv_p)dev->si_drv1; 607 int revents = 0; 608 609 if (events & (POLLIN | POLLRDNORM) && 610 !IFQ_IS_EMPTY(&priv->readq)) 611 revents |= events & (POLLIN | POLLRDNORM); 612 613 return (revents); 614 } 615 616 static void 617 ngd_kqread_detach(struct knote *kn) 618 { 619 priv_p priv = (priv_p)kn->kn_hook; 620 621 knlist_remove(&priv->rsel.si_note, kn, 0); 622 } 623 624 static int 625 ngd_kqread_event(struct knote *kn, long hint) 626 { 627 priv_p priv = (priv_p)kn->kn_hook; 628 struct mbuf *m; 629 630 IFQ_LOCK(&priv->readq); 631 if (IFQ_IS_EMPTY(&priv->readq)) { 632 kn->kn_data = 0; 633 } else { 634 /* 635 * Since the queue does not store the total number of bytes that 636 * could be read across all packets and we do not want to 637 * traverse the whole queue, we only report the number of bytes 638 * for the first packet in the queue. 639 */ 640 IF_POLL(&priv->readq, m); 641 kn->kn_data = m->m_len; 642 } 643 IFQ_UNLOCK(&priv->readq); 644 645 return (kn->kn_data > 0); 646 } 647 648 static void 649 ngd_kqwrite_detach(struct knote *kn) 650 { 651 priv_p priv = (priv_p)kn->kn_hook; 652 653 knlist_remove(&priv->wsel.si_note, kn, 0); 654 } 655 656 static int 657 ngd_kqwrite_event(struct knote *kn, long hint) 658 { 659 kn->kn_data = IP_MAXPACKET; 660 661 return (1); 662 } 663 664 static int 665 ngdkqfilter(struct cdev *dev, struct knote *kn) 666 { 667 priv_p priv = (priv_p)dev->si_drv1; 668 669 switch (kn->kn_filter) { 670 case EVFILT_READ: 671 kn->kn_fop = &ngd_read_filterops; 672 kn->kn_hook = priv; 673 knlist_add(&priv->rsel.si_note, kn, 0); 674 return (0); 675 case EVFILT_WRITE: 676 kn->kn_fop = &ngd_write_filterops; 677 kn->kn_hook = priv; 678 knlist_add(&priv->wsel.si_note, kn, 0); 679 return (0); 680 default: 681 return (EINVAL); 682 } 683 } 684