Wrapper of NetworkSocketAPI for BSD sockets on POSIX systems

Dependents:   BSDInterfaceTests HelloBSDInterface

Committer:
geky
Date:
Fri Apr 01 17:30:01 2016 +0000
Revision:
6:363dd62309cf
Parent:
5:1af10f9d9404
Matched changes to NSAPI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 1:29c61c1420c8 1 /* BSD implementation of NetworkInterfaceAPI
geky 0:d92b89886434 2 * Copyright (c) 2015 ARM Limited
geky 0:d92b89886434 3 *
geky 0:d92b89886434 4 * Licensed under the Apache License, Version 2.0 (the "License");
geky 0:d92b89886434 5 * you may not use this file except in compliance with the License.
geky 0:d92b89886434 6 * You may obtain a copy of the License at
geky 0:d92b89886434 7 *
geky 0:d92b89886434 8 * http://www.apache.org/licenses/LICENSE-2.0
geky 0:d92b89886434 9 *
geky 0:d92b89886434 10 * Unless required by applicable law or agreed to in writing, software
geky 0:d92b89886434 11 * distributed under the License is distributed on an "AS IS" BASIS,
geky 0:d92b89886434 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
geky 0:d92b89886434 13 * See the License for the specific language governing permissions and
geky 0:d92b89886434 14 * limitations under the License.
geky 0:d92b89886434 15 */
geky 0:d92b89886434 16
Christopher Haster 1:29c61c1420c8 17 #include "BSDInterface.h"
geky 0:d92b89886434 18
Christopher Haster 1:29c61c1420c8 19 #include <sys/ioctl.h>
Christopher Haster 2:0978e139e1c5 20 #include <netdb.h>
Christopher Haster 1:29c61c1420c8 21 #include <net/if.h>
Christopher Haster 1:29c61c1420c8 22 #include <unistd.h>
Christopher Haster 1:29c61c1420c8 23 #include <netinet/in.h>
Christopher Haster 1:29c61c1420c8 24 #include <sys/socket.h>
Christopher Haster 1:29c61c1420c8 25 #include <arpa/inet.h>
Christopher Haster 1:29c61c1420c8 26 #include <errno.h>
Christopher Haster 1:29c61c1420c8 27 #include <string.h>
Christopher Haster 1:29c61c1420c8 28 #include <stdio.h>
geky 0:d92b89886434 29
geky 0:d92b89886434 30
Christopher Haster 1:29c61c1420c8 31 // BSDInterface implementation
Christopher Haster 3:eabc4ea66a64 32 static bool ifctl(struct ifreq *ifr, unsigned req) {
Christopher Haster 1:29c61c1420c8 33 struct ifconf ifc;
Christopher Haster 1:29c61c1420c8 34 char buffer[1024];
geky 0:d92b89886434 35
Christopher Haster 2:0978e139e1c5 36 int sock = ::socket(AF_INET, SOCK_DGRAM, 0);
Christopher Haster 1:29c61c1420c8 37 if (sock < 0) {
Christopher Haster 1:29c61c1420c8 38 return 0;
geky 0:d92b89886434 39 }
geky 0:d92b89886434 40
Christopher Haster 1:29c61c1420c8 41 ifc.ifc_buf = buffer;
Christopher Haster 1:29c61c1420c8 42 ifc.ifc_len = sizeof buffer;
Christopher Haster 1:29c61c1420c8 43 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
Christopher Haster 3:eabc4ea66a64 44 ::close(sock);
Christopher Haster 3:eabc4ea66a64 45 return false;
geky 0:d92b89886434 46 }
geky 0:d92b89886434 47
Christopher Haster 1:29c61c1420c8 48 for (int i = 0; i < ifc.ifc_len; i++) {
Christopher Haster 3:eabc4ea66a64 49 strcpy(ifr->ifr_name, ifc.ifc_req[i].ifr_name);
geky 0:d92b89886434 50
Christopher Haster 3:eabc4ea66a64 51 if (ioctl(sock, SIOCGIFFLAGS, ifr) == 0
Christopher Haster 3:eabc4ea66a64 52 && !(ifr->ifr_flags & IFF_LOOPBACK)
Christopher Haster 3:eabc4ea66a64 53 && ioctl(sock, req, ifr) == 0) {
Christopher Haster 3:eabc4ea66a64 54 ::close(sock);
Christopher Haster 3:eabc4ea66a64 55 return true;
geky 0:d92b89886434 56 }
geky 0:d92b89886434 57 }
geky 0:d92b89886434 58
Christopher Haster 3:eabc4ea66a64 59 ::close(sock);
Christopher Haster 3:eabc4ea66a64 60 return false;
Christopher Haster 3:eabc4ea66a64 61 }
Christopher Haster 3:eabc4ea66a64 62
Christopher Haster 3:eabc4ea66a64 63 const char *BSDInterface::getIPAddress()
Christopher Haster 3:eabc4ea66a64 64 {
Christopher Haster 3:eabc4ea66a64 65 static char ip_address[NS_IP_SIZE] = "\0";
Christopher Haster 3:eabc4ea66a64 66 if (ip_address[0]) {
Christopher Haster 3:eabc4ea66a64 67 return ip_address;
Christopher Haster 3:eabc4ea66a64 68 }
Christopher Haster 3:eabc4ea66a64 69
Christopher Haster 3:eabc4ea66a64 70 struct ifreq ifr;
Christopher Haster 3:eabc4ea66a64 71 if (!ifctl(&ifr, SIOCGIFADDR)) {
Christopher Haster 3:eabc4ea66a64 72 return 0;
Christopher Haster 3:eabc4ea66a64 73 }
Christopher Haster 3:eabc4ea66a64 74
Christopher Haster 3:eabc4ea66a64 75 struct in_addr addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
Christopher Haster 3:eabc4ea66a64 76 strcpy(ip_address, inet_ntoa(addr));
Christopher Haster 3:eabc4ea66a64 77 return ip_address;
Christopher Haster 3:eabc4ea66a64 78 }
Christopher Haster 3:eabc4ea66a64 79
Christopher Haster 3:eabc4ea66a64 80 const char *BSDInterface::getMACAddress()
Christopher Haster 3:eabc4ea66a64 81 {
Christopher Haster 3:eabc4ea66a64 82 static char mac_address[NS_MAC_SIZE] = "\0";
Christopher Haster 3:eabc4ea66a64 83 if (mac_address[0]) {
Christopher Haster 3:eabc4ea66a64 84 return mac_address;
Christopher Haster 3:eabc4ea66a64 85 }
Christopher Haster 3:eabc4ea66a64 86
Christopher Haster 3:eabc4ea66a64 87 struct ifreq ifr;
Christopher Haster 3:eabc4ea66a64 88 if (!ifctl(&ifr, SIOCGIFHWADDR)) {
Christopher Haster 3:eabc4ea66a64 89 return 0;
Christopher Haster 3:eabc4ea66a64 90 }
Christopher Haster 3:eabc4ea66a64 91
Christopher Haster 3:eabc4ea66a64 92 sprintf(mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",
Christopher Haster 3:eabc4ea66a64 93 (unsigned char)ifr.ifr_hwaddr.sa_data[0],
Christopher Haster 3:eabc4ea66a64 94 (unsigned char)ifr.ifr_hwaddr.sa_data[1],
Christopher Haster 3:eabc4ea66a64 95 (unsigned char)ifr.ifr_hwaddr.sa_data[2],
Christopher Haster 3:eabc4ea66a64 96 (unsigned char)ifr.ifr_hwaddr.sa_data[3],
Christopher Haster 3:eabc4ea66a64 97 (unsigned char)ifr.ifr_hwaddr.sa_data[4],
Christopher Haster 3:eabc4ea66a64 98 (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
Christopher Haster 3:eabc4ea66a64 99 return mac_address;
geky 0:d92b89886434 100 }
geky 0:d92b89886434 101
Christopher Haster 2:0978e139e1c5 102 int32_t BSDInterface::getHostByName(const char *name, char *ip)
Christopher Haster 2:0978e139e1c5 103 {
Christopher Haster 2:0978e139e1c5 104 struct hostent *host = gethostbyname(name);
Christopher Haster 2:0978e139e1c5 105 if (!host || host->h_addrtype != AF_INET) {
Christopher Haster 2:0978e139e1c5 106 return NS_ERROR_DNS_FAILURE;
Christopher Haster 2:0978e139e1c5 107 }
Christopher Haster 2:0978e139e1c5 108
Christopher Haster 2:0978e139e1c5 109 strcpy(ip, inet_ntoa(*(struct in_addr *)host->h_addr));
Christopher Haster 2:0978e139e1c5 110 return 0;
Christopher Haster 2:0978e139e1c5 111 }
Christopher Haster 2:0978e139e1c5 112
Christopher Haster 4:28479a7d15ad 113 SocketInterface *BSDInterface::createSocket(ns_protocol_t proto)
geky 0:d92b89886434 114 {
Christopher Haster 4:28479a7d15ad 115 int type = (proto == NS_UDP) ? SOCK_DGRAM : SOCK_STREAM;
Christopher Haster 2:0978e139e1c5 116 int fd = ::socket(AF_INET, type, 0);
geky 0:d92b89886434 117 if (fd < 0) {
geky 0:d92b89886434 118 return 0;
geky 0:d92b89886434 119 }
geky 0:d92b89886434 120
Christopher Haster 1:29c61c1420c8 121 return new BSDSocket(fd);
geky 0:d92b89886434 122 }
geky 0:d92b89886434 123
Christopher Haster 1:29c61c1420c8 124 void BSDInterface::destroySocket(SocketInterface *socket)
geky 0:d92b89886434 125 {
Christopher Haster 2:0978e139e1c5 126 ::close(((BSDSocket*)socket)->fd);
geky 0:d92b89886434 127 delete socket;
geky 0:d92b89886434 128 }
geky 0:d92b89886434 129
geky 0:d92b89886434 130
Christopher Haster 5:1af10f9d9404 131 // BSDSocket implementation
Christopher Haster 5:1af10f9d9404 132 int32_t BSDInterface::BSDSocket::open(const char *ip, uint16_t port)
geky 0:d92b89886434 133 {
Christopher Haster 1:29c61c1420c8 134 struct sockaddr_in host;
geky 0:d92b89886434 135 memset(&host, 0, sizeof host);
geky 0:d92b89886434 136 host.sin_family = AF_INET;
geky 0:d92b89886434 137 host.sin_port = htons(port);
Christopher Haster 1:29c61c1420c8 138 inet_pton(AF_INET, ip, &host.sin_addr);
geky 0:d92b89886434 139
Christopher Haster 2:0978e139e1c5 140 if (::connect(fd, (struct sockaddr *)&host, sizeof host) < 0) {
geky 0:d92b89886434 141 return NS_ERROR_NO_CONNECTION;
geky 0:d92b89886434 142 }
geky 0:d92b89886434 143
geky 0:d92b89886434 144 return 0;
geky 0:d92b89886434 145 }
geky 0:d92b89886434 146
Christopher Haster 5:1af10f9d9404 147 int32_t BSDInterface::BSDSocket::close()
geky 0:d92b89886434 148 {
geky 0:d92b89886434 149 return 0;
geky 0:d92b89886434 150 }
geky 0:d92b89886434 151
Christopher Haster 5:1af10f9d9404 152 int32_t BSDInterface::BSDSocket::send(const void *data, uint32_t size)
geky 0:d92b89886434 153 {
Christopher Haster 1:29c61c1420c8 154 if (::send(fd, data, size, 0) < 0) {
Christopher Haster 1:29c61c1420c8 155 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 156 }
geky 0:d92b89886434 157
geky 6:363dd62309cf 158 return size;
geky 0:d92b89886434 159 }
geky 0:d92b89886434 160
Christopher Haster 5:1af10f9d9404 161 int32_t BSDInterface::BSDSocket::recv(void *data, uint32_t size)
geky 0:d92b89886434 162 {
Christopher Haster 1:29c61c1420c8 163 int ret = ::recv(fd, data, size, MSG_DONTWAIT);
geky 0:d92b89886434 164
geky 0:d92b89886434 165 if (ret > 0) {
geky 0:d92b89886434 166 return ret;
Christopher Haster 1:29c61c1420c8 167 } else if (errno == EAGAIN) {
geky 6:363dd62309cf 168 return NS_ERROR_WOULD_BLOCK;
geky 0:d92b89886434 169 } else {
geky 0:d92b89886434 170 return NS_ERROR_DEVICE_ERROR;
geky 0:d92b89886434 171 }
geky 0:d92b89886434 172 }
geky 0:d92b89886434 173
geky 0:d92b89886434 174