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