void PacketSender::close_socket(SocketType type, const NetworkInterface &iface) { if(type == ETHER_SOCKET) { #if defined(BSD) || defined(__FreeBSD_kernel__) BSDEtherSockets::iterator it = _ether_socket.find(iface.id()); if(it == _ether_socket.end()) throw invalid_socket_type(); if(::close(it->second) == -1) throw socket_close_error(make_error_string()); _ether_socket.erase(it); #elif !defined(WIN32) if(_ether_socket == INVALID_RAW_SOCKET) throw invalid_socket_type(); if(::close(_ether_socket) == -1) throw socket_close_error(make_error_string()); _ether_socket = INVALID_RAW_SOCKET; #endif } else { if(type >= SOCKETS_END || _sockets[type] == INVALID_RAW_SOCKET) throw invalid_socket_type(); #ifndef WIN32 if(close(_sockets[type]) == -1) throw socket_close_error(make_error_string()); #else closesocket(_sockets[type]); #endif _sockets[type] = INVALID_RAW_SOCKET; } }
void RadioTap::send(PacketSender &sender, const NetworkInterface &iface) { if(!iface) throw invalid_interface(); #if !defined(BSD) && !defined(__FreeBSD_kernel__) struct sockaddr_ll addr; memset(&addr, 0, sizeof(struct sockaddr_ll)); addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET); addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL); addr.sll_halen = 6; addr.sll_ifindex = iface.id(); const Tins::Dot11 *wlan = tins_cast<Tins::Dot11*>(inner_pdu()); if(wlan) { Tins::Dot11::address_type dot11_addr(wlan->addr1()); std::copy(dot11_addr.begin(), dot11_addr.end(), addr.sll_addr); } sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr)); #else sender.send_l2(*this, 0, 0, iface); #endif }
void PacketSender::open_l2_socket(const NetworkInterface& iface) { #if defined(BSD) || defined(__FreeBSD_kernel__) int sock = -1; // At some point, there should be an available device for (int i = 0; sock == -1;i++) { std::ostringstream oss; oss << "/dev/bpf" << i; sock = open(oss.str().c_str(), O_RDWR); } if(sock == -1) throw socket_open_error(make_error_string()); struct ifreq ifr; strncpy(ifr.ifr_name, iface.name().c_str(), sizeof(ifr.ifr_name) - 1); if(ioctl(sock, BIOCSETIF, (caddr_t)&ifr) < 0) { ::close(sock); throw socket_open_error(make_error_string()); } _ether_socket[iface.id()] = sock; #else if (_ether_socket == INVALID_RAW_SOCKET) { _ether_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (_ether_socket == -1) throw socket_open_error(make_error_string()); } #endif }
bool PacketSender::ether_socket_initialized(const NetworkInterface& iface) const { #if defined(BSD) || defined(__FreeBSD_kernel__) return _ether_socket.count(iface.id()); #else return _ether_socket != INVALID_RAW_SOCKET; #endif }
int PacketSender::get_ether_socket(const NetworkInterface& iface) { if(!ether_socket_initialized(iface)) open_l2_socket(iface); #if defined(BSD) || defined(__FreeBSD_kernel__) return _ether_socket[iface.id()]; #else return _ether_socket; #endif }
void Dot11::send(PacketSender &sender, const NetworkInterface &iface) { if(!iface) throw invalid_interface(); #if !defined(BSD) && !defined(__FreeBSD_kernel__) sockaddr_ll addr; memset(&addr, 0, sizeof(struct sockaddr_ll)); addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET); addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL); addr.sll_halen = 6; addr.sll_ifindex = iface.id(); memcpy(&(addr.sll_addr), _header.addr1, 6); sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr)); #else sender.send_l2(*this, 0, 0, iface); #endif }
void EthernetII::send(PacketSender &sender, const NetworkInterface &iface) { if(!iface) throw invalid_interface(); #if defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET) || defined(BSD) || defined(__FreeBSD_kernel__) // Sending using pcap_sendpacket/BSD bpf packet mode is the same here sender.send_l2(*this, 0, 0, iface); #elif defined(WIN32) // On Windows we can only send l2 PDUs using pcap_sendpacket throw std::runtime_error("LIBTINS_USE_PCAP_SENDPACKET is not enabled"); #else // Default GNU/Linux behaviour struct sockaddr_ll addr; memset(&addr, 0, sizeof(struct sockaddr_ll)); addr.sll_family = Endian::host_to_be<uint16_t>(PF_PACKET); addr.sll_protocol = Endian::host_to_be<uint16_t>(ETH_P_ALL); addr.sll_halen = address_type::address_size; addr.sll_ifindex = iface.id(); memcpy(&(addr.sll_addr), _eth.dst_mac, address_type::address_size); sender.send_l2(*this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr)); #endif }