NetworkSocketAPI / BSDInterface

Dependents:   BSDInterfaceTests HelloBSDInterface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BSDInterface.cpp Source File

BSDInterface.cpp

00001 /* BSD implementation of NetworkInterfaceAPI
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016  
00017 #include "BSDInterface.h"
00018 
00019 #include <sys/ioctl.h>
00020 #include <netdb.h>
00021 #include <net/if.h> 
00022 #include <unistd.h>
00023 #include <netinet/in.h>
00024 #include <sys/socket.h>
00025 #include <arpa/inet.h>
00026 #include <errno.h>
00027 #include <string.h>
00028 #include <stdio.h>
00029 
00030 
00031 // BSDInterface implementation
00032 static bool ifctl(struct ifreq *ifr, unsigned req) {
00033     struct ifconf ifc;
00034     char buffer[1024];
00035 
00036     int sock = ::socket(AF_INET, SOCK_DGRAM, 0);
00037     if (sock < 0) {
00038         return 0;
00039     }
00040 
00041     ifc.ifc_buf = buffer;
00042     ifc.ifc_len = sizeof buffer;
00043     if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
00044         ::close(sock);
00045         return false;
00046     }
00047 
00048     for (int i = 0; i < ifc.ifc_len; i++) {
00049         strcpy(ifr->ifr_name, ifc.ifc_req[i].ifr_name);
00050 
00051         if (ioctl(sock, SIOCGIFFLAGS, ifr) == 0
00052             && !(ifr->ifr_flags & IFF_LOOPBACK)
00053             && ioctl(sock, req, ifr) == 0) {
00054             ::close(sock);
00055             return true;
00056         }
00057     }
00058 
00059     ::close(sock);
00060     return false;
00061 }
00062 
00063 const char *BSDInterface::getIPAddress()
00064 {
00065     static char ip_address[NS_IP_SIZE] = "\0";
00066     if (ip_address[0]) {
00067         return ip_address;
00068     }
00069 
00070     struct ifreq ifr;
00071     if (!ifctl(&ifr, SIOCGIFADDR)) {
00072         return 0;
00073     }
00074 
00075     struct in_addr addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
00076     strcpy(ip_address, inet_ntoa(addr));
00077     return ip_address;
00078 }
00079 
00080 const char *BSDInterface::getMACAddress() 
00081 {
00082     static char mac_address[NS_MAC_SIZE] = "\0";
00083     if (mac_address[0]) {
00084         return mac_address;
00085     }
00086 
00087     struct ifreq ifr;
00088     if (!ifctl(&ifr, SIOCGIFHWADDR)) {
00089         return 0;
00090     }
00091 
00092     sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",
00093             (unsigned char)ifr.ifr_hwaddr.sa_data[0],
00094             (unsigned char)ifr.ifr_hwaddr.sa_data[1],
00095             (unsigned char)ifr.ifr_hwaddr.sa_data[2],
00096             (unsigned char)ifr.ifr_hwaddr.sa_data[3],
00097             (unsigned char)ifr.ifr_hwaddr.sa_data[4],
00098             (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
00099     return mac_address;
00100 }
00101 
00102 int32_t BSDInterface::getHostByName(const char *name, char *ip)
00103 {
00104     struct hostent *host = gethostbyname(name);
00105     if (!host || host->h_addrtype != AF_INET) {
00106         return NS_ERROR_DNS_FAILURE;
00107     }
00108 
00109     strcpy(ip, inet_ntoa(*(struct in_addr *)host->h_addr));
00110     return 0;
00111 }
00112 
00113 SocketInterface *BSDInterface::createSocket(ns_protocol_t proto)
00114 {
00115     int type = (proto == NS_UDP) ? SOCK_DGRAM : SOCK_STREAM;
00116     int fd = ::socket(AF_INET, type, 0);
00117     if (fd < 0) {
00118         return 0;
00119     }
00120 
00121     return new BSDSocket(fd);
00122 }
00123 
00124 void BSDInterface::destroySocket(SocketInterface *socket)
00125 {
00126     ::close(((BSDSocket*)socket)->fd);
00127     delete socket;
00128 }
00129 
00130 
00131 // BSDSocket implementation
00132 int32_t BSDInterface::BSDSocket::open(const char *ip, uint16_t port)
00133 {
00134     struct sockaddr_in host;    
00135     memset(&host, 0, sizeof host);
00136     host.sin_family = AF_INET;
00137     host.sin_port = htons(port);
00138     inet_pton(AF_INET, ip, &host.sin_addr);
00139 
00140     if (::connect(fd, (struct sockaddr *)&host, sizeof host) < 0) {
00141         return NS_ERROR_NO_CONNECTION;
00142     }
00143 
00144     return 0;
00145 }
00146 
00147 int32_t BSDInterface::BSDSocket::close()
00148 {
00149     return 0;
00150 }
00151 
00152 int32_t BSDInterface::BSDSocket::send(const void *data, uint32_t size)
00153 {
00154     if (::send(fd, data, size, 0) < 0) {
00155         return NS_ERROR_DEVICE_ERROR;
00156     }
00157 
00158     return size;
00159 }
00160 
00161 int32_t BSDInterface::BSDSocket::recv(void *data, uint32_t size)
00162 {
00163     int ret = ::recv(fd, data, size, MSG_DONTWAIT);
00164 
00165     if (ret > 0) {
00166         return ret;
00167     } else if (errno == EAGAIN) {
00168         return NS_ERROR_WOULD_BLOCK;
00169     } else {
00170         return NS_ERROR_DEVICE_ERROR;
00171     }
00172 }
00173 
00174