1* // Copyright 2021 Google LLC 2* // 3* // Licensed under the Apache License, Version 2.0 (the "License"); 4* // you may not use this file except in compliance with the License. 5* // You may obtain a copy of the License at 6* // 7* // http://www.apache.org/licenses/LICENSE-2.0 8* // 9* // Unless required by applicable law or agreed to in writing, software 10* // distributed under the License is distributed on an "AS IS" BASIS, 11* // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* // See the License for the specific language governing permissions and 13* // limitations under the License. 14* 15* #include "net_iface.h" 16* 17* #include <linux/if_packet.h> 18* #include <net/ethernet.h> 19* #include <sys/socket.h> 20* #include <unistd.h> 21* 22* #include <cstdio> 23* #include <cstring> 24* #include <stdexcept> 25* 26* namespace net 27* { 28* 29* IFaceBase::IFaceBase(const std::string& name) : name_{name} 30* { 31* if (name.size() >= IFNAMSIZ) 32* { 33* throw std::length_error("Interface name is too long"); 34* } 35* } 36* 37* int IFaceBase::get_index() const 38* { 39* struct ifreq ifr; 40* std::memset(&ifr, 0, sizeof(ifr)); 41* int ret = ioctl(SIOCGIFINDEX, &ifr); 42* if (ret < 0) 43* { 44* return ret; 45* } 46* 47* return ifr.ifr_ifindex; 48* } 49* 50* int IFaceBase::set_sock_flags(int sockfd, short flags) const 51* { 52* return mod_sock_flags(sockfd, flags, true); 53* } 54* 55* int IFaceBase::clear_sock_flags(int sockfd, short flags) const 56* { 57* return mod_sock_flags(sockfd, flags, false); 58* } 59* 60* int IFaceBase::mod_sock_flags(int sockfd, short flags, bool set) const 61* { 62* struct ifreq ifr; 63* std::memset(&ifr, 0, sizeof(ifr)); 64* 65* int ret = ioctl_sock(sockfd, SIOCGIFFLAGS, &ifr); 66* if (ret < 0) 67* { 68* return ret; 69* } 70* 71* if (set) 72* { 73* ifr.ifr_flags |= flags; 74* } 75* else 76* { 77* ifr.ifr_flags &= ~flags; 78* } 79* return ioctl_sock(sockfd, SIOCSIFFLAGS, &ifr); 80* } 81* 82* int IFace::ioctl_sock(int sockfd, int request, struct ifreq* ifr) const 83* { 84* if (ifr == nullptr) 85* { 86* return -1; 87* } 88* 89* /* Avoid string truncation. */ 90* size_t len = name_.length(); 91* if (len + 1 >= sizeof(ifr->ifr_name)) 92* { 93* return -1; 94* } 95* 96* std::memcpy(ifr->ifr_name, name_.c_str(), len); 97* ifr->ifr_name[len] = 0; 98* 99* return ::ioctl(sockfd, request, ifr); 100* } 101* 102* int IFace::bind_sock(int sockfd, struct sockaddr_ll* saddr) const 103* { 104* if (saddr == nullptr) 105* { 106* return -1; 107* } 108* 109* saddr->sll_ifindex = get_index(); 110* 111* return bind(sockfd, reinterpret_cast<struct sockaddr*>(saddr), 112* sizeof(*saddr)); 113* } 114* 115* int IFace::ioctl(int request, struct ifreq* ifr) const 116* { 117* if (ifr == nullptr) 118* { 119* return -1; 120* } 121* 122* int tempsock = socket(AF_INET, SOCK_DGRAM, 0); 123* if (tempsock < 0) 124* { 125* return tempsock; 126* } 127* 128* int ret = ioctl_sock(tempsock, request, ifr); 129* close(tempsock); 130* 131* return ret; 132* } 133* 134* } // namespace net 135*