Wrapper of NetworkSocketAPI for BSD sockets on POSIX systems
Dependents: BSDInterfaceTests HelloBSDInterface
BSDInterface.cpp
- Committer:
- geky
- Date:
- 2016-04-01
- Revision:
- 6:363dd62309cf
- Parent:
- 5:1af10f9d9404
File content as of revision 6:363dd62309cf:
/* BSD implementation of NetworkInterfaceAPI * Copyright (c) 2015 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "BSDInterface.h" #include <sys/ioctl.h> #include <netdb.h> #include <net/if.h> #include <unistd.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> #include <stdio.h> // BSDInterface implementation static bool ifctl(struct ifreq *ifr, unsigned req) { struct ifconf ifc; char buffer[1024]; int sock = ::socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { return 0; } ifc.ifc_buf = buffer; ifc.ifc_len = sizeof buffer; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { ::close(sock); return false; } for (int i = 0; i < ifc.ifc_len; i++) { strcpy(ifr->ifr_name, ifc.ifc_req[i].ifr_name); if (ioctl(sock, SIOCGIFFLAGS, ifr) == 0 && !(ifr->ifr_flags & IFF_LOOPBACK) && ioctl(sock, req, ifr) == 0) { ::close(sock); return true; } } ::close(sock); return false; } const char *BSDInterface::getIPAddress() { static char ip_address[NS_IP_SIZE] = "\0"; if (ip_address[0]) { return ip_address; } struct ifreq ifr; if (!ifctl(&ifr, SIOCGIFADDR)) { return 0; } struct in_addr addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; strcpy(ip_address, inet_ntoa(addr)); return ip_address; } const char *BSDInterface::getMACAddress() { static char mac_address[NS_MAC_SIZE] = "\0"; if (mac_address[0]) { return mac_address; } struct ifreq ifr; if (!ifctl(&ifr, SIOCGIFHWADDR)) { return 0; } sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)ifr.ifr_hwaddr.sa_data[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1], (unsigned char)ifr.ifr_hwaddr.sa_data[2], (unsigned char)ifr.ifr_hwaddr.sa_data[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4], (unsigned char)ifr.ifr_hwaddr.sa_data[5]); return mac_address; } int32_t BSDInterface::getHostByName(const char *name, char *ip) { struct hostent *host = gethostbyname(name); if (!host || host->h_addrtype != AF_INET) { return NS_ERROR_DNS_FAILURE; } strcpy(ip, inet_ntoa(*(struct in_addr *)host->h_addr)); return 0; } SocketInterface *BSDInterface::createSocket(ns_protocol_t proto) { int type = (proto == NS_UDP) ? SOCK_DGRAM : SOCK_STREAM; int fd = ::socket(AF_INET, type, 0); if (fd < 0) { return 0; } return new BSDSocket(fd); } void BSDInterface::destroySocket(SocketInterface *socket) { ::close(((BSDSocket*)socket)->fd); delete socket; } // BSDSocket implementation int32_t BSDInterface::BSDSocket::open(const char *ip, uint16_t port) { struct sockaddr_in host; memset(&host, 0, sizeof host); host.sin_family = AF_INET; host.sin_port = htons(port); inet_pton(AF_INET, ip, &host.sin_addr); if (::connect(fd, (struct sockaddr *)&host, sizeof host) < 0) { return NS_ERROR_NO_CONNECTION; } return 0; } int32_t BSDInterface::BSDSocket::close() { return 0; } int32_t BSDInterface::BSDSocket::send(const void *data, uint32_t size) { if (::send(fd, data, size, 0) < 0) { return NS_ERROR_DEVICE_ERROR; } return size; } int32_t BSDInterface::BSDSocket::recv(void *data, uint32_t size) { int ret = ::recv(fd, data, size, MSG_DONTWAIT); if (ret > 0) { return ret; } else if (errno == EAGAIN) { return NS_ERROR_WOULD_BLOCK; } else { return NS_ERROR_DEVICE_ERROR; } }