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