1a8353960SJulian Elischer /* 2a8353960SJulian Elischer * Copyright (c) 2002 Mark Santcroos <marks@ripe.net> 3a8353960SJulian Elischer * 4a8353960SJulian Elischer * Redistribution and use in source and binary forms, with or without 5a8353960SJulian Elischer * modification, are permitted provided that the following conditions 6a8353960SJulian Elischer * are met: 7a8353960SJulian Elischer * 1. Redistributions of source code must retain the above copyright 8a8353960SJulian Elischer * notice, this list of conditions and the following disclaimer. 9a8353960SJulian Elischer * 2. Redistributions in binary form must reproduce the above copyright 10a8353960SJulian Elischer * notice, this list of conditions and the following disclaimer in the 11a8353960SJulian Elischer * documentation and/or other materials provided with the distribution. 12a8353960SJulian Elischer * 3. The name of the author may not be used to endorse or promote products 13a8353960SJulian Elischer * derived from this software without specific prior written permission. 14a8353960SJulian Elischer * 15a8353960SJulian Elischer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16a8353960SJulian Elischer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17a8353960SJulian Elischer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18a8353960SJulian Elischer * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19a8353960SJulian Elischer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20a8353960SJulian Elischer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21a8353960SJulian Elischer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22a8353960SJulian Elischer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23a8353960SJulian Elischer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24a8353960SJulian Elischer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25a8353960SJulian Elischer * 26a8353960SJulian Elischer * Netgraph "device" node 27a8353960SJulian Elischer * 28a8353960SJulian Elischer * This node presents a /dev/ngd%d device that interfaces to an other 29a8353960SJulian Elischer * netgraph node. 30a8353960SJulian Elischer * 31a8353960SJulian Elischer * $FreeBSD$ 32a8353960SJulian Elischer * 33a8353960SJulian Elischer */ 34a8353960SJulian Elischer 35a8353960SJulian Elischer #include <sys/param.h> 36a8353960SJulian Elischer #include <sys/systm.h> 37a8353960SJulian Elischer #include <sys/kernel.h> 38a8353960SJulian Elischer #include <sys/mbuf.h> 39a8353960SJulian Elischer #include <sys/uio.h> 40a8353960SJulian Elischer #include <sys/queue.h> 41a8353960SJulian Elischer #include <sys/malloc.h> 42a8353960SJulian Elischer #include <sys/conf.h> 43a8353960SJulian Elischer #include <sys/poll.h> 44a8353960SJulian Elischer #include <sys/ioccom.h> 45a8353960SJulian Elischer 46a8353960SJulian Elischer #include <netgraph/ng_message.h> 47a8353960SJulian Elischer #include <netgraph/netgraph.h> 48a8353960SJulian Elischer 49a8353960SJulian Elischer #include "ng_device.h" 50a8353960SJulian Elischer 51a8353960SJulian Elischer /* turn this on for verbose messages */ 52a8353960SJulian Elischer #define NGD_DEBUG 53a8353960SJulian Elischer 54a8353960SJulian Elischer /* Netgraph methods */ 55a8353960SJulian Elischer static ng_constructor_t ng_device_cons; 56a8353960SJulian Elischer static ng_rcvmsg_t ng_device_rcvmsg; 57a8353960SJulian Elischer static ng_newhook_t ng_device_newhook; 58a8353960SJulian Elischer static ng_connect_t ng_device_connect; 59a8353960SJulian Elischer static ng_rcvdata_t ng_device_rcvdata; 60a8353960SJulian Elischer static ng_disconnect_t ng_device_disconnect; 61a8353960SJulian Elischer static int ng_device_mod_event(module_t mod, int event, void *data); 62a8353960SJulian Elischer 63a8353960SJulian Elischer static int ng_device_init(void); 64a8353960SJulian Elischer static int get_free_unit(void); 65a8353960SJulian Elischer 66a8353960SJulian Elischer /* Netgraph type */ 67a8353960SJulian Elischer static struct ng_type typestruct = { 68f8aae777SJulian Elischer .version = NG_ABI_VERSION, 69f8aae777SJulian Elischer .name = NG_DEVICE_NODE_TYPE, 70f8aae777SJulian Elischer .mod_event = ng_device_mod_event, 71f8aae777SJulian Elischer .constructor = ng_device_cons, 72f8aae777SJulian Elischer .rcvmsg = ng_device_rcvmsg, 73f8aae777SJulian Elischer .newhook = ng_device_newhook, 74f8aae777SJulian Elischer .connect = ng_device_connect, 75f8aae777SJulian Elischer .rcvdata = ng_device_rcvdata, 76f8aae777SJulian Elischer .disconnect = ng_device_disconnect, 77a8353960SJulian Elischer }; 78a8353960SJulian Elischer NETGRAPH_INIT(device, &typestruct); 79a8353960SJulian Elischer 80a8353960SJulian Elischer /* per hook data */ 81a8353960SJulian Elischer struct ngd_connection { 82a8353960SJulian Elischer SLIST_ENTRY(ngd_connection) links; 83a8353960SJulian Elischer 84a8353960SJulian Elischer dev_t ngddev; 85a8353960SJulian Elischer struct ng_hook *active_hook; 86a8353960SJulian Elischer char *readq; 87a8353960SJulian Elischer int loc; 88a8353960SJulian Elischer int unit; 89a8353960SJulian Elischer }; 90a8353960SJulian Elischer 91a8353960SJulian Elischer /* global data */ 92a8353960SJulian Elischer struct ngd_softc { 93a8353960SJulian Elischer SLIST_HEAD(, ngd_connection) head; 94a8353960SJulian Elischer 95a8353960SJulian Elischer node_p node; 9687e2c66aSHartmut Brandt char nodename[NG_NODESIZ]; 97a8353960SJulian Elischer } ngd_softc; 98a8353960SJulian Elischer 99a8353960SJulian Elischer /* the per connection receiving queue maximum */ 100a8353960SJulian Elischer #define NGD_QUEUE_SIZE (1024*10) 101a8353960SJulian Elischer 102a8353960SJulian Elischer /* Maximum number of NGD devices */ 103a8353960SJulian Elischer #define MAX_NGD 25 /* should be more than enough for now */ 104a8353960SJulian Elischer 105a8353960SJulian Elischer static d_close_t ngdclose; 106a8353960SJulian Elischer static d_open_t ngdopen; 107a8353960SJulian Elischer static d_read_t ngdread; 108a8353960SJulian Elischer static d_write_t ngdwrite; 109a8353960SJulian Elischer static d_ioctl_t ngdioctl; 110a8353960SJulian Elischer static d_poll_t ngdpoll; 111a8353960SJulian Elischer 112a8353960SJulian Elischer static struct cdevsw ngd_cdevsw = { 113dc08ffecSPoul-Henning Kamp .d_version = D_VERSION, 114dc08ffecSPoul-Henning Kamp .d_flags = D_NEEDGIANT, 1157ac40f5fSPoul-Henning Kamp .d_open = ngdopen, 1167ac40f5fSPoul-Henning Kamp .d_close = ngdclose, 1177ac40f5fSPoul-Henning Kamp .d_read = ngdread, 1187ac40f5fSPoul-Henning Kamp .d_write = ngdwrite, 1197ac40f5fSPoul-Henning Kamp .d_ioctl = ngdioctl, 1207ac40f5fSPoul-Henning Kamp .d_poll = ngdpoll, 1217ac40f5fSPoul-Henning Kamp .d_name = "ngd", 122a8353960SJulian Elischer }; 123a8353960SJulian Elischer 124a8353960SJulian Elischer /* 125a8353960SJulian Elischer * this holds all the stuff that should be done at load time 126a8353960SJulian Elischer */ 127a8353960SJulian Elischer static int 128a8353960SJulian Elischer ng_device_mod_event(module_t mod, int event, void *data) 129a8353960SJulian Elischer { 130a8353960SJulian Elischer int error = 0; 131a8353960SJulian Elischer 132a8353960SJulian Elischer #ifdef NGD_DEBUG 133a8353960SJulian Elischer printf("%s()\n",__func__); 134a8353960SJulian Elischer #endif /* NGD_DEBUG */ 135a8353960SJulian Elischer 136a8353960SJulian Elischer switch (event) { 137a8353960SJulian Elischer case MOD_LOAD: 138a8353960SJulian Elischer 139a8353960SJulian Elischer ng_device_init(); 140a8353960SJulian Elischer break; 141a8353960SJulian Elischer 142a8353960SJulian Elischer case MOD_UNLOAD: 143a8353960SJulian Elischer /* XXX do we need to do something specific ? */ 144a8353960SJulian Elischer /* ng_device_breakdown */ 145a8353960SJulian Elischer break; 146a8353960SJulian Elischer 147a8353960SJulian Elischer default: 148a8353960SJulian Elischer error = EOPNOTSUPP; 149a8353960SJulian Elischer break; 150a8353960SJulian Elischer } 151a8353960SJulian Elischer 152a8353960SJulian Elischer return(error); 153a8353960SJulian Elischer } 154a8353960SJulian Elischer 155a8353960SJulian Elischer 156a8353960SJulian Elischer static int 157a8353960SJulian Elischer ng_device_init() 158a8353960SJulian Elischer { 159a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 160a8353960SJulian Elischer 161a8353960SJulian Elischer #ifdef NGD_DEBUG 162a8353960SJulian Elischer printf("%s()\n",__func__); 163a8353960SJulian Elischer #endif /* NGD_DEBUG */ 164a8353960SJulian Elischer 165a8353960SJulian Elischer SLIST_INIT(&sc->head); 166a8353960SJulian Elischer 167a8353960SJulian Elischer if (ng_make_node_common(&typestruct, &sc->node) != 0) { 168a8353960SJulian Elischer printf("%s(): ng_make_node_common failed\n",__func__); 169a8353960SJulian Elischer return(ENXIO); 170a8353960SJulian Elischer } 171a8353960SJulian Elischer sprintf(sc->nodename, "%s", NG_DEVICE_NODE_TYPE); 172a8353960SJulian Elischer if (ng_name_node(sc->node, sc->nodename)) { 173a8353960SJulian Elischer NG_NODE_UNREF(sc->node); /* make it go away again */ 174a8353960SJulian Elischer printf("%s(): ng_name_node failed\n",__func__); 175a8353960SJulian Elischer return(ENXIO); 176a8353960SJulian Elischer } 177a8353960SJulian Elischer NG_NODE_SET_PRIVATE(sc->node, sc); 178a8353960SJulian Elischer 179a8353960SJulian Elischer return(0); 180a8353960SJulian Elischer } 181a8353960SJulian Elischer 182a8353960SJulian Elischer /* 183a8353960SJulian Elischer * don't allow to be created, only the device can do that 184a8353960SJulian Elischer */ 185a8353960SJulian Elischer static int 186a8353960SJulian Elischer ng_device_cons(node_p node) 187a8353960SJulian Elischer { 188a8353960SJulian Elischer 189a8353960SJulian Elischer #ifdef NGD_DEBUG 190a8353960SJulian Elischer printf("%s()\n",__func__); 191a8353960SJulian Elischer #endif /* NGD_DEBUG */ 192a8353960SJulian Elischer 193a8353960SJulian Elischer return(EINVAL); 194a8353960SJulian Elischer } 195a8353960SJulian Elischer 196a8353960SJulian Elischer /* 197a8353960SJulian Elischer * Receive control message. We just bounce it back as a reply. 198a8353960SJulian Elischer */ 199a8353960SJulian Elischer static int 200a8353960SJulian Elischer ng_device_rcvmsg(node_p node, item_p item, hook_p lasthook) 201a8353960SJulian Elischer { 202a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 203a8353960SJulian Elischer struct ng_mesg *msg; 204a8353960SJulian Elischer int error = 0; 205a8353960SJulian Elischer struct ngd_connection * connection = NULL; 206a8353960SJulian Elischer struct ngd_connection *tmp = NULL; 207a8353960SJulian Elischer 208a8353960SJulian Elischer #ifdef NGD_DEBUG 209a8353960SJulian Elischer printf("%s()\n",__func__); 210a8353960SJulian Elischer #endif /* NGD_DEBUG */ 211a8353960SJulian Elischer 212a8353960SJulian Elischer NGI_GET_MSG(item, msg); 213a8353960SJulian Elischer 214a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 215a8353960SJulian Elischer if(tmp->active_hook == lasthook) { 216a8353960SJulian Elischer connection = tmp; 217a8353960SJulian Elischer } 218a8353960SJulian Elischer } 219a8353960SJulian Elischer if(connection == NULL) { 220a8353960SJulian Elischer printf("%s(): connection is still NULL, no hook found\n",__func__); 221a8353960SJulian Elischer return(-1); 222a8353960SJulian Elischer } 223a8353960SJulian Elischer 224a8353960SJulian Elischer return(error); 225a8353960SJulian Elischer } 226a8353960SJulian Elischer 227a8353960SJulian Elischer static int 228a8353960SJulian Elischer get_free_unit() 229a8353960SJulian Elischer { 230a8353960SJulian Elischer struct ngd_connection *tmp = NULL; 231a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 232a8353960SJulian Elischer int n = 0; 233a8353960SJulian Elischer int unit = -1; 234a8353960SJulian Elischer 235a8353960SJulian Elischer #ifdef NGD_DEBUG 236a8353960SJulian Elischer printf("%s()\n",__func__); 237a8353960SJulian Elischer #endif /* NGD_DEBUG */ 238a8353960SJulian Elischer 239a8353960SJulian Elischer /* When there is no list yet, the first device unit is always 0. */ 240a8353960SJulian Elischer if SLIST_EMPTY(&sc->head) { 241a8353960SJulian Elischer unit = 0; 242a8353960SJulian Elischer return(unit); 243a8353960SJulian Elischer } 244a8353960SJulian Elischer 245a8353960SJulian Elischer /* Just do a brute force loop to find the first free unit that is 246a8353960SJulian Elischer * smaller than MAX_NGD. 247a8353960SJulian Elischer * Set MAX_NGD to a large value, doesn't impact performance. 248a8353960SJulian Elischer */ 249a8353960SJulian Elischer for(n = 0;n<MAX_NGD && unit == -1;n++) { 250a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 251a8353960SJulian Elischer 252a8353960SJulian Elischer if(tmp->unit == n) { 253a8353960SJulian Elischer unit = -1; 254a8353960SJulian Elischer break; 255a8353960SJulian Elischer } 256a8353960SJulian Elischer unit = n; 257a8353960SJulian Elischer } 258a8353960SJulian Elischer } 259a8353960SJulian Elischer 260a8353960SJulian Elischer return(unit); 261a8353960SJulian Elischer } 262a8353960SJulian Elischer 263a8353960SJulian Elischer /* 264a8353960SJulian Elischer * incoming hook 265a8353960SJulian Elischer */ 266a8353960SJulian Elischer static int 267a8353960SJulian Elischer ng_device_newhook(node_p node, hook_p hook, const char *name) 268a8353960SJulian Elischer { 269a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 270a8353960SJulian Elischer struct ngd_connection * new_connection = NULL; 271a8353960SJulian Elischer 272a8353960SJulian Elischer #ifdef NGD_DEBUG 273a8353960SJulian Elischer printf("%s()\n",__func__); 274a8353960SJulian Elischer #endif /* NGD_DEBUG */ 275a8353960SJulian Elischer 276a8353960SJulian Elischer new_connection = malloc(sizeof(struct ngd_connection), M_DEVBUF, M_NOWAIT); 277a8353960SJulian Elischer if(new_connection == NULL) { 278a8353960SJulian Elischer printf("%s(): ERROR: new_connection == NULL\n",__func__); 279a8353960SJulian Elischer return(-1); 280a8353960SJulian Elischer } 281a8353960SJulian Elischer 282a8353960SJulian Elischer new_connection->unit = get_free_unit(); 283a8353960SJulian Elischer if(new_connection->unit<0) { 284a8353960SJulian Elischer printf("%s: No free unit found by get_free_unit(), " 285a8353960SJulian Elischer "increas MAX_NGD\n",__func__); 286a8353960SJulian Elischer return(-1); 287a8353960SJulian Elischer } 288a8353960SJulian Elischer new_connection->ngddev = make_dev(&ngd_cdevsw, new_connection->unit, 0, 0,0600,"ngd%d",new_connection->unit); 289a8353960SJulian Elischer if(new_connection->ngddev == NULL) { 290a8353960SJulian Elischer printf("%s(): make_dev failed\n",__func__); 291a8353960SJulian Elischer return(-1); 292a8353960SJulian Elischer } 293a8353960SJulian Elischer 294a8353960SJulian Elischer new_connection->readq = malloc(sizeof(char)*NGD_QUEUE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); 295a8353960SJulian Elischer if(new_connection->readq == NULL) { 296a8353960SJulian Elischer printf("%s(): readq malloc failed\n",__func__); 297a8353960SJulian Elischer return(-1); 298a8353960SJulian Elischer } 299a8353960SJulian Elischer 300a8353960SJulian Elischer /* point to begin of buffer */ 301a8353960SJulian Elischer new_connection->loc = 0; 302a8353960SJulian Elischer new_connection->active_hook = hook; 303a8353960SJulian Elischer 304a8353960SJulian Elischer SLIST_INSERT_HEAD(&sc->head, new_connection, links); 305a8353960SJulian Elischer 306a8353960SJulian Elischer return(0); 307a8353960SJulian Elischer } 308a8353960SJulian Elischer 309a8353960SJulian Elischer /* 310a8353960SJulian Elischer * we gave ok to a new hook 311a8353960SJulian Elischer * now connect 312a8353960SJulian Elischer */ 313a8353960SJulian Elischer static int 314a8353960SJulian Elischer ng_device_connect(hook_p hook) 315a8353960SJulian Elischer { 316a8353960SJulian Elischer 317a8353960SJulian Elischer #ifdef NGD_DEBUG 318a8353960SJulian Elischer printf("%s()\n",__func__); 319a8353960SJulian Elischer #endif /* NGD_DEBUG */ 320a8353960SJulian Elischer 321a8353960SJulian Elischer return(0); 322a8353960SJulian Elischer } 323a8353960SJulian Elischer 324a8353960SJulian Elischer 325a8353960SJulian Elischer /* 326a8353960SJulian Elischer * Receive data from hook 327a8353960SJulian Elischer */ 328a8353960SJulian Elischer static int 329a8353960SJulian Elischer ng_device_rcvdata(hook_p hook, item_p item) 330a8353960SJulian Elischer { 331a8353960SJulian Elischer struct mbuf *m; 332a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 333a8353960SJulian Elischer struct ngd_connection * connection = NULL; 334a8353960SJulian Elischer struct ngd_connection * tmp; 335a8353960SJulian Elischer char *buffer; 336a8353960SJulian Elischer 337a8353960SJulian Elischer #ifdef NGD_DEBUG 338a8353960SJulian Elischer printf("%s()\n",__func__); 339a8353960SJulian Elischer #endif /* NGD_DEBUG */ 340a8353960SJulian Elischer 341a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 342a8353960SJulian Elischer if(tmp->active_hook == hook) { 343a8353960SJulian Elischer connection = tmp; 344a8353960SJulian Elischer } 345a8353960SJulian Elischer } 346a8353960SJulian Elischer if(connection == NULL) { 347a8353960SJulian Elischer printf("%s(): connection is still NULL, no hook found\n",__func__); 348a8353960SJulian Elischer return(-1); 349a8353960SJulian Elischer } 350a8353960SJulian Elischer 351a8353960SJulian Elischer NGI_GET_M(item, m); 352a8353960SJulian Elischer NG_FREE_ITEM(item); 353a8353960SJulian Elischer 354a8353960SJulian Elischer m = m_pullup(m,m->m_len); 355a8353960SJulian Elischer if(m == NULL) { 356a8353960SJulian Elischer printf("%s(): ERROR: m_pullup failed\n",__func__); 357a8353960SJulian Elischer return(-1); 358a8353960SJulian Elischer } 359a8353960SJulian Elischer 360a8353960SJulian Elischer buffer = malloc(sizeof(char)*m->m_len, M_DEVBUF, M_NOWAIT | M_ZERO); 361a8353960SJulian Elischer if(buffer == NULL) { 362a8353960SJulian Elischer printf("%s(): ERROR: buffer malloc failed\n",__func__); 363a8353960SJulian Elischer return(-1); 364a8353960SJulian Elischer } 365a8353960SJulian Elischer 366a8353960SJulian Elischer buffer = mtod(m,char *); 367a8353960SJulian Elischer 368a8353960SJulian Elischer if( (connection->loc+m->m_len) < NGD_QUEUE_SIZE) { 369a8353960SJulian Elischer memcpy(connection->readq+connection->loc, buffer, m->m_len); 370a8353960SJulian Elischer connection->loc += m->m_len; 371a8353960SJulian Elischer } else 372a8353960SJulian Elischer printf("%s(): queue full, first read out a bit\n",__func__); 373a8353960SJulian Elischer 374a8353960SJulian Elischer free(buffer,M_DEVBUF); 375a8353960SJulian Elischer 376a8353960SJulian Elischer return(0); 377a8353960SJulian Elischer } 378a8353960SJulian Elischer 379a8353960SJulian Elischer /* 380a8353960SJulian Elischer * Removal of the last link destroys the node 381a8353960SJulian Elischer */ 382a8353960SJulian Elischer static int 383a8353960SJulian Elischer ng_device_disconnect(hook_p hook) 384a8353960SJulian Elischer { 385a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 386a8353960SJulian Elischer struct ngd_connection * connection = NULL; 387a8353960SJulian Elischer struct ngd_connection * tmp; 388a8353960SJulian Elischer 389a8353960SJulian Elischer #ifdef NGD_DEBUG 390a8353960SJulian Elischer printf("%s()\n",__func__); 391a8353960SJulian Elischer #endif /* NGD_DEBUG */ 392a8353960SJulian Elischer 393a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 394a8353960SJulian Elischer if(tmp->active_hook == hook) { 395a8353960SJulian Elischer connection = tmp; 396a8353960SJulian Elischer } 397a8353960SJulian Elischer } 398a8353960SJulian Elischer if(connection == NULL) { 399a8353960SJulian Elischer printf("%s(): connection is still NULL, no hook found\n",__func__); 400a8353960SJulian Elischer return(-1); 401a8353960SJulian Elischer } 402a8353960SJulian Elischer 403a8353960SJulian Elischer free(connection->readq,M_DEVBUF); 404a8353960SJulian Elischer 405a8353960SJulian Elischer destroy_dev(connection->ngddev); 406a8353960SJulian Elischer 407a8353960SJulian Elischer SLIST_REMOVE(&sc->head,connection,ngd_connection,links); 408a8353960SJulian Elischer 409a8353960SJulian Elischer return(0); 410a8353960SJulian Elischer } 411a8353960SJulian Elischer /* 412a8353960SJulian Elischer * the device is opened 413a8353960SJulian Elischer */ 414a8353960SJulian Elischer static int 415a8353960SJulian Elischer ngdopen(dev_t dev, int flag, int mode, struct thread *td) 416a8353960SJulian Elischer { 417a8353960SJulian Elischer 418a8353960SJulian Elischer #ifdef NGD_DEBUG 419a8353960SJulian Elischer printf("%s()\n",__func__); 420a8353960SJulian Elischer #endif /* NGD_DEBUG */ 421a8353960SJulian Elischer 422a8353960SJulian Elischer return(0); 423a8353960SJulian Elischer } 424a8353960SJulian Elischer 425a8353960SJulian Elischer /* 426a8353960SJulian Elischer * the device is closed 427a8353960SJulian Elischer */ 428a8353960SJulian Elischer static int 429a8353960SJulian Elischer ngdclose(dev_t dev, int flag, int mode, struct thread *td) 430a8353960SJulian Elischer { 431a8353960SJulian Elischer 432a8353960SJulian Elischer #ifdef NGD_DEBUG 433a8353960SJulian Elischer printf("%s()\n",__func__); 434a8353960SJulian Elischer #endif 435a8353960SJulian Elischer 436a8353960SJulian Elischer return(0); 437a8353960SJulian Elischer } 438a8353960SJulian Elischer 439a8353960SJulian Elischer 440a8353960SJulian Elischer /* 441a8353960SJulian Elischer * process ioctl 442a8353960SJulian Elischer * 443a8353960SJulian Elischer * they are translated into netgraph messages and passed on 444a8353960SJulian Elischer * 445a8353960SJulian Elischer */ 446a8353960SJulian Elischer static int 447a8353960SJulian Elischer ngdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td) 448a8353960SJulian Elischer { 449a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 450a8353960SJulian Elischer struct ngd_connection * connection = NULL; 451a8353960SJulian Elischer struct ngd_connection * tmp; 452a8353960SJulian Elischer int error = 0; 453a8353960SJulian Elischer struct ng_mesg *msg; 454a8353960SJulian Elischer struct ngd_param_s * datap; 455a8353960SJulian Elischer 456a8353960SJulian Elischer #ifdef NGD_DEBUG 457a8353960SJulian Elischer printf("%s()\n",__func__); 458a8353960SJulian Elischer #endif /* NGD_DEBUG */ 459a8353960SJulian Elischer 460a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 461a8353960SJulian Elischer if(tmp->ngddev == dev) { 462a8353960SJulian Elischer connection = tmp; 463a8353960SJulian Elischer } 464a8353960SJulian Elischer } 465a8353960SJulian Elischer if(connection == NULL) { 466a8353960SJulian Elischer printf("%s(): connection is still NULL, no dev found\n",__func__); 467a8353960SJulian Elischer return(-1); 468a8353960SJulian Elischer } 469a8353960SJulian Elischer 470a8353960SJulian Elischer /* NG_MKMESSAGE(msg, cookie, cmdid, len, how) */ 471a8353960SJulian Elischer NG_MKMESSAGE(msg, NGM_DEVICE_COOKIE, cmd, sizeof(struct ngd_param_s), 472a8353960SJulian Elischer M_NOWAIT); 473a8353960SJulian Elischer if (msg == NULL) { 474a8353960SJulian Elischer printf("%s(): msg == NULL\n",__func__); 475a8353960SJulian Elischer goto nomsg; 476a8353960SJulian Elischer } 477a8353960SJulian Elischer 478a8353960SJulian Elischer /* pass the ioctl data into the ->data area */ 479a8353960SJulian Elischer datap = (struct ngd_param_s *)msg->data; 480a8353960SJulian Elischer datap->p = addr; 481a8353960SJulian Elischer 482a8353960SJulian Elischer /* NG_SEND_MSG_HOOK(error, here, msg, hook, retaddr) */ 483a8353960SJulian Elischer NG_SEND_MSG_HOOK(error, sc->node, msg, connection->active_hook, NULL); 484a8353960SJulian Elischer if(error) 485a8353960SJulian Elischer printf("%s(): NG_SEND_MSG_HOOK error: %d\n",__func__,error); 486a8353960SJulian Elischer 487a8353960SJulian Elischer nomsg: 488a8353960SJulian Elischer 489a8353960SJulian Elischer return(0); 490a8353960SJulian Elischer } 491a8353960SJulian Elischer 492a8353960SJulian Elischer 493a8353960SJulian Elischer /* 494a8353960SJulian Elischer * This function is called when a read(2) is done to our device. 495a8353960SJulian Elischer * We pass the data available in kernelspace on into userland using 496a8353960SJulian Elischer * uiomove. 497a8353960SJulian Elischer */ 498a8353960SJulian Elischer static int 499a8353960SJulian Elischer ngdread(dev_t dev, struct uio *uio, int flag) 500a8353960SJulian Elischer { 501a8353960SJulian Elischer int ret = 0, amnt; 502a8353960SJulian Elischer char buffer[uio->uio_resid+1]; 503a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 504a8353960SJulian Elischer struct ngd_connection * connection = NULL; 505a8353960SJulian Elischer struct ngd_connection * tmp; 506a8353960SJulian Elischer 507a8353960SJulian Elischer #ifdef NGD_DEBUG 508a8353960SJulian Elischer printf("%s()\n",__func__); 509a8353960SJulian Elischer #endif /* NGD_DEBUG */ 510a8353960SJulian Elischer 511a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 512a8353960SJulian Elischer if(tmp->ngddev == dev) { 513a8353960SJulian Elischer connection = tmp; 514a8353960SJulian Elischer } 515a8353960SJulian Elischer } 516a8353960SJulian Elischer if(connection == NULL) { 517a8353960SJulian Elischer printf("%s(): connection is still NULL, no dev found\n",__func__); 518a8353960SJulian Elischer return(-1); 519a8353960SJulian Elischer } 520a8353960SJulian Elischer 521a8353960SJulian Elischer while ( ( uio->uio_resid > 0 ) && ( connection->loc > 0 ) ) { 522a8353960SJulian Elischer amnt = MIN(uio->uio_resid,connection->loc); 523a8353960SJulian Elischer 524a8353960SJulian Elischer memcpy(buffer,connection->readq, amnt); 525a8353960SJulian Elischer memcpy(connection->readq, connection->readq+amnt, 526a8353960SJulian Elischer connection->loc-amnt); 527a8353960SJulian Elischer connection->loc -= amnt; 528a8353960SJulian Elischer 529a8353960SJulian Elischer ret = uiomove((caddr_t)buffer, amnt, uio); 530a8353960SJulian Elischer if(ret != 0) 531a8353960SJulian Elischer goto error; 532a8353960SJulian Elischer 533a8353960SJulian Elischer } 534a8353960SJulian Elischer return(0); 535a8353960SJulian Elischer 536a8353960SJulian Elischer error: 537a8353960SJulian Elischer printf("%s(): uiomove returns error %d\n",__func__,ret); 538a8353960SJulian Elischer /* do error cleanup here */ 539a8353960SJulian Elischer return(ret); 540a8353960SJulian Elischer } 541a8353960SJulian Elischer 542a8353960SJulian Elischer 543a8353960SJulian Elischer /* 544a8353960SJulian Elischer * This function is called when our device is written to. 545a8353960SJulian Elischer * We read the data from userland into our local buffer and pass it on 546a8353960SJulian Elischer * into the remote hook. 547a8353960SJulian Elischer * 548a8353960SJulian Elischer */ 549a8353960SJulian Elischer static int 550a8353960SJulian Elischer ngdwrite(dev_t dev, struct uio *uio, int flag) 551a8353960SJulian Elischer { 552a8353960SJulian Elischer int ret; 553a8353960SJulian Elischer int error = 0; 554a8353960SJulian Elischer struct mbuf *m; 555a8353960SJulian Elischer char buffer[uio->uio_resid]; 556a8353960SJulian Elischer int len = uio->uio_resid; 557a8353960SJulian Elischer struct ngd_softc *sc =& ngd_softc; 558a8353960SJulian Elischer struct ngd_connection * connection = NULL; 559a8353960SJulian Elischer struct ngd_connection * tmp; 560a8353960SJulian Elischer 561a8353960SJulian Elischer #ifdef NGD_DEBUG 562a8353960SJulian Elischer printf("%s()\n",__func__); 563a8353960SJulian Elischer #endif /* NGD_DEBUG */ 564a8353960SJulian Elischer 565a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 566a8353960SJulian Elischer if(tmp->ngddev == dev) { 567a8353960SJulian Elischer connection = tmp; 568a8353960SJulian Elischer } 569a8353960SJulian Elischer } 570a8353960SJulian Elischer 571a8353960SJulian Elischer if(connection == NULL) { 572a8353960SJulian Elischer printf("%s(): connection is still NULL, no dev found\n",__func__); 573a8353960SJulian Elischer return(-1); 574a8353960SJulian Elischer } 575a8353960SJulian Elischer 576a8353960SJulian Elischer if (len > 0) { 577a8353960SJulian Elischer if ((ret = uiomove((caddr_t)buffer, len, uio)) != 0) 578a8353960SJulian Elischer goto error; 579a8353960SJulian Elischer } else 580a8353960SJulian Elischer printf("%s(): len <= 0 : is this supposed to happen?!\n",__func__); 581a8353960SJulian Elischer 582a8353960SJulian Elischer m = m_devget(buffer,len,0,NULL,NULL); 583a8353960SJulian Elischer 584a8353960SJulian Elischer NG_SEND_DATA_ONLY(error,connection->active_hook,m); 585a8353960SJulian Elischer 586a8353960SJulian Elischer return(0); 587a8353960SJulian Elischer 588a8353960SJulian Elischer error: 589a8353960SJulian Elischer /* do error cleanup here */ 590a8353960SJulian Elischer printf("%s(): uiomove returned err: %d\n",__func__,ret); 591a8353960SJulian Elischer 592a8353960SJulian Elischer return(ret); 593a8353960SJulian Elischer } 594a8353960SJulian Elischer 595a8353960SJulian Elischer /* 596a8353960SJulian Elischer * we are being polled/selected 597a8353960SJulian Elischer * check if there is data available for read 598a8353960SJulian Elischer */ 599a8353960SJulian Elischer static int 600a8353960SJulian Elischer ngdpoll(dev_t dev, int events, struct thread *td) 601a8353960SJulian Elischer { 602a8353960SJulian Elischer int revents = 0; 603a8353960SJulian Elischer struct ngd_softc *sc = &ngd_softc; 604a8353960SJulian Elischer struct ngd_connection * connection = NULL; 605a8353960SJulian Elischer struct ngd_connection * tmp; 606a8353960SJulian Elischer 607a8353960SJulian Elischer 608a8353960SJulian Elischer if (events & (POLLIN | POLLRDNORM)) { 609a8353960SJulian Elischer /* get the connection we have to know the loc from */ 610a8353960SJulian Elischer SLIST_FOREACH(tmp,&sc->head,links) { 611a8353960SJulian Elischer if(tmp->ngddev == dev) { 612a8353960SJulian Elischer connection = tmp; 613a8353960SJulian Elischer } 614a8353960SJulian Elischer } 615a8353960SJulian Elischer if(connection == NULL) { 616a8353960SJulian Elischer printf("%s(): ERROR: connection is still NULL," 617a8353960SJulian Elischer "no dev found\n",__func__); 618a8353960SJulian Elischer return(-1); 619a8353960SJulian Elischer } 620a8353960SJulian Elischer 621a8353960SJulian Elischer if (connection->loc > 0) 622a8353960SJulian Elischer revents |= events & (POLLIN | POLLRDNORM); 623a8353960SJulian Elischer } 624a8353960SJulian Elischer 625a8353960SJulian Elischer return(revents); 626a8353960SJulian Elischer } 627