OZ++ Class: NetworkInterface |
/****************************************************************************** * * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer. * * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * NetworkInterface.h * *****************************************************************************/ #pragma once #include <oz++/CommonObject.h> #include <oz++/InterfaceNameIndex.h> #include <oz++/SocketDatagram.h> #include <oz++/CharString.h> #include <oz++/StringBufferT.h> #include <oz++/Bytes.h> #include <oz++/Pair.h> #include <linux/if.h> /* struct ifreq { #define IFHWADDRLEN 6 union { char ifrn_name[IFNAMSIZ]; } ifr_ifrn; union { struct sockaddr ifru_addr; struct sockaddr ifru_dstaddr; struct sockaddr ifru_broadaddr; struct sockaddr ifru_netmask; struct sockaddr ifru_hwaddr; short ifru_flags; int ifru_ivalue; //ifindex int ifru_mtu; struct ifmap ifru_map; char ifru_slave[IFNAMSIZ]; char ifru_newname[IFNAMSIZ]; void * ifru_data; struct if_settings ifru_settings; } ifr_ifru; }; */ namespace OZ { //AF_INET IPv4 struct InterfaceRecord { unsigned char family; char ifname[IFNAMSIZ+1]; // struct sockaddr ifaddr; struct sockaddr dstaddr; struct sockaddr broadaddr; struct sockaddr netmask; struct sockaddr hwaddr; short flags; int ifindex; //ifindex returned by SIOCGIFINDEX int mtu; struct ifmap map; char slave[IFNAMSIZ]; // char newname[IFNAMSIZ]; void * data; struct if_settings settings; }; //IPv4 class NetworkInterface :public CommonObject { private: struct ifreq ifr; struct InterfaceRecord record; SocketDatagram sock; public: NetworkInterface(int index) { clear(); record.family = AF_INET; InterfaceNameIndex nameIndex; const char* name = nameIndex.name(index); size_t namelen = sizeof(record.ifname); if (name && strlen(name) <= namelen) { strcpy(record.ifname, name); } else { throw IException("Invalid argument %d", index); } //struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, record.ifname, sizeof(ifr.ifr_name)); ifr.ifr_addr.sa_family = record.family; getAll(); } public: NetworkInterface(const char* name) { clear(); record.family = AF_INET; size_t namelen = sizeof(record.ifname); if (name && strlen(name) < namelen) { strcpy(record.ifname, name); } else { throw IException("Invalid argument %s", name); } memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, record.ifname, sizeof(ifr.ifr_name)); ifr.ifr_addr.sa_family = record.family; getAll(); } private: void clear() { memset(&record, 0, sizeof(record)); } sockaddr getIfAddr() { if(sock.ioctl(SIOCGIFADDR, &ifr) == 0) { record.ifaddr = ifr.ifr_addr; } else { throw IException("Failed to get address"); } return record.ifaddr; } sockaddr getDstAddr() { if(sock.ioctl(SIOCGIFDSTADDR, &ifr) == 0) { record.dstaddr = ifr.ifr_dstaddr; } else { throw IException("Failed to get address"); } return record.dstaddr; } sockaddr getBroadAddr() { if(sock.ioctl(SIOCGIFBRDADDR, &ifr) == 0) { record.broadaddr = ifr.ifr_broadaddr; } else { throw IException("Failed to get address"); } return record.broadaddr; } sockaddr getNetmask() { if(sock.ioctl(SIOCGIFNETMASK, &ifr) == 0) { record.netmask = ifr.ifr_netmask; } else { throw IException("Failed to get address"); } return record.netmask; } sockaddr getHardwareAddr() { if (sock.ioctl(SIOCGIFHWADDR, &ifr) == 0) { record.hwaddr = ifr.ifr_hwaddr; } else { throw IException("Failed to get hardware address"); } return record.hwaddr; } int getFlags() { if (sock.ioctl(SIOCGIFFLAGS, &ifr) == 0) { record.flags = ifr.ifr_flags; } else { throw IException("Failed to get ifflags address"); } return record.flags; } int getIfindex() { if (sock.ioctl(SIOCGIFINDEX, &ifr) == 0) { record.ifindex = ifr.ifr_ifindex; } else { throw IException("Failed to get ivalue"); } return record.ifindex; } int getMtu() { if (sock.ioctl(SIOCGIFMTU, &ifr) == 0) { record.mtu = ifr.ifr_mtu; } else { throw IException("Failed to get mtu"); } return record.mtu; } private: void getAll() { getIfAddr(); getDstAddr(); getBroadAddr(); getNetmask(); getHardwareAddr(); getFlags(); getIfindex(); getMtu(); } public: static CharString getFlags(int flag) { Pair<int, const char*> flags[] = { {IFF_UP ,"IFF_UP"}, {IFF_BROADCAST ,"IFF_BROADCAST"}, {IFF_DEBUG ,"IFF_DEBUG"}, {IFF_LOOPBACK ,"IFF_LOOPBACK"}, {IFF_POINTOPOINT ,"IFF_POINTOPOINT"}, {IFF_RUNNING ,"IFF_RUNNING"}, {IFF_NOARP ,"IFF_NOARP"}, {IFF_PROMISC ,"IFF_PROMISC"}, {IFF_NOTRAILERS ,"IFF_NOTRAILERS"}, {IFF_ALLMULTI ,"IFF_ALLMULTI"}, {IFF_MASTER ,"IFF_MASTER"}, {IFF_SLAVE ,"IFF_SLAVE"}, {IFF_MULTICAST ,"IFF_MULTICAST"}, {IFF_PORTSEL ,"IFF_PORTSEL"}, {IFF_AUTOMEDIA ,"IFF_AUTOMEDI"}, {IFF_DYNAMIC ,"IFF_DYNAMIC"}, {IFF_LOWER_UP ,"IFF_LOWER_UP"}, {IFF_DORMANT ,"IFF_DORMANT"}, {IFF_ECHO ,"IFF_ECHO"}, }; StringBufferT<char> buffer; for (int i = 0; i<SizeOf(flags); i++) { if (flag & flags[i].first) { if (buffer.getContentSize() > 0) { buffer.append("|"); } buffer.append(flags[i].second); } } const char* string = (const char*)buffer; return CharString(string); } public: struct sockaddr ifaddr() { return record.ifaddr; } CharString ifAddrString() { char buff[20]; struct sockaddr_in* addrin = (struct sockaddr_in*)&record.ifaddr; ::inet_ntop(record.family, &addrin->sin_addr, buff, sizeof(buff)); return CharString(buff); } CharString dstAddrString() { char buff[20]; struct sockaddr_in* addrin = (struct sockaddr_in*)&record.dstaddr; ::inet_ntop(record.family, &addrin->sin_addr, buff, sizeof(buff)); return CharString(buff); } CharString broadAddrString() { char buff[20]; struct sockaddr_in* addrin = (struct sockaddr_in*)&record.broadaddr; ::inet_ntop(record.family, &addrin->sin_addr, buff, sizeof(buff)); return CharString(buff); } Bytes hardwareAddr() { size_t size = sizeof(record.hwaddr.sa_data); if (record.family == AF_INET) { size = 6; } return Bytes((unsigned char*)record.hwaddr.sa_data, size); } CharString flags() { return getFlags(record.flags); } int ifindex() { return record.ifindex; } int mtu() { return record.mtu; } public: void display() { printf("Ifaddr: %s\n", (const char*)ifAddrString() ); printf("Dstaddr: %s\n", (const char*)dstAddrString() ); printf("BroadAddr: %s\n", (const char*)broadAddrString() ); printf("HardwareAddr:"); hardwareAddr().display(); printf("Flags: %s\n", (const char*)flags() ); printf("Ifindex: %d\n", ifindex() ); printf("Mtu: %d\n", mtu() ); } }; }