xref: /haiku/src/add-ons/kernel/network/devices/loopback/loopback.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 = 65536;
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 	return sStackModule->device_enqueue_buffer(device, buffer);
114 }
115 
116 
117 status_t
118 loopback_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 
128 status_t
129 loopback_set_promiscuous(net_device *device, bool promiscuous)
130 {
131 	return EOPNOTSUPP;
132 }
133 
134 
135 status_t
136 loopback_set_media(net_device *device, uint32 media)
137 {
138 	return EOPNOTSUPP;
139 }
140 
141 
142 status_t
143 loopback_add_multicast(net_device *device, const sockaddr *address)
144 {
145 	return B_OK;
146 }
147 
148 
149 status_t
150 loopback_remove_multicast(net_device *device, const sockaddr *address)
151 {
152 	return B_OK;
153 }
154 
155 
156 static status_t
157 loopback_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 
170 net_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 
190 module_info *modules[] = {
191 	(module_info *)&sLoopbackModule,
192 	NULL
193 };
194