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