1186481Sjulian/*
2186481Sjulian * ng_ether_echo.c
3186481Sjulian */
4186481Sjulian
5186481Sjulian/*-
6186481Sjulian * Copyright (c) 1996-1999 Whistle Communications, Inc.
7186481Sjulian * All rights reserved.
8186481Sjulian *
9186481Sjulian * Subject to the following obligations and disclaimer of warranty, use and
10186481Sjulian * redistribution of this software, in source or object code forms, with or
11186481Sjulian * without modifications are expressly permitted by Whistle Communications;
12186481Sjulian * provided, however, that:
13186481Sjulian * 1. Any and all reproductions of the source or object code must include the
14186481Sjulian *    copyright notice above and the following disclaimer of warranties; and
15186481Sjulian * 2. No rights are granted, in any manner or form, to use Whistle
16186481Sjulian *    Communications, Inc. trademarks, including the mark "WHISTLE
17186481Sjulian *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
18186481Sjulian *    such appears in the above copyright notice or in the software.
19186481Sjulian *
20186481Sjulian * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
21186481Sjulian * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
22186481Sjulian * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
23186481Sjulian * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
24186481Sjulian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
25186481Sjulian * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
26186481Sjulian * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
27186481Sjulian * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
28186481Sjulian * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
29186481Sjulian * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
30186481Sjulian * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
31186481Sjulian * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
32186481Sjulian * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
33186481Sjulian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34186481Sjulian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35186481Sjulian * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
36186481Sjulian * OF SUCH DAMAGE.
37186481Sjulian *
38186481Sjulian * Author: Julian Elisher <julian@freebsd.org>
39186481Sjulian *
40186481Sjulian * $FreeBSD$
41186481Sjulian * $Whistle: ng_echo.c,v 1.13 1999/11/01 09:24:51 julian Exp $
42186481Sjulian */
43186481Sjulian
44186481Sjulian/*
45186481Sjulian * Netgraph "ether_echo" node
46186481Sjulian *
47186481Sjulian * This node simply bounces data and messages back to whence they came.
48186481Sjulian * However it swaps the source and destination ether fields.
49186481Sjulian * No testing is done!
50186481Sjulian */
51186481Sjulian
52186481Sjulian#include <sys/param.h>
53186481Sjulian#include <sys/systm.h>
54186481Sjulian#include <sys/kernel.h>
55186481Sjulian#include <sys/malloc.h>
56186481Sjulian#include <sys/mbuf.h>
57186481Sjulian#include <netgraph/ng_message.h>
58186481Sjulian#include <netgraph/netgraph.h>
59186481Sjulian#include <netgraph/ng_ether_echo.h>
60186481Sjulian
61186481Sjulian#include <net/ethernet.h>
62186481Sjulian
63186481Sjulian/* Netgraph methods */
64186481Sjulianstatic ng_constructor_t	ngee_cons;
65186481Sjulianstatic ng_rcvmsg_t	ngee_rcvmsg;
66186481Sjulianstatic ng_rcvdata_t	ngee_rcvdata;
67186481Sjulianstatic ng_disconnect_t	ngee_disconnect;
68186481Sjulian
69186481Sjulian/* Netgraph type */
70186481Sjulianstatic struct ng_type typestruct = {
71186481Sjulian	.version =	NG_ABI_VERSION,
72186481Sjulian	.name =		NG_ETHER_ECHO_NODE_TYPE,
73186481Sjulian	.constructor =	ngee_cons,
74186481Sjulian	.rcvmsg =	ngee_rcvmsg,
75186481Sjulian	.rcvdata =	ngee_rcvdata,
76186481Sjulian	.disconnect =	ngee_disconnect,
77186481Sjulian};
78186481SjulianNETGRAPH_INIT(ether_echo, &typestruct);
79186481Sjulian
80186481Sjulianstatic int
81186481Sjulianngee_cons(node_p node)
82186481Sjulian{
83186481Sjulian	return (0);
84186481Sjulian}
85186481Sjulian
86186481Sjulian/*
87186481Sjulian * Receive control message. We just bounce it back as a reply.
88186481Sjulian */
89186481Sjulianstatic int
90186481Sjulianngee_rcvmsg(node_p node, item_p item, hook_p lasthook)
91186481Sjulian{
92186481Sjulian	struct ng_mesg *msg;
93186481Sjulian	int error = 0;
94186481Sjulian
95186481Sjulian	NGI_GET_MSG(item, msg);
96186481Sjulian	msg->header.flags |= NGF_RESP;
97186481Sjulian	NG_RESPOND_MSG(error, node, item, msg);
98186481Sjulian	return (error);
99186481Sjulian}
100186481Sjulian
101186481Sjulian/*
102186481Sjulian * Receive data
103186481Sjulian */
104186481Sjulianstatic int
105186481Sjulianngee_rcvdata(hook_p hook, item_p item)
106186481Sjulian{
107186481Sjulian	int error;
108186481Sjulian	struct mbuf *m;
109186481Sjulian
110186481Sjulian	struct ether_header *eh;
111186481Sjulian	struct ether_addr tmpaddr;
112186481Sjulian
113186481Sjulian	/* Make sure we have an entire header */
114186481Sjulian	NGI_GET_M(item, m);
115186481Sjulian	if (m->m_len < sizeof(*eh) ) {
116186481Sjulian		m = m_pullup(m, sizeof(*eh));
117186481Sjulian		if (m == NULL) {
118186481Sjulian			NG_FREE_ITEM(item);
119186481Sjulian			return(EINVAL);
120186481Sjulian		}
121186481Sjulian	}
122186481Sjulian	eh = mtod(m, struct ether_header *);
123186481Sjulian
124186481Sjulian	/* swap the source and destination fields */
125186481Sjulian	bcopy(eh->ether_dhost, &tmpaddr, ETHER_ADDR_LEN);
126186481Sjulian	bcopy(eh->ether_shost, eh->ether_dhost, ETHER_ADDR_LEN);
127186481Sjulian	bcopy(&tmpaddr, eh->ether_shost, ETHER_ADDR_LEN);
128186481Sjulian
129186481Sjulian	NG_FWD_NEW_DATA(error, item, hook, m);
130186481Sjulian	return (error);
131186481Sjulian}
132186481Sjulian
133186481Sjulian/*
134186481Sjulian * Removal of the last link destroys the nodeo
135186481Sjulian */
136186481Sjulianstatic int
137186481Sjulianngee_disconnect(hook_p hook)
138186481Sjulian{
139186481Sjulian	if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
140186481Sjulian	&& (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
141186481Sjulian		ng_rmnode_self(NG_HOOK_NODE(hook));
142186481Sjulian	}
143186481Sjulian	return (0);
144186481Sjulian}
145186481Sjulian
146