ng_sample.c revision 141409
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: head/sys/netgraph/ng_sample.c 141409 2005-02-06 19:20:16Z glebius $ 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 6170870SjulianMALLOC_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 { 12452419Sjulian int dlci; /* The DLCI it represents, -1 == downstream */ 12552419Sjulian int channel; /* The channel representing this DLCI */ 12652419Sjulian 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 */ 15768876Sdwmalone MALLOC(privdata, xxx_p, sizeof(*privdata), M_NETGRAPH, 15868876Sdwmalone M_NOWAIT | M_ZERO); 15952419Sjulian if (privdata == NULL) 16052419Sjulian return (ENOMEM); 16152419Sjulian for (i = 0; i < XXX_NUM_DLCIS; i++) { 16252419Sjulian privdata->channel[i].dlci = -2; 16352419Sjulian privdata->channel[i].channel = i; 16452419Sjulian } 16552419Sjulian 16652419Sjulian /* Link structs together; this counts as our one reference to *nodep */ 16773005Sjulian NG_NODE_SET_PRIVATE(node, privdata); 16870784Sjulian privdata->node = node; 16952419Sjulian return (0); 17052419Sjulian} 17152419Sjulian 17252419Sjulian/* 17352419Sjulian * Give our ok for a hook to be added... 17452419Sjulian * If we are not running this might kick a device into life. 17552419Sjulian * Possibly decode information out of the hook name. 17652419Sjulian * Add the hook's private info to the hook structure. 17752419Sjulian * (if we had some). In this example, we assume that there is a 17852419Sjulian * an array of structs, called 'channel' in the private info, 17952419Sjulian * one for each active channel. The private 18052419Sjulian * pointer of each hook points to the appropriate XXX_hookinfo struct 18152419Sjulian * so that the source of an input packet is easily identified. 18252419Sjulian * (a dlci is a frame relay channel) 18352419Sjulian */ 18452419Sjulianstatic int 18552419Sjulianng_xxx_newhook(node_p node, hook_p hook, const char *name) 18652419Sjulian{ 18770784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 18852419Sjulian const char *cp; 18952419Sjulian int dlci = 0; 19052419Sjulian int chan; 19152419Sjulian 19252419Sjulian#if 0 19352419Sjulian /* Possibly start up the device if it's not already going */ 19452419Sjulian if ((xxxp->flags & SCF_RUNNING) == 0) { 19552419Sjulian ng_xxx_start_hardware(xxxp); 19652419Sjulian } 19752419Sjulian#endif 19852419Sjulian 19952419Sjulian /* Example of how one might use hooks with embedded numbers: All 20052419Sjulian * hooks start with 'dlci' and have a decimal trailing channel 20152419Sjulian * number up to 4 digits Use the leadin defined int he associated .h 20252419Sjulian * file. */ 20352816Sarchie if (strncmp(name, 20452816Sarchie NG_XXX_HOOK_DLCI_LEADIN, strlen(NG_XXX_HOOK_DLCI_LEADIN)) == 0) { 20553648Sarchie char *eptr; 20652816Sarchie 207139238Srik cp = name + strlen(NG_XXX_HOOK_DLCI_LEADIN); 20852816Sarchie if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) 20952419Sjulian return (EINVAL); 21052816Sarchie dlci = (int)strtoul(cp, &eptr, 10); 21152816Sarchie if (*eptr != '\0' || dlci < 0 || dlci > 1023) 21252816Sarchie return (EINVAL); 21352816Sarchie 21452419Sjulian /* We have a dlci, now either find it, or allocate it */ 21552419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 21652419Sjulian if (xxxp->channel[chan].dlci == dlci) 21752419Sjulian break; 21852419Sjulian if (chan == XXX_NUM_DLCIS) { 21952419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 220139249Srik if (xxxp->channel[chan].dlci == -2) 221139249Srik break; 22252419Sjulian if (chan == XXX_NUM_DLCIS) 22352419Sjulian return (ENOBUFS); 224139249Srik xxxp->channel[chan].dlci = dlci; 22552419Sjulian } 22652419Sjulian if (xxxp->channel[chan].hook != NULL) 22752419Sjulian return (EADDRINUSE); 22870784Sjulian NG_HOOK_SET_PRIVATE(hook, xxxp->channel + chan); 22952419Sjulian xxxp->channel[chan].hook = hook; 23052419Sjulian return (0); 23152419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DOWNSTREAM) == 0) { 23252419Sjulian /* Example of simple predefined hooks. */ 23352419Sjulian /* do something specific to the downstream connection */ 23452419Sjulian xxxp->downstream_hook.hook = hook; 23570784Sjulian NG_HOOK_SET_PRIVATE(hook, &xxxp->downstream_hook); 23652419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DEBUG) == 0) { 23752419Sjulian /* do something specific to a debug connection */ 23852419Sjulian xxxp->debughook = hook; 23970784Sjulian NG_HOOK_SET_PRIVATE(hook, NULL); 24052419Sjulian } else 24152419Sjulian return (EINVAL); /* not a hook we know about */ 24252419Sjulian return(0); 24352419Sjulian} 24452419Sjulian 24552419Sjulian/* 24652419Sjulian * Get a netgraph control message. 24770700Sjulian * We actually recieve a queue item that has a pointer to the message. 24870700Sjulian * If we free the item, the message will be freed too, unless we remove 24970700Sjulian * it from the item using NGI_GET_MSG(); 25070700Sjulian * The return address is also stored in the item, as an ng_ID_t, 25170700Sjulian * accessible as NGI_RETADDR(item); 25252419Sjulian * Check it is one we understand. If needed, send a response. 25352419Sjulian * We could save the address for an async action later, but don't here. 25452419Sjulian * Always free the message. 25552419Sjulian * The response should be in a malloc'd region that the caller can 'free'. 25652419Sjulian * A response is not required. 25752419Sjulian * Theoretically you could respond defferently to old message types if 25852419Sjulian * the cookie in the header didn't match what we consider to be current 25952419Sjulian * (so that old userland programs could continue to work). 26052419Sjulian */ 26152419Sjulianstatic int 26270700Sjulianng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook) 26352419Sjulian{ 26470784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 26552419Sjulian struct ng_mesg *resp = NULL; 26652419Sjulian int error = 0; 26770700Sjulian struct ng_mesg *msg; 26852419Sjulian 26970700Sjulian NGI_GET_MSG(item, msg); 27052419Sjulian /* Deal with message according to cookie and command */ 27152419Sjulian switch (msg->header.typecookie) { 27252419Sjulian case NGM_XXX_COOKIE: 27352419Sjulian switch (msg->header.cmd) { 27452419Sjulian case NGM_XXX_GET_STATUS: 27552419Sjulian { 27652419Sjulian struct ngxxxstat *stats; 27752419Sjulian 27852419Sjulian NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); 27952419Sjulian if (!resp) { 28052419Sjulian error = ENOMEM; 28152419Sjulian break; 28252419Sjulian } 28352419Sjulian stats = (struct ngxxxstat *) resp->data; 28452419Sjulian stats->packets_in = xxxp->packets_in; 28552419Sjulian stats->packets_out = xxxp->packets_out; 28652419Sjulian break; 28752419Sjulian } 28852419Sjulian case NGM_XXX_SET_FLAG: 28952419Sjulian if (msg->header.arglen != sizeof(u_int32_t)) { 29052419Sjulian error = EINVAL; 29152419Sjulian break; 29252419Sjulian } 29352419Sjulian xxxp->flags = *((u_int32_t *) msg->data); 29452419Sjulian break; 29552419Sjulian default: 29652419Sjulian error = EINVAL; /* unknown command */ 29752419Sjulian break; 29852419Sjulian } 29952419Sjulian break; 30052419Sjulian default: 30152419Sjulian error = EINVAL; /* unknown cookie type */ 30252419Sjulian break; 30352419Sjulian } 30452419Sjulian 30552419Sjulian /* Take care of synchronous response, if any */ 30670700Sjulian NG_RESPOND_MSG(error, node, item, resp); 30752419Sjulian /* Free the message and return */ 30870700Sjulian NG_FREE_MSG(msg); 30952419Sjulian return(error); 31052419Sjulian} 31152419Sjulian 31252419Sjulian/* 31352419Sjulian * Receive data, and do something with it. 31470700Sjulian * Actually we receive a queue item which holds the data. 315131155Sjulian * If we free the item it will also free the data unless we have 316131155Sjulian * previously disassociated it using the NGI_GET_M() macro. 31752419Sjulian * Possibly send it out on another link after processing. 31852419Sjulian * Possibly do something different if it comes from different 319131155Sjulian * hooks. The caller will never free m, so if we use up this data or 320131155Sjulian * abort we must free it. 32152419Sjulian * 32252419Sjulian * If we want, we may decide to force this data to be queued and reprocessed 32369922Sjulian * at the netgraph NETISR time. 32469922Sjulian * We would do that by setting the HK_QUEUE flag on our hook. We would do that 32569922Sjulian * in the connect() method. 32652419Sjulian */ 32752419Sjulianstatic int 32870700Sjulianng_xxx_rcvdata(hook_p hook, item_p item ) 32952419Sjulian{ 33070784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 33152419Sjulian int chan = -2; 33252419Sjulian int dlci = -2; 33352419Sjulian int error; 33470700Sjulian struct mbuf *m; 33552419Sjulian 33670700Sjulian NGI_GET_M(item, m); 33770784Sjulian if (NG_HOOK_PRIVATE(hook)) { 33870784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 33970784Sjulian chan = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->channel; 34052419Sjulian if (dlci != -1) { 34152419Sjulian /* If received on a DLCI hook process for this 34252419Sjulian * channel and pass it to the downstream module. 34352419Sjulian * Normally one would add a multiplexing header at 34452419Sjulian * the front here */ 34552419Sjulian /* M_PREPEND(....) ; */ 34652419Sjulian /* mtod(m, xxxxxx)->dlci = dlci; */ 34770700Sjulian NG_FWD_NEW_DATA(error, item, 34870700Sjulian xxxp->downstream_hook.hook, m); 34952419Sjulian xxxp->packets_out++; 35052419Sjulian } else { 35152419Sjulian /* data came from the multiplexed link */ 35252419Sjulian dlci = 1; /* get dlci from header */ 35352419Sjulian /* madjust(....) *//* chop off header */ 35452419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 35552419Sjulian if (xxxp->channel[chan].dlci == dlci) 35652419Sjulian break; 35752419Sjulian if (chan == XXX_NUM_DLCIS) { 35870700Sjulian NG_FREE_ITEM(item); 35970700Sjulian NG_FREE_M(m); 36052419Sjulian return (ENETUNREACH); 36152419Sjulian } 36252419Sjulian /* If we were called at splnet, use the following: 363131155Sjulian * NG_SEND_DATA_ONLY(error, otherhook, m); if this 36452419Sjulian * node is running at some SPL other than SPLNET 36552419Sjulian * then you should use instead: error = 366131155Sjulian * ng_queueit(otherhook, m, NULL); m = NULL; 367131155Sjulian * This queues the data using the standard NETISR 368131155Sjulian * system and schedules the data to be picked 36952419Sjulian * up again once the system has moved to SPLNET and 370131155Sjulian * the processing of the data can continue. After 371131155Sjulian * these are run 'm' should be considered 37252419Sjulian * as invalid and NG_SEND_DATA actually zaps them. */ 37370700Sjulian NG_FWD_NEW_DATA(error, item, 37470700Sjulian xxxp->channel[chan].hook, m); 37552419Sjulian xxxp->packets_in++; 37652419Sjulian } 37752419Sjulian } else { 37852419Sjulian /* It's the debug hook, throw it away.. */ 37970933Sjulian if (hook == xxxp->downstream_hook.hook) { 38070700Sjulian NG_FREE_ITEM(item); 38170700Sjulian NG_FREE_M(m); 38270933Sjulian } 38352419Sjulian } 38452419Sjulian return 0; 38552419Sjulian} 38652419Sjulian 38752419Sjulian#if 0 38852419Sjulian/* 38952419Sjulian * If this were a device node, the data may have been received in response 39052419Sjulian * to some interrupt. 39152419Sjulian * in which case it would probably look as follows: 39252419Sjulian */ 39352419Sjuliandevintr() 39452419Sjulian{ 39569922Sjulian int error; 39652419Sjulian 39752419Sjulian /* get packet from device and send on */ 39852419Sjulian m = MGET(blah blah) 39969922Sjulian 40069922Sjulian NG_SEND_DATA_ONLY(error, xxxp->upstream_hook.hook, m); 40169922Sjulian /* see note above in xxx_rcvdata() */ 40269922Sjulian /* and ng_xxx_connect() */ 40352419Sjulian} 40452419Sjulian 40552419Sjulian#endif /* 0 */ 40652419Sjulian 40752419Sjulian/* 40852419Sjulian * Do local shutdown processing.. 40970700Sjulian * All our links and the name have already been removed. 41071849Sjulian * If we are a persistant device, we might refuse to go away. 41171849Sjulian * In the case of a persistant node we signal the framework that we 412132464Sjulian * are still in business by clearing the NGF_INVALID bit. However 413132464Sjulian * If we find the NGF_REALLY_DIE bit set, this means that 41471849Sjulian * we REALLY need to die (e.g. hardware removed). 41571849Sjulian * This would have been set using the NG_NODE_REALLY_DIE(node) 41671849Sjulian * macro in some device dependent function (not shown here) before 41771849Sjulian * calling ng_rmnode_self(). 41852419Sjulian */ 41952419Sjulianstatic int 42070700Sjulianng_xxx_shutdown(node_p node) 42152419Sjulian{ 42270784Sjulian const xxx_p privdata = NG_NODE_PRIVATE(node); 42352419Sjulian 42471849Sjulian#ifndef PERSISTANT_NODE 42570784Sjulian NG_NODE_SET_PRIVATE(node, NULL); 426132828Sglebius NG_NODE_UNREF(node); 42752419Sjulian FREE(privdata, M_NETGRAPH); 42852419Sjulian#else 429132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 43071849Sjulian /* 43171849Sjulian * WE came here because the widget card is being unloaded, 43271849Sjulian * so stop being persistant. 43371849Sjulian * Actually undo all the things we did on creation. 43471849Sjulian */ 43571849Sjulian NG_NODE_SET_PRIVATE(node, NULL); 43671849Sjulian NG_NODE_UNREF(privdata->node); 43771849Sjulian FREE(privdata, M_NETGRAPH); 43871849Sjulian return (0); 43971849Sjulian } 440132464Sjulian NG_NODE_REVIVE(node); /* tell ng_rmnode() we will persist */ 44152419Sjulian#endif /* PERSISTANT_NODE */ 44252419Sjulian return (0); 44352419Sjulian} 44452419Sjulian 44552419Sjulian/* 44652419Sjulian * This is called once we've already connected a new hook to the other node. 44752419Sjulian * It gives us a chance to balk at the last minute. 44852419Sjulian */ 44952419Sjulianstatic int 45052419Sjulianng_xxx_connect(hook_p hook) 45152419Sjulian{ 45269922Sjulian#if 0 45369922Sjulian /* 45469922Sjulian * If we were a driver running at other than splnet then 45569922Sjulian * we should set the QUEUE bit on the edge so that we 45669922Sjulian * will deliver by queing. 45769922Sjulian */ 45869922Sjulian if /*it is the upstream hook */ 45970784Sjulian NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 46069922Sjulian#endif 46169922Sjulian#if 0 46269922Sjulian /* 46369922Sjulian * If for some reason we want incoming date to be queued 46469922Sjulian * by the NETISR system and delivered later we can set the same bit on 46569922Sjulian * OUR hook. (maybe to allow unwinding of the stack) 46669922Sjulian */ 46769922Sjulian 46870784Sjulian if (NG_HOOK_PRIVATE(hook)) { 46969922Sjulian int dlci; 47069922Sjulian /* 47169922Sjulian * If it's dlci 1023, requeue it so that it's handled 47269922Sjulian * at a lower priority. This is how a node decides to 47369922Sjulian * defer a data message. 47469922Sjulian */ 47570784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 47669922Sjulian if (dlci == 1023) { 47770784Sjulian NG_HOOK_FORCE_QUEUE(hook); 47869922Sjulian } 47969922Sjulian#endif 48069922Sjulian /* otherwise be really amiable and just say "YUP that's OK by me! " */ 48152419Sjulian return (0); 48252419Sjulian} 48352419Sjulian 48452419Sjulian/* 48573005Sjulian * Hook disconnection 48652419Sjulian * 48752419Sjulian * For this type, removal of the last link destroys the node 48852419Sjulian */ 48952419Sjulianstatic int 49052419Sjulianng_xxx_disconnect(hook_p hook) 49152419Sjulian{ 49270784Sjulian if (NG_HOOK_PRIVATE(hook)) 49370784Sjulian ((struct XXX_hookinfo *) (NG_HOOK_PRIVATE(hook)))->hook = NULL; 49470784Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 49570784Sjulian && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */ 49670784Sjulian ng_rmnode_self(NG_HOOK_NODE(hook)); 49752419Sjulian return (0); 49852419Sjulian} 49952419Sjulian 500