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 "datalink.h" 11 #include "domains.h" 12 #include "interfaces.h" 13 #include "link.h" 14 #include "stack_private.h" 15 #include "utility.h" 16 17 #include <net_device.h> 18 19 #include <lock.h> 20 #include <util/AutoLock.h> 21 22 #include <KernelExport.h> 23 #include <ProtocolUtilities.h> 24 25 #include <net/if_types.h> 26 #include <new> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/sockio.h> 30 31 32 class LocalStackBundle { 33 public: 34 static net_stack_module_info *Stack() { return &gNetStackModule; } 35 static net_buffer_module_info *Buffer() { return &gNetBufferModule; } 36 }; 37 38 typedef DatagramSocket<BenaphoreLocking, LocalStackBundle> LocalDatagramSocket; 39 40 class LinkProtocol : public net_protocol, public LocalDatagramSocket { 41 public: 42 LinkProtocol(net_socket *socket); 43 ~LinkProtocol(); 44 45 status_t StartMonitoring(const char *); 46 status_t StopMonitoring(); 47 48 private: 49 status_t _SocketStatus() const; 50 status_t _Unregister(); 51 52 net_device_monitor fMonitor; 53 net_device_interface *fMonitoredDevice; 54 55 static status_t _MonitorData(net_device_monitor *monitor, net_buffer *buffer); 56 static void _MonitorEvent(net_device_monitor *monitor, int32 event); 57 }; 58 59 60 struct net_domain *sDomain; 61 62 63 LinkProtocol::LinkProtocol(net_socket *socket) 64 : LocalDatagramSocket("packet capture", socket) 65 { 66 fMonitor.cookie = this; 67 fMonitor.receive = _MonitorData; 68 fMonitor.event = _MonitorEvent; 69 fMonitoredDevice = NULL; 70 } 71 72 73 LinkProtocol::~LinkProtocol() 74 { 75 if (fMonitoredDevice) { 76 unregister_device_monitor(fMonitoredDevice->device, &fMonitor); 77 put_device_interface(fMonitoredDevice); 78 } 79 } 80 81 82 status_t 83 LinkProtocol::StartMonitoring(const char *deviceName) 84 { 85 BenaphoreLocker _(fLock); 86 87 if (fMonitoredDevice) 88 return B_BUSY; 89 90 net_device_interface *interface = get_device_interface(deviceName); 91 if (interface == NULL) 92 return ENODEV; 93 94 status_t status = register_device_monitor(interface->device, &fMonitor); 95 if (status < B_OK) { 96 put_device_interface(interface); 97 return status; 98 } 99 100 fMonitoredDevice = interface; 101 return B_OK; 102 } 103 104 105 status_t 106 LinkProtocol::StopMonitoring() 107 { 108 BenaphoreLocker _(fLock); 109 110 // TODO compare our device with the supplied device name? 111 return _Unregister(); 112 } 113 114 115 status_t 116 LinkProtocol::_SocketStatus() const 117 { 118 if (fMonitoredDevice == NULL) 119 return ENODEV; 120 return LocalDatagramSocket::_SocketStatus(); 121 } 122 123 status_t 124 LinkProtocol::_Unregister() 125 { 126 if (fMonitoredDevice == NULL) 127 return B_BAD_VALUE; 128 129 status_t status = unregister_device_monitor(fMonitoredDevice->device, 130 &fMonitor); 131 put_device_interface(fMonitoredDevice); 132 fMonitoredDevice = NULL; 133 134 return status; 135 } 136 137 138 status_t 139 LinkProtocol::_MonitorData(net_device_monitor *monitor, net_buffer *packet) 140 { 141 return ((LinkProtocol *)monitor->cookie)->SocketEnqueue(packet); 142 } 143 144 145 void 146 LinkProtocol::_MonitorEvent(net_device_monitor *monitor, int32 event) 147 { 148 LinkProtocol *protocol = (LinkProtocol *)monitor->cookie; 149 150 if (event == B_DEVICE_GOING_DOWN) { 151 BenaphoreLocker _(protocol->fLock); 152 153 protocol->_Unregister(); 154 if (protocol->_IsEmpty()) { 155 protocol->WakeAll(); 156 notify_socket(protocol->socket, B_SELECT_READ, ENODEV); 157 } 158 } 159 } 160 161 162 // #pragma mark - 163 164 165 net_protocol * 166 link_init_protocol(net_socket *socket) 167 { 168 LinkProtocol *protocol = new (std::nothrow) LinkProtocol(socket); 169 if (protocol && protocol->InitCheck() < B_OK) { 170 delete protocol; 171 return NULL; 172 } 173 174 return protocol; 175 } 176 177 178 status_t 179 link_uninit_protocol(net_protocol *protocol) 180 { 181 delete (LinkProtocol *)protocol; 182 return B_OK; 183 } 184 185 186 status_t 187 link_open(net_protocol *protocol) 188 { 189 return B_OK; 190 } 191 192 193 status_t 194 link_close(net_protocol *protocol) 195 { 196 return B_OK; 197 } 198 199 200 status_t 201 link_free(net_protocol *protocol) 202 { 203 return B_OK; 204 } 205 206 207 status_t 208 link_connect(net_protocol *protocol, const struct sockaddr *address) 209 { 210 return EOPNOTSUPP; 211 } 212 213 214 status_t 215 link_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 216 { 217 return EOPNOTSUPP; 218 } 219 220 221 status_t 222 link_control(net_protocol *_protocol, int level, int option, void *value, 223 size_t *_length) 224 { 225 LinkProtocol *protocol = (LinkProtocol *)_protocol; 226 227 // TODO All of this common functionality should be elsewhere 228 229 switch (option) { 230 case SIOCGIFINDEX: 231 { 232 // get index of interface 233 struct ifreq request; 234 if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK) 235 return B_BAD_ADDRESS; 236 237 net_device_interface *interface = get_device_interface(request.ifr_name); 238 if (interface != NULL) { 239 request.ifr_index = interface->device->index; 240 put_device_interface(interface); 241 } else 242 request.ifr_index = 0; 243 244 return user_memcpy(value, &request, sizeof(struct ifreq)); 245 } 246 case SIOCGIFNAME: 247 { 248 // get name of interface via index 249 struct ifreq request; 250 if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK) 251 return B_BAD_ADDRESS; 252 253 net_device_interface *interface = get_device_interface(request.ifr_index); 254 if (interface != NULL) { 255 strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE); 256 put_device_interface(interface); 257 } else 258 return ENODEV; 259 260 return user_memcpy(value, &request, sizeof(struct ifreq)); 261 } 262 263 case SIOCGIFCOUNT: 264 { 265 // count number of interfaces 266 struct ifconf config; 267 config.ifc_value = count_device_interfaces(); 268 269 return user_memcpy(value, &config, sizeof(struct ifconf)); 270 } 271 272 case SIOCGIFCONF: 273 { 274 // retrieve available interfaces 275 struct ifconf config; 276 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) 277 return B_BAD_ADDRESS; 278 279 status_t result = list_device_interfaces(config.ifc_buf, 280 (size_t *)&config.ifc_len); 281 if (result != B_OK) 282 return result; 283 284 return user_memcpy(value, &config, sizeof(struct ifconf)); 285 } 286 287 case SIOCGIFADDR: 288 { 289 // get address of interface 290 struct ifreq request; 291 if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK) 292 return B_BAD_ADDRESS; 293 294 net_device_interface *interface = get_device_interface(request.ifr_name); 295 if (interface != NULL) { 296 get_device_interface_address(interface, &request.ifr_addr); 297 put_device_interface(interface); 298 } else 299 return ENODEV; 300 301 return user_memcpy(&((struct ifreq *)value)->ifr_addr, 302 &request.ifr_addr, request.ifr_addr.sa_len); 303 } 304 305 case SIOCSPACKETCAP: 306 { 307 struct ifreq request; 308 if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK) 309 return B_BAD_ADDRESS; 310 311 return protocol->StartMonitoring(request.ifr_name); 312 } 313 314 case SIOCCPACKETCAP: 315 return protocol->StopMonitoring(); 316 } 317 318 return datalink_control(sDomain, option, value, _length); 319 } 320 321 322 status_t 323 link_getsockopt(net_protocol *protocol, int level, int option, void *value, 324 int *length) 325 { 326 return protocol->next->module->getsockopt(protocol, level, option, 327 value, length); 328 } 329 330 331 status_t 332 link_setsockopt(net_protocol *protocol, int level, int option, 333 const void *value, int length) 334 { 335 return protocol->next->module->setsockopt(protocol, level, option, 336 value, length); 337 } 338 339 340 status_t 341 link_bind(net_protocol *protocol, const struct sockaddr *address) 342 { 343 // TODO: bind to a specific interface and ethernet type 344 return B_ERROR; 345 } 346 347 348 status_t 349 link_unbind(net_protocol *protocol, struct sockaddr *address) 350 { 351 return B_ERROR; 352 } 353 354 355 status_t 356 link_listen(net_protocol *protocol, int count) 357 { 358 return EOPNOTSUPP; 359 } 360 361 362 status_t 363 link_shutdown(net_protocol *protocol, int direction) 364 { 365 return EOPNOTSUPP; 366 } 367 368 369 status_t 370 link_send_data(net_protocol *protocol, net_buffer *buffer) 371 { 372 return B_NOT_ALLOWED; 373 } 374 375 376 status_t 377 link_send_routed_data(net_protocol *protocol, struct net_route *route, 378 net_buffer *buffer) 379 { 380 return B_NOT_ALLOWED; 381 } 382 383 384 ssize_t 385 link_send_avail(net_protocol *protocol) 386 { 387 return B_ERROR; 388 } 389 390 391 status_t 392 link_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 393 net_buffer **_buffer) 394 { 395 return ((LinkProtocol *)protocol)->SocketDequeue(flags, _buffer); 396 } 397 398 399 ssize_t 400 link_read_avail(net_protocol *protocol) 401 { 402 return ((LinkProtocol *)protocol)->AvailableData(); 403 } 404 405 406 struct net_domain * 407 link_get_domain(net_protocol *protocol) 408 { 409 return sDomain; 410 } 411 412 413 size_t 414 link_get_mtu(net_protocol *protocol, const struct sockaddr *address) 415 { 416 // TODO: for now 417 return 0; 418 } 419 420 421 status_t 422 link_receive_data(net_buffer *buffer) 423 { 424 return B_ERROR; 425 } 426 427 428 status_t 429 link_error(uint32 code, net_buffer *data) 430 { 431 return B_ERROR; 432 } 433 434 435 status_t 436 link_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code, 437 void *errorData) 438 { 439 return B_ERROR; 440 } 441 442 443 static status_t 444 link_std_ops(int32 op, ...) 445 { 446 switch (op) { 447 case B_MODULE_INIT: 448 return register_domain(AF_LINK, "link", NULL, NULL, &sDomain); 449 450 case B_MODULE_UNINIT: 451 unregister_domain(sDomain); 452 return B_OK; 453 454 default: 455 return B_ERROR; 456 } 457 } 458 459 460 // #pragma mark - 461 462 463 void 464 link_init() 465 { 466 register_domain_protocols(AF_LINK, SOCK_DGRAM, 0, "network/stack/link/v1", NULL); 467 468 register_domain_datalink_protocols(AF_LINK, IFT_ETHER, 469 "network/datalink_protocols/ethernet_frame/v1", 470 NULL); 471 } 472 473 474 net_protocol_module_info gLinkModule = { 475 { 476 "network/stack/link/v1", 477 0, 478 link_std_ops 479 }, 480 link_init_protocol, 481 link_uninit_protocol, 482 link_open, 483 link_close, 484 link_free, 485 link_connect, 486 link_accept, 487 link_control, 488 link_getsockopt, 489 link_setsockopt, 490 link_bind, 491 link_unbind, 492 link_listen, 493 link_shutdown, 494 link_send_data, 495 link_send_routed_data, 496 link_send_avail, 497 link_read_data, 498 link_read_avail, 499 link_get_domain, 500 link_get_mtu, 501 link_receive_data, 502 NULL, 503 link_error, 504 link_error_reply, 505 }; 506