1/*
2 * Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 */
8
9
10#include <net_buffer.h>
11#include <net_device.h>
12#include <net_stack.h>
13
14#include <KernelExport.h>
15
16#include <net/if.h>
17#include <net/if_types.h>
18#include <net/if_media.h>
19#include <new>
20#include <stdlib.h>
21#include <string.h>
22
23
24struct loopback_device : net_device {
25};
26
27
28struct net_buffer_module_info *gBufferModule;
29static struct net_stack_module_info *sStackModule;
30
31
32//	#pragma mark -
33
34
35status_t
36loopback_init(const char *name, net_device **_device)
37{
38	loopback_device *device;
39
40	if (strncmp(name, "loop", 4))
41		return B_BAD_VALUE;
42
43	status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
44	if (status < B_OK)
45		return status;
46
47	status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
48	if (status < B_OK)
49		goto err1;
50
51	device = new (std::nothrow) loopback_device;
52	if (device == NULL) {
53		status = B_NO_MEMORY;
54		goto err2;
55	}
56
57	memset(device, 0, sizeof(loopback_device));
58
59	strcpy(device->name, name);
60	device->flags = IFF_LOOPBACK | IFF_LINK;
61	device->type = IFT_LOOP;
62	device->mtu = 65536;
63	device->media = IFM_ACTIVE;
64
65	*_device = device;
66	return B_OK;
67
68err2:
69	put_module(NET_BUFFER_MODULE_NAME);
70err1:
71	put_module(NET_STACK_MODULE_NAME);
72	return status;
73}
74
75
76status_t
77loopback_uninit(net_device *_device)
78{
79	loopback_device *device = (loopback_device *)_device;
80
81	put_module(NET_STACK_MODULE_NAME);
82	put_module(NET_BUFFER_MODULE_NAME);
83	delete device;
84
85	return B_OK;
86}
87
88
89status_t
90loopback_up(net_device *device)
91{
92	return B_OK;
93}
94
95
96void
97loopback_down(net_device *device)
98{
99}
100
101
102status_t
103loopback_control(net_device *device, int32 op, void *argument,
104	size_t length)
105{
106	return B_BAD_VALUE;
107}
108
109
110status_t
111loopback_send_data(net_device *device, net_buffer *buffer)
112{
113	return sStackModule->device_enqueue_buffer(device, buffer);
114}
115
116
117status_t
118loopback_set_mtu(net_device *device, size_t mtu)
119{
120	if (mtu > 65536 || mtu < 16)
121		return B_BAD_VALUE;
122
123	device->mtu = mtu;
124	return B_OK;
125}
126
127
128status_t
129loopback_set_promiscuous(net_device *device, bool promiscuous)
130{
131	return EOPNOTSUPP;
132}
133
134
135status_t
136loopback_set_media(net_device *device, uint32 media)
137{
138	return EOPNOTSUPP;
139}
140
141
142status_t
143loopback_add_multicast(net_device *device, const sockaddr *address)
144{
145	return B_OK;
146}
147
148
149status_t
150loopback_remove_multicast(net_device *device, const sockaddr *address)
151{
152	return B_OK;
153}
154
155
156static status_t
157loopback_std_ops(int32 op, ...)
158{
159	switch (op) {
160		case B_MODULE_INIT:
161		case B_MODULE_UNINIT:
162			return B_OK;
163
164		default:
165			return B_ERROR;
166	}
167}
168
169
170net_device_module_info sLoopbackModule = {
171	{
172		"network/devices/loopback/v1",
173		0,
174		loopback_std_ops
175	},
176	loopback_init,
177	loopback_uninit,
178	loopback_up,
179	loopback_down,
180	loopback_control,
181	loopback_send_data,
182	NULL, // receive_data
183	loopback_set_mtu,
184	loopback_set_promiscuous,
185	loopback_set_media,
186	loopback_add_multicast,
187	loopback_remove_multicast,
188};
189
190module_info *modules[] = {
191	(module_info *)&sLoopbackModule,
192	NULL
193};
194