xref: /haiku/src/add-ons/kernel/network/devices/loopback/loopback.cpp (revision b9a5b9a6ee494261f2882bfc0ee9fde92282bef6)
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 
24 struct loopback_device : net_device {
25 };
26 
27 
28 struct net_buffer_module_info *gBufferModule;
29 static struct net_stack_module_info *sStackModule;
30 
31 
32 //	#pragma mark -
33 
34 
35 status_t
36 loopback_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 = 16384;
63 	device->media = IFM_ACTIVE;
64 
65 	*_device = device;
66 	return B_OK;
67 
68 err2:
69 	put_module(NET_BUFFER_MODULE_NAME);
70 err1:
71 	put_module(NET_STACK_MODULE_NAME);
72 	return status;
73 }
74 
75 
76 status_t
77 loopback_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 
89 status_t
90 loopback_up(net_device *device)
91 {
92 	return B_OK;
93 }
94 
95 
96 void
97 loopback_down(net_device *device)
98 {
99 }
100 
101 
102 status_t
103 loopback_control(net_device *device, int32 op, void *argument,
104 	size_t length)
105 {
106 	return B_BAD_VALUE;
107 }
108 
109 
110 status_t
111 loopback_send_data(net_device *device, net_buffer *buffer)
112 {
113 	gBufferModule->swap_addresses(buffer);
114 
115 	return sStackModule->device_enqueue_buffer(device, buffer);
116 }
117 
118 
119 status_t
120 loopback_set_mtu(net_device *device, size_t mtu)
121 {
122 	if (mtu > 65536 || mtu < 16)
123 		return B_BAD_VALUE;
124 
125 	device->mtu = mtu;
126 	return B_OK;
127 }
128 
129 
130 status_t
131 loopback_set_promiscuous(net_device *device, bool promiscuous)
132 {
133 	return EOPNOTSUPP;
134 }
135 
136 
137 status_t
138 loopback_set_media(net_device *device, uint32 media)
139 {
140 	return EOPNOTSUPP;
141 }
142 
143 
144 status_t
145 loopback_add_multicast(net_device *device, const sockaddr *address)
146 {
147 	return B_OK;
148 }
149 
150 
151 status_t
152 loopback_remove_multicast(net_device *device, const sockaddr *address)
153 {
154 	return B_OK;
155 }
156 
157 
158 static status_t
159 loopback_std_ops(int32 op, ...)
160 {
161 	switch (op) {
162 		case B_MODULE_INIT:
163 		case B_MODULE_UNINIT:
164 			return B_OK;
165 
166 		default:
167 			return B_ERROR;
168 	}
169 }
170 
171 
172 net_device_module_info sLoopbackModule = {
173 	{
174 		"network/devices/loopback/v1",
175 		0,
176 		loopback_std_ops
177 	},
178 	loopback_init,
179 	loopback_uninit,
180 	loopback_up,
181 	loopback_down,
182 	loopback_control,
183 	loopback_send_data,
184 	NULL, // receive_data
185 	loopback_set_mtu,
186 	loopback_set_promiscuous,
187 	loopback_set_media,
188 	loopback_add_multicast,
189 	loopback_remove_multicast,
190 };
191 
192 module_info *modules[] = {
193 	(module_info *)&sLoopbackModule,
194 	NULL
195 };
196