152419Sjulian/* 252419Sjulian * ng_sample.c 3139823Simp */ 4139823Simp 5139823Simp/*- 652419Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc. 752419Sjulian * All rights reserved. 852419Sjulian * 952419Sjulian * Subject to the following obligations and disclaimer of warranty, use and 1052419Sjulian * redistribution of this software, in source or object code forms, with or 1152419Sjulian * without modifications are expressly permitted by Whistle Communications; 1252419Sjulian * provided, however, that: 1352419Sjulian * 1. Any and all reproductions of the source or object code must include the 1452419Sjulian * copyright notice above and the following disclaimer of warranties; and 1552419Sjulian * 2. No rights are granted, in any manner or form, to use Whistle 1652419Sjulian * Communications, Inc. trademarks, including the mark "WHISTLE 1752419Sjulian * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1852419Sjulian * such appears in the above copyright notice or in the software. 1952419Sjulian * 2052419Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 2152419Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2252419Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2352419Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2452419Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2552419Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2652419Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2752419Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2852419Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2952419Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 3052419Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 3152419Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3252419Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3352419Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3452419Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3552419Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3652419Sjulian * OF SUCH DAMAGE. 3752419Sjulian * 3867506Sjulian * Author: Julian Elischer <julian@freebsd.org> 3952419Sjulian * 4052419Sjulian * $FreeBSD$ 4152752Sjulian * $Whistle: ng_sample.c,v 1.13 1999/11/01 09:24:52 julian Exp $ 4252419Sjulian */ 4352419Sjulian 4452419Sjulian#include <sys/param.h> 4552419Sjulian#include <sys/systm.h> 4652419Sjulian#include <sys/kernel.h> 4752419Sjulian#include <sys/mbuf.h> 4852419Sjulian#include <sys/malloc.h> 4953997Sarchie#include <sys/ctype.h> 5052419Sjulian#include <sys/errno.h> 5152419Sjulian#include <sys/syslog.h> 5252419Sjulian 5352419Sjulian#include <netgraph/ng_message.h> 5453997Sarchie#include <netgraph/ng_parse.h> 5552419Sjulian#include <netgraph/ng_sample.h> 5652419Sjulian#include <netgraph/netgraph.h> 5752419Sjulian 5870870Sjulian/* If you do complicated mallocs you may want to do this */ 5970870Sjulian/* and use it for your mallocs */ 6070870Sjulian#ifdef NG_SEPARATE_MALLOC 61249132Smavstatic MALLOC_DEFINE(M_NETGRAPH_XXX, "netgraph_xxx", "netgraph xxx node"); 6270870Sjulian#else 6370870Sjulian#define M_NETGRAPH_XXX M_NETGRAPH 6470870Sjulian#endif 6570870Sjulian 6652419Sjulian/* 6752419Sjulian * This section contains the netgraph method declarations for the 6852419Sjulian * sample node. These methods define the netgraph 'type'. 6952419Sjulian */ 7052419Sjulian 7152752Sjulianstatic ng_constructor_t ng_xxx_constructor; 7252752Sjulianstatic ng_rcvmsg_t ng_xxx_rcvmsg; 7370700Sjulianstatic ng_shutdown_t ng_xxx_shutdown; 7452752Sjulianstatic ng_newhook_t ng_xxx_newhook; 7552752Sjulianstatic ng_connect_t ng_xxx_connect; 76141409Sglebiusstatic ng_rcvdata_t ng_xxx_rcvdata; 7752752Sjulianstatic ng_disconnect_t ng_xxx_disconnect; 7852419Sjulian 7953997Sarchie/* Parse type for struct ngxxxstat */ 8097685Sarchiestatic const struct ng_parse_struct_field ng_xxx_stat_type_fields[] 8197685Sarchie = NG_XXX_STATS_TYPE_INFO; 8253997Sarchiestatic const struct ng_parse_type ng_xxx_stat_type = { 8353997Sarchie &ng_parse_struct_type, 8497685Sarchie &ng_xxx_stat_type_fields 8553997Sarchie}; 8653997Sarchie 8753997Sarchie/* List of commands and how to convert arguments to/from ASCII */ 8853997Sarchiestatic const struct ng_cmdlist ng_xxx_cmdlist[] = { 8953997Sarchie { 9053997Sarchie NGM_XXX_COOKIE, 9153997Sarchie NGM_XXX_GET_STATUS, 9253997Sarchie "getstatus", 9353997Sarchie NULL, 9453997Sarchie &ng_xxx_stat_type, 9553997Sarchie }, 9653997Sarchie { 9753997Sarchie NGM_XXX_COOKIE, 9853997Sarchie NGM_XXX_SET_FLAG, 9953997Sarchie "setflag", 10053997Sarchie &ng_parse_int32_type, 10153997Sarchie NULL 10253997Sarchie }, 10353997Sarchie { 0 } 10453997Sarchie}; 10553997Sarchie 10652419Sjulian/* Netgraph node type descriptor */ 10752419Sjulianstatic struct ng_type typestruct = { 108129823Sjulian .version = NG_ABI_VERSION, 109129823Sjulian .name = NG_XXX_NODE_TYPE, 110129823Sjulian .constructor = ng_xxx_constructor, 111129823Sjulian .rcvmsg = ng_xxx_rcvmsg, 112129823Sjulian .shutdown = ng_xxx_shutdown, 113129823Sjulian .newhook = ng_xxx_newhook, 114129823Sjulian/* .findhook = ng_xxx_findhook, */ 115129823Sjulian .connect = ng_xxx_connect, 116129823Sjulian .rcvdata = ng_xxx_rcvdata, 117129823Sjulian .disconnect = ng_xxx_disconnect, 118129823Sjulian .cmdlist = ng_xxx_cmdlist, 11952419Sjulian}; 12052419SjulianNETGRAPH_INIT(xxx, &typestruct); 12152419Sjulian 12252419Sjulian/* Information we store for each hook on each node */ 12352419Sjulianstruct XXX_hookinfo { 124141410Sglebius int dlci; /* The DLCI it represents, -1 == downstream */ 125141410Sglebius int channel; /* The channel representing this DLCI */ 126141410Sglebius hook_p hook; 12752419Sjulian}; 12852419Sjulian 12952419Sjulian/* Information we store for each node */ 13052419Sjulianstruct XXX { 13152419Sjulian struct XXX_hookinfo channel[XXX_NUM_DLCIS]; 13252419Sjulian struct XXX_hookinfo downstream_hook; 13352419Sjulian node_p node; /* back pointer to node */ 13452419Sjulian hook_p debughook; 13552419Sjulian u_int packets_in; /* packets in from downstream */ 13652419Sjulian u_int packets_out; /* packets out towards downstream */ 13752419Sjulian u_int32_t flags; 13852419Sjulian}; 13952419Sjuliantypedef struct XXX *xxx_p; 14052419Sjulian 14152419Sjulian/* 14270700Sjulian * Allocate the private data structure. The generic node has already 14370700Sjulian * been created. Link them together. We arrive with a reference to the node 14470700Sjulian * i.e. the reference count is incremented for us already. 14552419Sjulian * 14652419Sjulian * If this were a device node than this work would be done in the attach() 14752419Sjulian * routine and the constructor would return EINVAL as you should not be able 14852419Sjulian * to creatednodes that depend on hardware (unless you can add the hardware :) 14952419Sjulian */ 15052419Sjulianstatic int 15170784Sjulianng_xxx_constructor(node_p node) 15252419Sjulian{ 15352419Sjulian xxx_p privdata; 15473005Sjulian int i; 15552419Sjulian 15652419Sjulian /* Initialize private descriptor */ 157220768Sglebius privdata = malloc(sizeof(*privdata), M_NETGRAPH, M_WAITOK | M_ZERO); 15852419Sjulian for (i = 0; i < XXX_NUM_DLCIS; i++) { 15952419Sjulian privdata->channel[i].dlci = -2; 16052419Sjulian privdata->channel[i].channel = i; 16152419Sjulian } 16252419Sjulian 16352419Sjulian /* Link structs together; this counts as our one reference to *nodep */ 16473005Sjulian NG_NODE_SET_PRIVATE(node, privdata); 16570784Sjulian privdata->node = node; 16652419Sjulian return (0); 16752419Sjulian} 16852419Sjulian 16952419Sjulian/* 17052419Sjulian * Give our ok for a hook to be added... 17152419Sjulian * If we are not running this might kick a device into life. 17252419Sjulian * Possibly decode information out of the hook name. 17352419Sjulian * Add the hook's private info to the hook structure. 17452419Sjulian * (if we had some). In this example, we assume that there is a 17552419Sjulian * an array of structs, called 'channel' in the private info, 17652419Sjulian * one for each active channel. The private 17752419Sjulian * pointer of each hook points to the appropriate XXX_hookinfo struct 17852419Sjulian * so that the source of an input packet is easily identified. 17952419Sjulian * (a dlci is a frame relay channel) 18052419Sjulian */ 18152419Sjulianstatic int 18252419Sjulianng_xxx_newhook(node_p node, hook_p hook, const char *name) 18352419Sjulian{ 18470784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 18552419Sjulian const char *cp; 18652419Sjulian int dlci = 0; 18752419Sjulian int chan; 18852419Sjulian 18952419Sjulian#if 0 19052419Sjulian /* Possibly start up the device if it's not already going */ 19152419Sjulian if ((xxxp->flags & SCF_RUNNING) == 0) { 19252419Sjulian ng_xxx_start_hardware(xxxp); 19352419Sjulian } 19452419Sjulian#endif 19552419Sjulian 19652419Sjulian /* Example of how one might use hooks with embedded numbers: All 19752419Sjulian * hooks start with 'dlci' and have a decimal trailing channel 19852419Sjulian * number up to 4 digits Use the leadin defined int he associated .h 19952419Sjulian * file. */ 20052816Sarchie if (strncmp(name, 20152816Sarchie NG_XXX_HOOK_DLCI_LEADIN, strlen(NG_XXX_HOOK_DLCI_LEADIN)) == 0) { 20253648Sarchie char *eptr; 20352816Sarchie 204139238Srik cp = name + strlen(NG_XXX_HOOK_DLCI_LEADIN); 20552816Sarchie if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) 20652419Sjulian return (EINVAL); 20752816Sarchie dlci = (int)strtoul(cp, &eptr, 10); 20852816Sarchie if (*eptr != '\0' || dlci < 0 || dlci > 1023) 20952816Sarchie return (EINVAL); 21052816Sarchie 21152419Sjulian /* We have a dlci, now either find it, or allocate it */ 21252419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 21352419Sjulian if (xxxp->channel[chan].dlci == dlci) 21452419Sjulian break; 21552419Sjulian if (chan == XXX_NUM_DLCIS) { 21652419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 217139249Srik if (xxxp->channel[chan].dlci == -2) 218139249Srik break; 21952419Sjulian if (chan == XXX_NUM_DLCIS) 22052419Sjulian return (ENOBUFS); 221139249Srik xxxp->channel[chan].dlci = dlci; 22252419Sjulian } 22352419Sjulian if (xxxp->channel[chan].hook != NULL) 22452419Sjulian return (EADDRINUSE); 22570784Sjulian NG_HOOK_SET_PRIVATE(hook, xxxp->channel + chan); 22652419Sjulian xxxp->channel[chan].hook = hook; 22752419Sjulian return (0); 22852419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DOWNSTREAM) == 0) { 22952419Sjulian /* Example of simple predefined hooks. */ 23052419Sjulian /* do something specific to the downstream connection */ 23152419Sjulian xxxp->downstream_hook.hook = hook; 23270784Sjulian NG_HOOK_SET_PRIVATE(hook, &xxxp->downstream_hook); 23352419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DEBUG) == 0) { 23452419Sjulian /* do something specific to a debug connection */ 23552419Sjulian xxxp->debughook = hook; 23670784Sjulian NG_HOOK_SET_PRIVATE(hook, NULL); 23752419Sjulian } else 23852419Sjulian return (EINVAL); /* not a hook we know about */ 23952419Sjulian return(0); 24052419Sjulian} 24152419Sjulian 24252419Sjulian/* 24352419Sjulian * Get a netgraph control message. 24470700Sjulian * We actually recieve a queue item that has a pointer to the message. 24570700Sjulian * If we free the item, the message will be freed too, unless we remove 24670700Sjulian * it from the item using NGI_GET_MSG(); 24770700Sjulian * The return address is also stored in the item, as an ng_ID_t, 24870700Sjulian * accessible as NGI_RETADDR(item); 24952419Sjulian * Check it is one we understand. If needed, send a response. 25052419Sjulian * We could save the address for an async action later, but don't here. 25152419Sjulian * Always free the message. 25252419Sjulian * The response should be in a malloc'd region that the caller can 'free'. 25352419Sjulian * A response is not required. 25452419Sjulian * Theoretically you could respond defferently to old message types if 25552419Sjulian * the cookie in the header didn't match what we consider to be current 25652419Sjulian * (so that old userland programs could continue to work). 25752419Sjulian */ 25852419Sjulianstatic int 25970700Sjulianng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook) 26052419Sjulian{ 26170784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 26252419Sjulian struct ng_mesg *resp = NULL; 26352419Sjulian int error = 0; 26470700Sjulian struct ng_mesg *msg; 26552419Sjulian 26670700Sjulian NGI_GET_MSG(item, msg); 26752419Sjulian /* Deal with message according to cookie and command */ 26852419Sjulian switch (msg->header.typecookie) { 269141410Sglebius case NGM_XXX_COOKIE: 27052419Sjulian switch (msg->header.cmd) { 27152419Sjulian case NGM_XXX_GET_STATUS: 27252419Sjulian { 27352419Sjulian struct ngxxxstat *stats; 27452419Sjulian 27552419Sjulian NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); 27652419Sjulian if (!resp) { 27752419Sjulian error = ENOMEM; 27852419Sjulian break; 27952419Sjulian } 28052419Sjulian stats = (struct ngxxxstat *) resp->data; 28152419Sjulian stats->packets_in = xxxp->packets_in; 28252419Sjulian stats->packets_out = xxxp->packets_out; 28352419Sjulian break; 28452419Sjulian } 28552419Sjulian case NGM_XXX_SET_FLAG: 28652419Sjulian if (msg->header.arglen != sizeof(u_int32_t)) { 28752419Sjulian error = EINVAL; 28852419Sjulian break; 28952419Sjulian } 29052419Sjulian xxxp->flags = *((u_int32_t *) msg->data); 29152419Sjulian break; 29252419Sjulian default: 29352419Sjulian error = EINVAL; /* unknown command */ 29452419Sjulian break; 29552419Sjulian } 29652419Sjulian break; 29752419Sjulian default: 29852419Sjulian error = EINVAL; /* unknown cookie type */ 29952419Sjulian break; 30052419Sjulian } 30152419Sjulian 30252419Sjulian /* Take care of synchronous response, if any */ 30370700Sjulian NG_RESPOND_MSG(error, node, item, resp); 30452419Sjulian /* Free the message and return */ 30570700Sjulian NG_FREE_MSG(msg); 30652419Sjulian return(error); 30752419Sjulian} 30852419Sjulian 30952419Sjulian/* 31052419Sjulian * Receive data, and do something with it. 31170700Sjulian * Actually we receive a queue item which holds the data. 312131155Sjulian * If we free the item it will also free the data unless we have 313131155Sjulian * previously disassociated it using the NGI_GET_M() macro. 31452419Sjulian * Possibly send it out on another link after processing. 31552419Sjulian * Possibly do something different if it comes from different 316131155Sjulian * hooks. The caller will never free m, so if we use up this data or 317131155Sjulian * abort we must free it. 31852419Sjulian * 31952419Sjulian * If we want, we may decide to force this data to be queued and reprocessed 32069922Sjulian * at the netgraph NETISR time. 32169922Sjulian * We would do that by setting the HK_QUEUE flag on our hook. We would do that 322141410Sglebius * in the connect() method. 32352419Sjulian */ 32452419Sjulianstatic int 32570700Sjulianng_xxx_rcvdata(hook_p hook, item_p item ) 32652419Sjulian{ 32770784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 32852419Sjulian int chan = -2; 32952419Sjulian int dlci = -2; 33052419Sjulian int error; 33170700Sjulian struct mbuf *m; 33252419Sjulian 33370700Sjulian NGI_GET_M(item, m); 33470784Sjulian if (NG_HOOK_PRIVATE(hook)) { 33570784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 33670784Sjulian chan = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->channel; 33752419Sjulian if (dlci != -1) { 33852419Sjulian /* If received on a DLCI hook process for this 33952419Sjulian * channel and pass it to the downstream module. 34052419Sjulian * Normally one would add a multiplexing header at 34152419Sjulian * the front here */ 34252419Sjulian /* M_PREPEND(....) ; */ 34352419Sjulian /* mtod(m, xxxxxx)->dlci = dlci; */ 344141410Sglebius NG_FWD_NEW_DATA(error, item, 34570700Sjulian xxxp->downstream_hook.hook, m); 34652419Sjulian xxxp->packets_out++; 34752419Sjulian } else { 34852419Sjulian /* data came from the multiplexed link */ 34952419Sjulian dlci = 1; /* get dlci from header */ 35052419Sjulian /* madjust(....) *//* chop off header */ 35152419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 35252419Sjulian if (xxxp->channel[chan].dlci == dlci) 35352419Sjulian break; 35452419Sjulian if (chan == XXX_NUM_DLCIS) { 35570700Sjulian NG_FREE_ITEM(item); 35670700Sjulian NG_FREE_M(m); 35752419Sjulian return (ENETUNREACH); 35852419Sjulian } 35952419Sjulian /* If we were called at splnet, use the following: 360131155Sjulian * NG_SEND_DATA_ONLY(error, otherhook, m); if this 36152419Sjulian * node is running at some SPL other than SPLNET 36252419Sjulian * then you should use instead: error = 363131155Sjulian * ng_queueit(otherhook, m, NULL); m = NULL; 364131155Sjulian * This queues the data using the standard NETISR 365131155Sjulian * system and schedules the data to be picked 36652419Sjulian * up again once the system has moved to SPLNET and 367131155Sjulian * the processing of the data can continue. After 368131155Sjulian * these are run 'm' should be considered 36952419Sjulian * as invalid and NG_SEND_DATA actually zaps them. */ 37070700Sjulian NG_FWD_NEW_DATA(error, item, 37170700Sjulian xxxp->channel[chan].hook, m); 37252419Sjulian xxxp->packets_in++; 37352419Sjulian } 37452419Sjulian } else { 37552419Sjulian /* It's the debug hook, throw it away.. */ 37670933Sjulian if (hook == xxxp->downstream_hook.hook) { 37770700Sjulian NG_FREE_ITEM(item); 37870700Sjulian NG_FREE_M(m); 37970933Sjulian } 38052419Sjulian } 38152419Sjulian return 0; 38252419Sjulian} 38352419Sjulian 38452419Sjulian#if 0 38552419Sjulian/* 38652419Sjulian * If this were a device node, the data may have been received in response 38752419Sjulian * to some interrupt. 38852419Sjulian * in which case it would probably look as follows: 38952419Sjulian */ 39052419Sjuliandevintr() 39152419Sjulian{ 39269922Sjulian int error; 39352419Sjulian 39452419Sjulian /* get packet from device and send on */ 39552419Sjulian m = MGET(blah blah) 39669922Sjulian 39769922Sjulian NG_SEND_DATA_ONLY(error, xxxp->upstream_hook.hook, m); 39869922Sjulian /* see note above in xxx_rcvdata() */ 39969922Sjulian /* and ng_xxx_connect() */ 40052419Sjulian} 40152419Sjulian 40252419Sjulian#endif /* 0 */ 40352419Sjulian 40452419Sjulian/* 40552419Sjulian * Do local shutdown processing.. 40670700Sjulian * All our links and the name have already been removed. 40771849Sjulian * If we are a persistant device, we might refuse to go away. 40871849Sjulian * In the case of a persistant node we signal the framework that we 409132464Sjulian * are still in business by clearing the NGF_INVALID bit. However 410132464Sjulian * If we find the NGF_REALLY_DIE bit set, this means that 41171849Sjulian * we REALLY need to die (e.g. hardware removed). 41271849Sjulian * This would have been set using the NG_NODE_REALLY_DIE(node) 41371849Sjulian * macro in some device dependent function (not shown here) before 41471849Sjulian * calling ng_rmnode_self(). 41552419Sjulian */ 41652419Sjulianstatic int 41770700Sjulianng_xxx_shutdown(node_p node) 41852419Sjulian{ 41970784Sjulian const xxx_p privdata = NG_NODE_PRIVATE(node); 42052419Sjulian 42171849Sjulian#ifndef PERSISTANT_NODE 42270784Sjulian NG_NODE_SET_PRIVATE(node, NULL); 423132828Sglebius NG_NODE_UNREF(node); 424184205Sdes free(privdata, M_NETGRAPH); 42552419Sjulian#else 426132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 42771849Sjulian /* 42871849Sjulian * WE came here because the widget card is being unloaded, 42971849Sjulian * so stop being persistant. 43071849Sjulian * Actually undo all the things we did on creation. 43171849Sjulian */ 43271849Sjulian NG_NODE_SET_PRIVATE(node, NULL); 43371849Sjulian NG_NODE_UNREF(privdata->node); 434184205Sdes free(privdata, M_NETGRAPH); 435141410Sglebius return (0); 436141410Sglebius } 437132464Sjulian NG_NODE_REVIVE(node); /* tell ng_rmnode() we will persist */ 43852419Sjulian#endif /* PERSISTANT_NODE */ 43952419Sjulian return (0); 44052419Sjulian} 44152419Sjulian 44252419Sjulian/* 44352419Sjulian * This is called once we've already connected a new hook to the other node. 44452419Sjulian * It gives us a chance to balk at the last minute. 44552419Sjulian */ 44652419Sjulianstatic int 44752419Sjulianng_xxx_connect(hook_p hook) 44852419Sjulian{ 44969922Sjulian#if 0 45069922Sjulian /* 45169922Sjulian * If we were a driver running at other than splnet then 45269922Sjulian * we should set the QUEUE bit on the edge so that we 45369922Sjulian * will deliver by queing. 45469922Sjulian */ 45569922Sjulian if /*it is the upstream hook */ 45670784Sjulian NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 45769922Sjulian#endif 45869922Sjulian#if 0 45969922Sjulian /* 46069922Sjulian * If for some reason we want incoming date to be queued 46169922Sjulian * by the NETISR system and delivered later we can set the same bit on 46269922Sjulian * OUR hook. (maybe to allow unwinding of the stack) 46369922Sjulian */ 46469922Sjulian 46570784Sjulian if (NG_HOOK_PRIVATE(hook)) { 46669922Sjulian int dlci; 467141410Sglebius /* 46869922Sjulian * If it's dlci 1023, requeue it so that it's handled 46969922Sjulian * at a lower priority. This is how a node decides to 47069922Sjulian * defer a data message. 47169922Sjulian */ 47270784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 47369922Sjulian if (dlci == 1023) { 47470784Sjulian NG_HOOK_FORCE_QUEUE(hook); 47569922Sjulian } 47669922Sjulian#endif 47769922Sjulian /* otherwise be really amiable and just say "YUP that's OK by me! " */ 47852419Sjulian return (0); 47952419Sjulian} 48052419Sjulian 48152419Sjulian/* 48273005Sjulian * Hook disconnection 48352419Sjulian * 48452419Sjulian * For this type, removal of the last link destroys the node 48552419Sjulian */ 48652419Sjulianstatic int 48752419Sjulianng_xxx_disconnect(hook_p hook) 48852419Sjulian{ 48970784Sjulian if (NG_HOOK_PRIVATE(hook)) 49070784Sjulian ((struct XXX_hookinfo *) (NG_HOOK_PRIVATE(hook)))->hook = NULL; 49170784Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 49270784Sjulian && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */ 49370784Sjulian ng_rmnode_self(NG_HOOK_NODE(hook)); 49452419Sjulian return (0); 49552419Sjulian} 49652419Sjulian 497