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 status_t status = sStackModule->device_enqueue_buffer(device, buffer); 114 if (status == B_OK) { 115 atomic_add64((int64*)&device->stats.send.bytes, buffer->size); 116 atomic_add((int32*)&device->stats.send.packets, 1); 117 } else { 118 atomic_add((int32*)&device->stats.send.errors, 1); 119 } 120 return status; 121 } 122 123 124 status_t 125 loopback_set_mtu(net_device *device, size_t mtu) 126 { 127 if (mtu > 65536 || mtu < 16) 128 return B_BAD_VALUE; 129 130 device->mtu = mtu; 131 return B_OK; 132 } 133 134 135 status_t 136 loopback_set_promiscuous(net_device *device, bool promiscuous) 137 { 138 return EOPNOTSUPP; 139 } 140 141 142 status_t 143 loopback_set_media(net_device *device, uint32 media) 144 { 145 return EOPNOTSUPP; 146 } 147 148 149 status_t 150 loopback_add_multicast(net_device *device, const sockaddr *address) 151 { 152 return B_OK; 153 } 154 155 156 status_t 157 loopback_remove_multicast(net_device *device, const sockaddr *address) 158 { 159 return B_OK; 160 } 161 162 163 static status_t 164 loopback_std_ops(int32 op, ...) 165 { 166 switch (op) { 167 case B_MODULE_INIT: 168 case B_MODULE_UNINIT: 169 return B_OK; 170 171 default: 172 return B_ERROR; 173 } 174 } 175 176 177 net_device_module_info sLoopbackModule = { 178 { 179 "network/devices/loopback/v1", 180 0, 181 loopback_std_ops 182 }, 183 loopback_init, 184 loopback_uninit, 185 loopback_up, 186 loopback_down, 187 loopback_control, 188 loopback_send_data, 189 NULL, // receive_data 190 loopback_set_mtu, 191 loopback_set_promiscuous, 192 loopback_set_media, 193 loopback_add_multicast, 194 loopback_remove_multicast, 195 }; 196 197 module_info *modules[] = { 198 (module_info *)&sLoopbackModule, 199 NULL 200 }; 201