ng_sample.c revision 132828
152419Sjulian 252419Sjulian/* 352419Sjulian * ng_sample.c 452419Sjulian * 552419Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc. 652419Sjulian * All rights reserved. 752419Sjulian * 852419Sjulian * Subject to the following obligations and disclaimer of warranty, use and 952419Sjulian * redistribution of this software, in source or object code forms, with or 1052419Sjulian * without modifications are expressly permitted by Whistle Communications; 1152419Sjulian * provided, however, that: 1252419Sjulian * 1. Any and all reproductions of the source or object code must include the 1352419Sjulian * copyright notice above and the following disclaimer of warranties; and 1452419Sjulian * 2. No rights are granted, in any manner or form, to use Whistle 1552419Sjulian * Communications, Inc. trademarks, including the mark "WHISTLE 1652419Sjulian * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1752419Sjulian * such appears in the above copyright notice or in the software. 1852419Sjulian * 1952419Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 2052419Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2152419Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2252419Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2352419Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2452419Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2552419Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2652419Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2752419Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2852419Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 2952419Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 3052419Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3152419Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3252419Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3352419Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3452419Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3552419Sjulian * OF SUCH DAMAGE. 3652419Sjulian * 3767506Sjulian * Author: Julian Elischer <julian@freebsd.org> 3852419Sjulian * 3952419Sjulian * $FreeBSD: head/sys/netgraph/ng_sample.c 132828 2004-07-29 08:05:02Z glebius $ 4052752Sjulian * $Whistle: ng_sample.c,v 1.13 1999/11/01 09:24:52 julian Exp $ 4152419Sjulian */ 4252419Sjulian 4352419Sjulian#include <sys/param.h> 4452419Sjulian#include <sys/systm.h> 4552419Sjulian#include <sys/kernel.h> 4652419Sjulian#include <sys/mbuf.h> 4752419Sjulian#include <sys/malloc.h> 4853997Sarchie#include <sys/ctype.h> 4952419Sjulian#include <sys/errno.h> 5052419Sjulian#include <sys/syslog.h> 5152419Sjulian 5252419Sjulian#include <netgraph/ng_message.h> 5353997Sarchie#include <netgraph/ng_parse.h> 5452419Sjulian#include <netgraph/ng_sample.h> 5552419Sjulian#include <netgraph/netgraph.h> 5652419Sjulian 5770870Sjulian/* If you do complicated mallocs you may want to do this */ 5870870Sjulian/* and use it for your mallocs */ 5970870Sjulian#ifdef NG_SEPARATE_MALLOC 6070870SjulianMALLOC_DEFINE(M_NETGRAPH_XXX, "netgraph_xxx", "netgraph xxx node "); 6170870Sjulian#else 6270870Sjulian#define M_NETGRAPH_XXX M_NETGRAPH 6370870Sjulian#endif 6470870Sjulian 6552419Sjulian/* 6652419Sjulian * This section contains the netgraph method declarations for the 6752419Sjulian * sample node. These methods define the netgraph 'type'. 6852419Sjulian */ 6952419Sjulian 7052752Sjulianstatic ng_constructor_t ng_xxx_constructor; 7152752Sjulianstatic ng_rcvmsg_t ng_xxx_rcvmsg; 7270700Sjulianstatic ng_shutdown_t ng_xxx_shutdown; 7352752Sjulianstatic ng_newhook_t ng_xxx_newhook; 7452752Sjulianstatic ng_connect_t ng_xxx_connect; 7552752Sjulianstatic ng_rcvdata_t ng_xxx_rcvdata; /* note these are both ng_rcvdata_t */ 7652752Sjulianstatic ng_disconnect_t ng_xxx_disconnect; 7752419Sjulian 7853997Sarchie/* Parse type for struct ngxxxstat */ 7997685Sarchiestatic const struct ng_parse_struct_field ng_xxx_stat_type_fields[] 8097685Sarchie = NG_XXX_STATS_TYPE_INFO; 8153997Sarchiestatic const struct ng_parse_type ng_xxx_stat_type = { 8253997Sarchie &ng_parse_struct_type, 8397685Sarchie &ng_xxx_stat_type_fields 8453997Sarchie}; 8553997Sarchie 8653997Sarchie/* List of commands and how to convert arguments to/from ASCII */ 8753997Sarchiestatic const struct ng_cmdlist ng_xxx_cmdlist[] = { 8853997Sarchie { 8953997Sarchie NGM_XXX_COOKIE, 9053997Sarchie NGM_XXX_GET_STATUS, 9153997Sarchie "getstatus", 9253997Sarchie NULL, 9353997Sarchie &ng_xxx_stat_type, 9453997Sarchie }, 9553997Sarchie { 9653997Sarchie NGM_XXX_COOKIE, 9753997Sarchie NGM_XXX_SET_FLAG, 9853997Sarchie "setflag", 9953997Sarchie &ng_parse_int32_type, 10053997Sarchie NULL 10153997Sarchie }, 10253997Sarchie { 0 } 10353997Sarchie}; 10453997Sarchie 10552419Sjulian/* Netgraph node type descriptor */ 10652419Sjulianstatic struct ng_type typestruct = { 107129823Sjulian .version = NG_ABI_VERSION, 108129823Sjulian .name = NG_XXX_NODE_TYPE, 109129823Sjulian .constructor = ng_xxx_constructor, 110129823Sjulian .rcvmsg = ng_xxx_rcvmsg, 111129823Sjulian .shutdown = ng_xxx_shutdown, 112129823Sjulian .newhook = ng_xxx_newhook, 113129823Sjulian/* .findhook = ng_xxx_findhook, */ 114129823Sjulian .connect = ng_xxx_connect, 115129823Sjulian .rcvdata = ng_xxx_rcvdata, 116129823Sjulian .disconnect = ng_xxx_disconnect, 117129823Sjulian .cmdlist = ng_xxx_cmdlist, 11852419Sjulian}; 11952419SjulianNETGRAPH_INIT(xxx, &typestruct); 12052419Sjulian 12152419Sjulian/* Information we store for each hook on each node */ 12252419Sjulianstruct XXX_hookinfo { 12352419Sjulian int dlci; /* The DLCI it represents, -1 == downstream */ 12452419Sjulian int channel; /* The channel representing this DLCI */ 12552419Sjulian hook_p hook; 12652419Sjulian}; 12752419Sjulian 12852419Sjulian/* Information we store for each node */ 12952419Sjulianstruct XXX { 13052419Sjulian struct XXX_hookinfo channel[XXX_NUM_DLCIS]; 13152419Sjulian struct XXX_hookinfo downstream_hook; 13252419Sjulian node_p node; /* back pointer to node */ 13352419Sjulian hook_p debughook; 13452419Sjulian u_int packets_in; /* packets in from downstream */ 13552419Sjulian u_int packets_out; /* packets out towards downstream */ 13652419Sjulian u_int32_t flags; 13752419Sjulian}; 13852419Sjuliantypedef struct XXX *xxx_p; 13952419Sjulian 14052419Sjulian/* 14170700Sjulian * Allocate the private data structure. The generic node has already 14270700Sjulian * been created. Link them together. We arrive with a reference to the node 14370700Sjulian * i.e. the reference count is incremented for us already. 14452419Sjulian * 14552419Sjulian * If this were a device node than this work would be done in the attach() 14652419Sjulian * routine and the constructor would return EINVAL as you should not be able 14752419Sjulian * to creatednodes that depend on hardware (unless you can add the hardware :) 14852419Sjulian */ 14952419Sjulianstatic int 15070784Sjulianng_xxx_constructor(node_p node) 15152419Sjulian{ 15252419Sjulian xxx_p privdata; 15373005Sjulian int i; 15452419Sjulian 15552419Sjulian /* Initialize private descriptor */ 15668876Sdwmalone MALLOC(privdata, xxx_p, sizeof(*privdata), M_NETGRAPH, 15768876Sdwmalone M_NOWAIT | M_ZERO); 15852419Sjulian if (privdata == NULL) 15952419Sjulian return (ENOMEM); 16052419Sjulian for (i = 0; i < XXX_NUM_DLCIS; i++) { 16152419Sjulian privdata->channel[i].dlci = -2; 16252419Sjulian privdata->channel[i].channel = i; 16352419Sjulian } 16452419Sjulian 16552419Sjulian /* Link structs together; this counts as our one reference to *nodep */ 16673005Sjulian NG_NODE_SET_PRIVATE(node, privdata); 16770784Sjulian privdata->node = node; 16852419Sjulian return (0); 16952419Sjulian} 17052419Sjulian 17152419Sjulian/* 17252419Sjulian * Give our ok for a hook to be added... 17352419Sjulian * If we are not running this might kick a device into life. 17452419Sjulian * Possibly decode information out of the hook name. 17552419Sjulian * Add the hook's private info to the hook structure. 17652419Sjulian * (if we had some). In this example, we assume that there is a 17752419Sjulian * an array of structs, called 'channel' in the private info, 17852419Sjulian * one for each active channel. The private 17952419Sjulian * pointer of each hook points to the appropriate XXX_hookinfo struct 18052419Sjulian * so that the source of an input packet is easily identified. 18152419Sjulian * (a dlci is a frame relay channel) 18252419Sjulian */ 18352419Sjulianstatic int 18452419Sjulianng_xxx_newhook(node_p node, hook_p hook, const char *name) 18552419Sjulian{ 18670784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 18752419Sjulian const char *cp; 18852419Sjulian int dlci = 0; 18952419Sjulian int chan; 19052419Sjulian 19152419Sjulian#if 0 19252419Sjulian /* Possibly start up the device if it's not already going */ 19352419Sjulian if ((xxxp->flags & SCF_RUNNING) == 0) { 19452419Sjulian ng_xxx_start_hardware(xxxp); 19552419Sjulian } 19652419Sjulian#endif 19752419Sjulian 19852419Sjulian /* Example of how one might use hooks with embedded numbers: All 19952419Sjulian * hooks start with 'dlci' and have a decimal trailing channel 20052419Sjulian * number up to 4 digits Use the leadin defined int he associated .h 20152419Sjulian * file. */ 20252816Sarchie if (strncmp(name, 20352816Sarchie NG_XXX_HOOK_DLCI_LEADIN, strlen(NG_XXX_HOOK_DLCI_LEADIN)) == 0) { 20453648Sarchie char *eptr; 20552816Sarchie 20652419Sjulian cp = name + sizeof(NG_XXX_HOOK_DLCI_LEADIN); 20752816Sarchie if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) 20852419Sjulian return (EINVAL); 20952816Sarchie dlci = (int)strtoul(cp, &eptr, 10); 21052816Sarchie if (*eptr != '\0' || dlci < 0 || dlci > 1023) 21152816Sarchie return (EINVAL); 21252816Sarchie 21352419Sjulian /* We have a dlci, now either find it, or allocate it */ 21452419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 21552419Sjulian if (xxxp->channel[chan].dlci == dlci) 21652419Sjulian break; 21752419Sjulian if (chan == XXX_NUM_DLCIS) { 21852419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 21952419Sjulian if (xxxp->channel[chan].dlci != -2) 22052419Sjulian continue; 22152419Sjulian if (chan == XXX_NUM_DLCIS) 22252419Sjulian return (ENOBUFS); 22352419Sjulian } 22452419Sjulian if (xxxp->channel[chan].hook != NULL) 22552419Sjulian return (EADDRINUSE); 22670784Sjulian NG_HOOK_SET_PRIVATE(hook, xxxp->channel + chan); 22752419Sjulian xxxp->channel[chan].hook = hook; 22852419Sjulian return (0); 22952419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DOWNSTREAM) == 0) { 23052419Sjulian /* Example of simple predefined hooks. */ 23152419Sjulian /* do something specific to the downstream connection */ 23252419Sjulian xxxp->downstream_hook.hook = hook; 23370784Sjulian NG_HOOK_SET_PRIVATE(hook, &xxxp->downstream_hook); 23452419Sjulian } else if (strcmp(name, NG_XXX_HOOK_DEBUG) == 0) { 23552419Sjulian /* do something specific to a debug connection */ 23652419Sjulian xxxp->debughook = hook; 23770784Sjulian NG_HOOK_SET_PRIVATE(hook, NULL); 23852419Sjulian } else 23952419Sjulian return (EINVAL); /* not a hook we know about */ 24052419Sjulian return(0); 24152419Sjulian} 24252419Sjulian 24352419Sjulian/* 24452419Sjulian * Get a netgraph control message. 24570700Sjulian * We actually recieve a queue item that has a pointer to the message. 24670700Sjulian * If we free the item, the message will be freed too, unless we remove 24770700Sjulian * it from the item using NGI_GET_MSG(); 24870700Sjulian * The return address is also stored in the item, as an ng_ID_t, 24970700Sjulian * accessible as NGI_RETADDR(item); 25052419Sjulian * Check it is one we understand. If needed, send a response. 25152419Sjulian * We could save the address for an async action later, but don't here. 25252419Sjulian * Always free the message. 25352419Sjulian * The response should be in a malloc'd region that the caller can 'free'. 25452419Sjulian * A response is not required. 25552419Sjulian * Theoretically you could respond defferently to old message types if 25652419Sjulian * the cookie in the header didn't match what we consider to be current 25752419Sjulian * (so that old userland programs could continue to work). 25852419Sjulian */ 25952419Sjulianstatic int 26070700Sjulianng_xxx_rcvmsg(node_p node, item_p item, hook_p lasthook) 26152419Sjulian{ 26270784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(node); 26352419Sjulian struct ng_mesg *resp = NULL; 26452419Sjulian int error = 0; 26570700Sjulian struct ng_mesg *msg; 26652419Sjulian 26770700Sjulian NGI_GET_MSG(item, msg); 26852419Sjulian /* Deal with message according to cookie and command */ 26952419Sjulian switch (msg->header.typecookie) { 27052419Sjulian case NGM_XXX_COOKIE: 27152419Sjulian switch (msg->header.cmd) { 27252419Sjulian case NGM_XXX_GET_STATUS: 27352419Sjulian { 27452419Sjulian struct ngxxxstat *stats; 27552419Sjulian 27652419Sjulian NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT); 27752419Sjulian if (!resp) { 27852419Sjulian error = ENOMEM; 27952419Sjulian break; 28052419Sjulian } 28152419Sjulian stats = (struct ngxxxstat *) resp->data; 28252419Sjulian stats->packets_in = xxxp->packets_in; 28352419Sjulian stats->packets_out = xxxp->packets_out; 28452419Sjulian break; 28552419Sjulian } 28652419Sjulian case NGM_XXX_SET_FLAG: 28752419Sjulian if (msg->header.arglen != sizeof(u_int32_t)) { 28852419Sjulian error = EINVAL; 28952419Sjulian break; 29052419Sjulian } 29152419Sjulian xxxp->flags = *((u_int32_t *) msg->data); 29252419Sjulian break; 29352419Sjulian default: 29452419Sjulian error = EINVAL; /* unknown command */ 29552419Sjulian break; 29652419Sjulian } 29752419Sjulian break; 29852419Sjulian default: 29952419Sjulian error = EINVAL; /* unknown cookie type */ 30052419Sjulian break; 30152419Sjulian } 30252419Sjulian 30352419Sjulian /* Take care of synchronous response, if any */ 30470700Sjulian NG_RESPOND_MSG(error, node, item, resp); 30552419Sjulian /* Free the message and return */ 30670700Sjulian NG_FREE_MSG(msg); 30752419Sjulian return(error); 30852419Sjulian} 30952419Sjulian 31052419Sjulian/* 31152419Sjulian * Receive data, and do something with it. 31270700Sjulian * Actually we receive a queue item which holds the data. 313131155Sjulian * If we free the item it will also free the data unless we have 314131155Sjulian * previously disassociated it using the NGI_GET_M() macro. 31552419Sjulian * Possibly send it out on another link after processing. 31652419Sjulian * Possibly do something different if it comes from different 317131155Sjulian * hooks. The caller will never free m, so if we use up this data or 318131155Sjulian * abort we must free it. 31952419Sjulian * 32052419Sjulian * If we want, we may decide to force this data to be queued and reprocessed 32169922Sjulian * at the netgraph NETISR time. 32269922Sjulian * We would do that by setting the HK_QUEUE flag on our hook. We would do that 32369922Sjulian * in the connect() method. 32452419Sjulian */ 32552419Sjulianstatic int 32670700Sjulianng_xxx_rcvdata(hook_p hook, item_p item ) 32752419Sjulian{ 32870784Sjulian const xxx_p xxxp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 32952419Sjulian int chan = -2; 33052419Sjulian int dlci = -2; 33152419Sjulian int error; 33270700Sjulian struct mbuf *m; 33352419Sjulian 33470700Sjulian NGI_GET_M(item, m); 33570784Sjulian if (NG_HOOK_PRIVATE(hook)) { 33670784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 33770784Sjulian chan = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->channel; 33852419Sjulian if (dlci != -1) { 33952419Sjulian /* If received on a DLCI hook process for this 34052419Sjulian * channel and pass it to the downstream module. 34152419Sjulian * Normally one would add a multiplexing header at 34252419Sjulian * the front here */ 34352419Sjulian /* M_PREPEND(....) ; */ 34452419Sjulian /* mtod(m, xxxxxx)->dlci = dlci; */ 34570700Sjulian NG_FWD_NEW_DATA(error, item, 34670700Sjulian xxxp->downstream_hook.hook, m); 34752419Sjulian xxxp->packets_out++; 34852419Sjulian } else { 34952419Sjulian /* data came from the multiplexed link */ 35052419Sjulian dlci = 1; /* get dlci from header */ 35152419Sjulian /* madjust(....) *//* chop off header */ 35252419Sjulian for (chan = 0; chan < XXX_NUM_DLCIS; chan++) 35352419Sjulian if (xxxp->channel[chan].dlci == dlci) 35452419Sjulian break; 35552419Sjulian if (chan == XXX_NUM_DLCIS) { 35670700Sjulian NG_FREE_ITEM(item); 35770700Sjulian NG_FREE_M(m); 35852419Sjulian return (ENETUNREACH); 35952419Sjulian } 36052419Sjulian /* If we were called at splnet, use the following: 361131155Sjulian * NG_SEND_DATA_ONLY(error, otherhook, m); if this 36252419Sjulian * node is running at some SPL other than SPLNET 36352419Sjulian * then you should use instead: error = 364131155Sjulian * ng_queueit(otherhook, m, NULL); m = NULL; 365131155Sjulian * This queues the data using the standard NETISR 366131155Sjulian * system and schedules the data to be picked 36752419Sjulian * up again once the system has moved to SPLNET and 368131155Sjulian * the processing of the data can continue. After 369131155Sjulian * these are run 'm' should be considered 37052419Sjulian * as invalid and NG_SEND_DATA actually zaps them. */ 37170700Sjulian NG_FWD_NEW_DATA(error, item, 37270700Sjulian xxxp->channel[chan].hook, m); 37352419Sjulian xxxp->packets_in++; 37452419Sjulian } 37552419Sjulian } else { 37652419Sjulian /* It's the debug hook, throw it away.. */ 37770933Sjulian if (hook == xxxp->downstream_hook.hook) { 37870700Sjulian NG_FREE_ITEM(item); 37970700Sjulian NG_FREE_M(m); 38070933Sjulian } 38152419Sjulian } 38252419Sjulian return 0; 38352419Sjulian} 38452419Sjulian 38552419Sjulian#if 0 38652419Sjulian/* 38752419Sjulian * If this were a device node, the data may have been received in response 38852419Sjulian * to some interrupt. 38952419Sjulian * in which case it would probably look as follows: 39052419Sjulian */ 39152419Sjuliandevintr() 39252419Sjulian{ 39369922Sjulian int error; 39452419Sjulian * here */ 39552419Sjulian 39652419Sjulian /* get packet from device and send on */ 39752419Sjulian m = MGET(blah blah) 39869922Sjulian 39969922Sjulian NG_SEND_DATA_ONLY(error, xxxp->upstream_hook.hook, m); 40069922Sjulian /* see note above in xxx_rcvdata() */ 40169922Sjulian /* and ng_xxx_connect() */ 40252419Sjulian} 40352419Sjulian 40452419Sjulian#endif /* 0 */ 40552419Sjulian 40652419Sjulian/* 40752419Sjulian * Do local shutdown processing.. 40870700Sjulian * All our links and the name have already been removed. 40971849Sjulian * If we are a persistant device, we might refuse to go away. 41071849Sjulian * In the case of a persistant node we signal the framework that we 411132464Sjulian * are still in business by clearing the NGF_INVALID bit. However 412132464Sjulian * If we find the NGF_REALLY_DIE bit set, this means that 41371849Sjulian * we REALLY need to die (e.g. hardware removed). 41471849Sjulian * This would have been set using the NG_NODE_REALLY_DIE(node) 41571849Sjulian * macro in some device dependent function (not shown here) before 41671849Sjulian * calling ng_rmnode_self(). 41752419Sjulian */ 41852419Sjulianstatic int 41970700Sjulianng_xxx_shutdown(node_p node) 42052419Sjulian{ 42170784Sjulian const xxx_p privdata = NG_NODE_PRIVATE(node); 42252419Sjulian 42371849Sjulian#ifndef PERSISTANT_NODE 42470784Sjulian NG_NODE_SET_PRIVATE(node, NULL); 425132828Sglebius NG_NODE_UNREF(node); 42652419Sjulian FREE(privdata, M_NETGRAPH); 42752419Sjulian#else 428132464Sjulian if (node->nd_flags & NGF_REALLY_DIE) { 42971849Sjulian /* 43071849Sjulian * WE came here because the widget card is being unloaded, 43171849Sjulian * so stop being persistant. 43271849Sjulian * Actually undo all the things we did on creation. 43371849Sjulian */ 43471849Sjulian NG_NODE_SET_PRIVATE(node, NULL); 43571849Sjulian NG_NODE_UNREF(privdata->node); 43671849Sjulian FREE(privdata, M_NETGRAPH); 43771849Sjulian return (0); 43871849Sjulian } 439132464Sjulian NG_NODE_REVIVE(node); /* tell ng_rmnode() we will persist */ 44052419Sjulian#endif /* PERSISTANT_NODE */ 44152419Sjulian return (0); 44252419Sjulian} 44352419Sjulian 44452419Sjulian/* 44552419Sjulian * This is called once we've already connected a new hook to the other node. 44652419Sjulian * It gives us a chance to balk at the last minute. 44752419Sjulian */ 44852419Sjulianstatic int 44952419Sjulianng_xxx_connect(hook_p hook) 45052419Sjulian{ 45169922Sjulian#if 0 45269922Sjulian /* 45369922Sjulian * If we were a driver running at other than splnet then 45469922Sjulian * we should set the QUEUE bit on the edge so that we 45569922Sjulian * will deliver by queing. 45669922Sjulian */ 45769922Sjulian if /*it is the upstream hook */ 45870784Sjulian NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 45969922Sjulian#endif 46069922Sjulian#if 0 46169922Sjulian /* 46269922Sjulian * If for some reason we want incoming date to be queued 46369922Sjulian * by the NETISR system and delivered later we can set the same bit on 46469922Sjulian * OUR hook. (maybe to allow unwinding of the stack) 46569922Sjulian */ 46669922Sjulian 46770784Sjulian if (NG_HOOK_PRIVATE(hook)) { 46869922Sjulian int dlci; 46969922Sjulian /* 47069922Sjulian * If it's dlci 1023, requeue it so that it's handled 47169922Sjulian * at a lower priority. This is how a node decides to 47269922Sjulian * defer a data message. 47369922Sjulian */ 47470784Sjulian dlci = ((struct XXX_hookinfo *) NG_HOOK_PRIVATE(hook))->dlci; 47569922Sjulian if (dlci == 1023) { 47670784Sjulian NG_HOOK_FORCE_QUEUE(hook); 47769922Sjulian } 47869922Sjulian#endif 47969922Sjulian /* otherwise be really amiable and just say "YUP that's OK by me! " */ 48052419Sjulian return (0); 48152419Sjulian} 48252419Sjulian 48352419Sjulian/* 48473005Sjulian * Hook disconnection 48552419Sjulian * 48652419Sjulian * For this type, removal of the last link destroys the node 48752419Sjulian */ 48852419Sjulianstatic int 48952419Sjulianng_xxx_disconnect(hook_p hook) 49052419Sjulian{ 49170784Sjulian if (NG_HOOK_PRIVATE(hook)) 49270784Sjulian ((struct XXX_hookinfo *) (NG_HOOK_PRIVATE(hook)))->hook = NULL; 49370784Sjulian if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 49470784Sjulian && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */ 49570784Sjulian ng_rmnode_self(NG_HOOK_NODE(hook)); 49652419Sjulian return (0); 49752419Sjulian} 49852419Sjulian 499