ng_UI.c revision 184205
11638Srgrimes/* 21638Srgrimes * ng_UI.c 31638Srgrimes */ 41638Srgrimes 51638Srgrimes/*- 61638Srgrimes * Copyright (c) 1996-1999 Whistle Communications, Inc. 71638Srgrimes * All rights reserved. 81638Srgrimes * 91638Srgrimes * Subject to the following obligations and disclaimer of warranty, use and 101638Srgrimes * redistribution of this software, in source or object code forms, with or 111638Srgrimes * without modifications are expressly permitted by Whistle Communications; 121638Srgrimes * provided, however, that: 131638Srgrimes * 1. Any and all reproductions of the source or object code must include the 141638Srgrimes * copyright notice above and the following disclaimer of warranties; and 151638Srgrimes * 2. No rights are granted, in any manner or form, to use Whistle 161638Srgrimes * Communications, Inc. trademarks, including the mark "WHISTLE 171638Srgrimes * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 181638Srgrimes * such appears in the above copyright notice or in the software. 191638Srgrimes * 201638Srgrimes * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 211638Srgrimes * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 221638Srgrimes * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 231638Srgrimes * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 241638Srgrimes * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 251638Srgrimes * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 261638Srgrimes * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 271638Srgrimes * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 281638Srgrimes * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 291638Srgrimes * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 301638Srgrimes * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 311638Srgrimes * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 321638Srgrimes * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3350476Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 341638Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 351638Srgrimes * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 361638Srgrimes * OF SUCH DAMAGE. 371638Srgrimes * 381638Srgrimes * Author: Julian Elischer <julian@freebsd.org> 391638Srgrimes * 401638Srgrimes * $FreeBSD: head/sys/netgraph/ng_UI.c 184205 2008-10-23 15:53:51Z des $ 411638Srgrimes * $Whistle: ng_UI.c,v 1.14 1999/11/01 09:24:51 julian Exp $ 421638Srgrimes */ 431638Srgrimes 441638Srgrimes#include <sys/param.h> 451638Srgrimes#include <sys/systm.h> 461638Srgrimes#include <sys/errno.h> 471638Srgrimes#include <sys/kernel.h> 481638Srgrimes#include <sys/malloc.h> 491638Srgrimes#include <sys/mbuf.h> 501638Srgrimes#include <sys/errno.h> 511638Srgrimes 521638Srgrimes 531638Srgrimes#include <netgraph/ng_message.h> 541638Srgrimes#include <netgraph/netgraph.h> 551638Srgrimes#include <netgraph/ng_UI.h> 561638Srgrimes 571638Srgrimes/* 581638Srgrimes * DEFINITIONS 591638Srgrimes */ 601638Srgrimes 611638Srgrimes/* Everything, starting with sdlc on has defined UI as 0x03 */ 621638Srgrimes#define HDLC_UI 0x03 631638Srgrimes 641638Srgrimes/* Node private data */ 651638Srgrimesstruct ng_UI_private { 661638Srgrimes hook_p downlink; 671638Srgrimes hook_p uplink; 681638Srgrimes}; 691638Srgrimestypedef struct ng_UI_private *priv_p; 701638Srgrimes 711638Srgrimes/* Netgraph node methods */ 721638Srgrimesstatic ng_constructor_t ng_UI_constructor; 731638Srgrimesstatic ng_rcvmsg_t ng_UI_rcvmsg; 741638Srgrimesstatic ng_shutdown_t ng_UI_shutdown; 751638Srgrimesstatic ng_newhook_t ng_UI_newhook; 761638Srgrimesstatic ng_rcvdata_t ng_UI_rcvdata; 771638Srgrimesstatic ng_disconnect_t ng_UI_disconnect; 781638Srgrimes 791638Srgrimes/* Node type descriptor */ 801638Srgrimesstatic struct ng_type typestruct = { 811638Srgrimes .version = NG_ABI_VERSION, 821638Srgrimes .name = NG_UI_NODE_TYPE, 831638Srgrimes .constructor = ng_UI_constructor, 841638Srgrimes .rcvmsg = ng_UI_rcvmsg, 851638Srgrimes .shutdown = ng_UI_shutdown, 861638Srgrimes .newhook = ng_UI_newhook, 871638Srgrimes .rcvdata = ng_UI_rcvdata, 881638Srgrimes .disconnect = ng_UI_disconnect, 891638Srgrimes}; 901638SrgrimesNETGRAPH_INIT(UI, &typestruct); 911638Srgrimes 921638Srgrimes/************************************************************************ 931638Srgrimes NETGRAPH NODE STUFF 941638Srgrimes ************************************************************************/ 951638Srgrimes 961638Srgrimes/* 971638Srgrimes * Create a newborn node. We start with an implicit reference. 981638Srgrimes */ 991638Srgrimes 1001638Srgrimesstatic int 1011638Srgrimesng_UI_constructor(node_p node) 1021638Srgrimes{ 1031638Srgrimes priv_p priv; 1041638Srgrimes 1051638Srgrimes /* Allocate private structure */ 1061638Srgrimes priv = malloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 1071638Srgrimes if (priv == NULL) { 1081638Srgrimes return (ENOMEM); 1091638Srgrimes } 1101638Srgrimes NG_NODE_SET_PRIVATE(node, priv); 1111638Srgrimes return (0); 1121638Srgrimes} 1131638Srgrimes 1141638Srgrimes/* 1151638Srgrimes * Give our ok for a hook to be added 1161638Srgrimes */ 1171638Srgrimesstatic int 1181638Srgrimesng_UI_newhook(node_p node, hook_p hook, const char *name) 1191638Srgrimes{ 1201638Srgrimes const priv_p priv = NG_NODE_PRIVATE(node); 1211638Srgrimes 1221638Srgrimes if (!strcmp(name, NG_UI_HOOK_DOWNSTREAM)) { 1231638Srgrimes if (priv->downlink) 1241638Srgrimes return (EISCONN); 1251638Srgrimes priv->downlink = hook; 1261638Srgrimes } else if (!strcmp(name, NG_UI_HOOK_UPSTREAM)) { 1271638Srgrimes if (priv->uplink) 1281638Srgrimes return (EISCONN); 1291638Srgrimes priv->uplink = hook; 1301638Srgrimes } else 1311638Srgrimes return (EINVAL); 1321638Srgrimes return (0); 1331638Srgrimes} 1341638Srgrimes 1351638Srgrimes/* 1361638Srgrimes * Receive a control message 1371638Srgrimes */ 1381638Srgrimesstatic int 1391638Srgrimesng_UI_rcvmsg(node_p node, item_p item, hook_p lasthook) 1401638Srgrimes{ 1411638Srgrimes int error; 1421638Srgrimes const priv_p priv = NG_NODE_PRIVATE(node); 1431638Srgrimes struct ng_mesg *msg; 1441638Srgrimes 1451638Srgrimes msg = NGI_MSG(item); /* only peeking */ 1461638Srgrimes if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) { 1471638Srgrimes if (lasthook == priv->downlink) { 1481638Srgrimes if (priv->uplink) { 1491638Srgrimes NG_FWD_ITEM_HOOK(error, item, priv->uplink); 1501638Srgrimes return (error); 1511638Srgrimes } 15222188Sache } else { 1531638Srgrimes if (priv->downlink) { 1541638Srgrimes NG_FWD_ITEM_HOOK(error, item, priv->downlink); 1551638Srgrimes return (error); 1561638Srgrimes } 1571638Srgrimes } 1581638Srgrimes } 1591638Srgrimes 1601638Srgrimes NG_FREE_ITEM(item); 1611638Srgrimes return (EINVAL); 1621638Srgrimes} 1631638Srgrimes 1641638Srgrimes#define MAX_ENCAPS_HDR 1 1651638Srgrimes#define ERROUT(x) do { error = (x); goto done; } while (0) 1661638Srgrimes 16722188Sache/* 1681638Srgrimes * Receive a data frame 1691638Srgrimes */ 1701638Srgrimesstatic int 1711638Srgrimesng_UI_rcvdata(hook_p hook, item_p item) 1721638Srgrimes{ 1731638Srgrimes const node_p node = NG_HOOK_NODE(hook); 1741638Srgrimes const priv_p priv = NG_NODE_PRIVATE(node); 1751638Srgrimes struct mbuf *m; 1761638Srgrimes int error = 0; 1771638Srgrimes 1781638Srgrimes NGI_GET_M(item, m); 1791638Srgrimes if (hook == priv->downlink) { 1801638Srgrimes u_char *start, *ptr; 1811638Srgrimes 18222188Sache if (m->m_len < MAX_ENCAPS_HDR 1831638Srgrimes && !(m = m_pullup(m, MAX_ENCAPS_HDR))) 1841638Srgrimes ERROUT(ENOBUFS); 1851638Srgrimes ptr = start = mtod(m, u_char *); 1861638Srgrimes 1871638Srgrimes /* Must be UI frame */ 1881638Srgrimes if (*ptr++ != HDLC_UI) 1891638Srgrimes ERROUT(0); 1901638Srgrimes 1911638Srgrimes m_adj(m, ptr - start); 1921638Srgrimes NG_FWD_NEW_DATA(error, item, priv->uplink, m); /* m -> NULL */ 1931638Srgrimes } else if (hook == priv->uplink) { 1941638Srgrimes M_PREPEND(m, 1, M_DONTWAIT); /* Prepend IP NLPID */ 1951638Srgrimes if (!m) 1961638Srgrimes ERROUT(ENOBUFS); 1971638Srgrimes mtod(m, u_char *)[0] = HDLC_UI; 1981638Srgrimes NG_FWD_NEW_DATA(error, item, priv->downlink, m); /* m -> NULL */ 1991638Srgrimes } else 2001638Srgrimes panic(__func__); 2011638Srgrimes 20222188Sachedone: 2031638Srgrimes NG_FREE_M(m); /* does nothing if m == NULL */ 2041638Srgrimes if (item) 2051638Srgrimes NG_FREE_ITEM(item); 2061638Srgrimes return (error); 2071638Srgrimes} 2081638Srgrimes 2091638Srgrimes/* 2101638Srgrimes * Shutdown node 2111638Srgrimes */ 2121638Srgrimesstatic int 2131638Srgrimesng_UI_shutdown(node_p node) 2141638Srgrimes{ 2151638Srgrimes const priv_p priv = NG_NODE_PRIVATE(node); 2161638Srgrimes 21722188Sache /* Take down netgraph node */ 2181638Srgrimes free(priv, M_NETGRAPH); 2191638Srgrimes NG_NODE_SET_PRIVATE(node, NULL); 2201638Srgrimes NG_NODE_UNREF(node); 2211638Srgrimes return (0); 2221638Srgrimes} 2231638Srgrimes 2241638Srgrimes/* 2251638Srgrimes * Hook disconnection 2261638Srgrimes */ 2271638Srgrimesstatic int 2281638Srgrimesng_UI_disconnect(hook_p hook) 2291638Srgrimes{ 2301638Srgrimes const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 2311638Srgrimes 2321638Srgrimes if (hook == priv->downlink) 2331638Srgrimes priv->downlink = NULL; 2341638Srgrimes else if (hook == priv->uplink) 2351638Srgrimes priv->uplink = NULL; 2361638Srgrimes else 2371638Srgrimes panic(__func__); 2381638Srgrimes /* 2391638Srgrimes * If we are not already shutting down, 2401638Srgrimes * and we have no more hooks, then DO shut down. 2411638Srgrimes */ 2421638Srgrimes if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) 2431638Srgrimes && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { 2441638Srgrimes ng_rmnode_self(NG_HOOK_NODE(hook)); 2451638Srgrimes } 2461638Srgrimes return (0); 2471638Srgrimes} 2481638Srgrimes 24922188Sache