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
loopback_init(const char * name,net_device ** _device)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
loopback_uninit(net_device * _device)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
loopback_up(net_device * device)90 loopback_up(net_device *device)
91 {
92 return B_OK;
93 }
94
95
96 void
loopback_down(net_device * device)97 loopback_down(net_device *device)
98 {
99 }
100
101
102 status_t
loopback_control(net_device * device,int32 op,void * argument,size_t length)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
loopback_send_data(net_device * device,net_buffer * buffer)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
loopback_set_mtu(net_device * device,size_t mtu)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
loopback_set_promiscuous(net_device * device,bool promiscuous)129 loopback_set_promiscuous(net_device *device, bool promiscuous)
130 {
131 return EOPNOTSUPP;
132 }
133
134
135 status_t
loopback_set_media(net_device * device,uint32 media)136 loopback_set_media(net_device *device, uint32 media)
137 {
138 return EOPNOTSUPP;
139 }
140
141
142 status_t
loopback_add_multicast(net_device * device,const sockaddr * address)143 loopback_add_multicast(net_device *device, const sockaddr *address)
144 {
145 return B_OK;
146 }
147
148
149 status_t
loopback_remove_multicast(net_device * device,const sockaddr * address)150 loopback_remove_multicast(net_device *device, const sockaddr *address)
151 {
152 return B_OK;
153 }
154
155
156 static status_t
loopback_std_ops(int32 op,...)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