1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2013 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 17ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include "shill/eap_listener.h" 18ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 19ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include <linux/if_ether.h> 20ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include <linux/if_packet.h> 21ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include <netinet/in.h> 22ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 23ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include <base/bind.h> 24a41ab517725d036b63420f8445550246f8f50b99Alex Vakulenko#include <base/compiler_specific.h> 25ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 26ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include "shill/eap_protocol.h" 27ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include "shill/event_dispatcher.h" 28ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart#include "shill/logging.h" 298d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/sockets.h" 30ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 31ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartnamespace shill { 32ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 33ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartconst size_t EapListener::kMaxEapPacketLength = 34ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart sizeof(eap_protocol::Ieee8021xHdr) + sizeof(eap_protocol::EapHeader); 35ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 36a794cd60a7339d576ea2eed263a4f0a20fb255afPaul StewartEapListener::EapListener(EventDispatcher* event_dispatcher, 37ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart int interface_index) 38ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart : dispatcher_(event_dispatcher), 39ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart interface_index_(interface_index), 40ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart sockets_(new Sockets()), 41ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_(-1) {} 42ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 43ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul StewartEapListener::~EapListener() {} 44ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 45ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartbool EapListener::Start() { 46ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (!CreateSocket()) { 47ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart LOG(ERROR) << "Could not open EAP listener socket."; 48ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart Stop(); 49ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return false; 50ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 51ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 52ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart receive_request_handler_.reset( 53ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart dispatcher_->CreateReadyHandler( 54ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_, 55ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart IOHandler::kModeInput, 56ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart base::Bind(&EapListener::ReceiveRequest, base::Unretained(this)))); 57ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 58ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return true; 59ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart} 60ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 61ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartvoid EapListener::Stop() { 62ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart receive_request_handler_.reset(); 63ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_closer_.reset(); 64ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_ = -1; 65ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart} 66ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 67ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 68ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartbool EapListener::CreateSocket() { 69ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart int socket = sockets_->Socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); 70ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (socket == -1) { 71ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart PLOG(ERROR) << "Could not create EAP listener socket"; 72ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return false; 73ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 74ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_ = socket; 75ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_closer_.reset(new ScopedSocketCloser(sockets_.get(), socket_)); 76ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 77ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (sockets_->SetNonBlocking(socket_) != 0) { 78ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart PLOG(ERROR) << "Could not set socket to be non-blocking"; 79ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return false; 80ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 81ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 82ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart sockaddr_ll socket_address; 83ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart memset(&socket_address, 0, sizeof(socket_address)); 84ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_address.sll_family = AF_PACKET; 85ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_address.sll_protocol = htons(ETH_P_PAE); 86ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_address.sll_ifindex = interface_index_; 87ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 88ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (sockets_->Bind(socket_, 89a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr*>(&socket_address), 90ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart sizeof(socket_address)) != 0) { 91ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart PLOG(ERROR) << "Could not bind socket to interface"; 92ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return false; 93ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 94ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 95ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return true; 96ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart} 97ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 98ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewartvoid EapListener::ReceiveRequest(int fd) { 99ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart struct ALIGNAS(1) { 100ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart eap_protocol::Ieee8021xHdr onex_header; 101ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart eap_protocol::EapHeader eap_header; 102ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } payload; 103ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart sockaddr_ll remote_address; 104ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart memset(&remote_address, 0, sizeof(remote_address)); 105ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socklen_t socklen = sizeof(remote_address); 106ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart int result = sockets_->RecvFrom( 107ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart socket_, &payload, sizeof(payload), 0, 108a794cd60a7339d576ea2eed263a4f0a20fb255afPaul Stewart reinterpret_cast<struct sockaddr*>(&remote_address), 109ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart &socklen); 110ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (result < 0) { 111ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart PLOG(ERROR) << "Socket recvfrom failed"; 112ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart Stop(); 113ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return; 114ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 115ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 116ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart if (result != sizeof(payload)) { 117ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart LOG(INFO) << "Short EAP packet received"; 118ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return; 119ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 120ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 121475ce5aad3c7c4b1f53783d969bc904ed5f1c065Paul Stewart if (payload.onex_header.version < eap_protocol::kIeee8021xEapolVersion1 || 122ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart payload.onex_header.type != eap_protocol::kIIeee8021xTypeEapPacket || 123ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart payload.eap_header.code != eap_protocol::kEapCodeRequest) { 124ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart LOG(INFO) << "Packet is not a valid EAP request"; 125ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart return; 126ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart } 127ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 128ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart request_received_callback_.Run(); 129ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart} 130ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart 131ac802ac47b09e93cd61ae67e10ab5feecee1cf15Paul Stewart} // namespace shill 132