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