Commit 48abc6f1 authored by torinmr@chromium.org's avatar torinmr@chromium.org

Prepared newlib toolchain for socket implementation

Now that appropriate socket headers have been found for newlib,
two things need to be done before socket implementation work can begin.
First, wrappers must be added to kernel_wrap_newlib. Second, some
helper functions provided by glibc need to be implemented. This CL
does both. In particular, inet_ntoa() and inet_ntop() have been
implemented, allowing the conversion of IPv4 and IPv6 addresses
to strings.

NOTRY=true
BUG=None
TEST=None
R=noelallen@chromium.org,bradnelson@google.com

Review URL: https://chromiumcodereview.appspot.com/21610003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215937 0039d316-1c4b-4281-b951-d872f2087c98
parent c3ee3546
......@@ -828,6 +828,7 @@ src/jsoncpp/README.chromium
src/Makefile
src/nacl_io/event_emitter.cc
src/nacl_io/event_listener.cc
src/nacl_io/inet_ntoa.cc
src/nacl_io/kernel_handle.cc
src/nacl_io/kernel_intercept.cc
src/nacl_io/kernel_object.cc
......
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "nacl_io/ossocket.h"
#ifdef PROVIDES_SOCKET_API
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <string>
static inline uint8_t get_byte(const void* addr, int byte) {
const char* buf = static_cast<const char*>(addr);
return static_cast<uint8_t>(buf[byte]);
}
char* inet_ntoa(struct in_addr in) {
static char addr[INET_ADDRSTRLEN];
snprintf(addr, INET_ADDRSTRLEN, "%u.%u.%u.%u",
get_byte(&in, 0), get_byte(&in, 1),
get_byte(&in, 2), get_byte(&in, 3));
return addr;
}
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) {
if (AF_INET == af) {
if (size < INET_ADDRSTRLEN) {
errno = ENOSPC;
return NULL;
}
struct in_addr in;
memcpy(&in, src, sizeof(in));
char* result = inet_ntoa(in);
memcpy(dst, result, strlen(result) + 1);
return dst;
}
if (AF_INET6 == af) {
if (size < INET6_ADDRSTRLEN) {
errno = ENOSPC;
return NULL;
}
const uint8_t* tuples = static_cast<const uint8_t*>(src);
std::stringstream output;
for (int i = 0; i < 8; i++) {
uint16_t tuple = (tuples[2*i] << 8) + tuples[2*i+1];
output << std::hex << tuple;
if (i < 7) {
output << ":";
}
}
memcpy(dst, output.str().c_str(), output.str().size() + 1);
return dst;
}
errno = EAFNOSUPPORT;
return NULL;
}
#endif // PROVIDES_SOCKET_API
......@@ -118,11 +118,11 @@ int WRAP(seek)(int fd, off_t offset, int whence, off_t* new_offset) {
return (*new_offset < 0) ? errno : 0;
}
int WRAP(stat)(const char *pathname, struct stat *buf) {
int WRAP(stat)(const char* pathname, struct stat* buf) {
return (ki_stat(pathname, buf) < 0) ? errno : 0;
}
int WRAP(write)(int fd, const void *buf, size_t count, size_t *nwrote) {
int WRAP(write)(int fd, const void* buf, size_t count, size_t* nwrote) {
if (!ki_is_initialized())
return REAL(write)(fd, buf, count, nwrote);
......@@ -131,6 +131,76 @@ int WRAP(write)(int fd, const void *buf, size_t count, size_t *nwrote) {
return (signed_nwrote < 0) ? errno : 0;
}
// Socket functions
int accept(int fd, struct sockaddr* addr, socklen_t* len) {
return ki_accept(fd, addr, len);
}
int bind(int fd, const struct sockaddr* addr, socklen_t len) {
return ki_bind(fd, addr, len);
}
int connect(int fd, const struct sockaddr* addr, socklen_t len) {
return ki_connect(fd, addr, len);
}
int getpeername(int fd, struct sockaddr* addr, socklen_t* len) {
return ki_getpeername(fd, addr, len);
}
int getsockname(int fd, struct sockaddr* addr, socklen_t* len) {
return ki_getsockname(fd, addr, len);
}
int getsockopt(int fd, int lvl, int optname, void* optval, socklen_t* len) {
return ki_getsockopt(fd, lvl, optname, optval, len);
}
int listen(int fd, int backlog) {
return ki_listen(fd, backlog);
}
ssize_t recv(int fd, void* buf, size_t len, int flags) {
return ki_recv(fd, buf, len, flags);
}
ssize_t recvfrom(int fd, void* buf, size_t len, int flags,
struct sockaddr* addr, socklen_t* addrlen) {
return ki_recvfrom(fd, buf, len, flags, addr, addrlen);
}
ssize_t recvmsg(int fd, struct msghdr* msg, int flags) {
return ki_recvmsg(fd, msg, flags);
}
ssize_t send(int fd, const void* buf, size_t len, int flags) {
return ki_send(fd, buf, len, flags);
}
ssize_t sendto(int fd, const void* buf, size_t len, int flags,
const struct sockaddr* addr, socklen_t addrlen) {
return ki_sendto(fd, buf, len, flags, addr, addrlen);
}
ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
return ki_sendmsg(fd, msg, flags);
}
int setsockopt(int fd, int lvl, int optname, const void* optval,
socklen_t len) {
return ki_setsockopt(fd, lvl, optname, optval, len);
}
int shutdown(int fd, int how) {
return ki_shutdown(fd, how);
}
int socket(int domain, int type, int protocol) {
return ki_socket(domain, type, protocol);
}
int socketpair(int domain, int type, int protocol, int* sv) {
return ki_socketpair(domain, type, protocol, sv);
}
// "real" functions, i.e. the unwrapped original functions.
......@@ -138,11 +208,11 @@ int _real_close(int fd) {
return REAL(close)(fd);
}
int _real_fstat(int fd, struct stat *buf) {
int _real_fstat(int fd, struct stat* buf) {
return REAL(fstat)(fd, buf);
}
int _real_getdents(int fd, dirent* nacl_buf, size_t nacl_count, size_t *nread) {
int _real_getdents(int fd, dirent* nacl_buf, size_t nacl_count, size_t* nread) {
return REAL(getdents)(fd, nacl_buf, nacl_count, nread);
}
......@@ -171,7 +241,7 @@ int _real_open_resource(const char* file, int* fd) {
return ENOSYS;
}
int _real_read(int fd, void *buf, size_t count, size_t *nread) {
int _real_read(int fd, void* buf, size_t count, size_t* nread) {
return REAL(read)(fd, buf, count, nread);
}
......@@ -179,7 +249,7 @@ int _real_rmdir(const char* pathname) {
return ENOSYS;
}
int _real_write(int fd, const void *buf, size_t count, size_t *nwrote) {
int _real_write(int fd, const void* buf, size_t count, size_t* nwrote) {
return REAL(write)(fd, buf, count, nwrote);
}
......
......@@ -12,6 +12,7 @@
'SOURCES' : [
"event_emitter.cc",
"event_listener.cc",
"inet_ntoa.cc",
"kernel_handle.cc",
"kernel_intercept.cc",
"kernel_object.cc",
......
......@@ -5,7 +5,7 @@
#ifndef LIBRARIES_NACL_IO_OSSOCKET_H_
#define LIBRARIES_NACL_IO_OSSOCKET_H_
#if defined(__native_client__) && defined(__GLIBC__)
#if defined(__native_client__)
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
......
......@@ -259,4 +259,111 @@ TEST_F(SocketTest, Socketpair) {
EXPECT_EQ(errno, EPROTONOSUPPORT);
}
// These functions don't go through KernelProxy, so they don't require a test
// fixture
static struct in_addr generate_ipv4_addr(int tuple1, int tuple2,
int tuple3, int tuple4) {
unsigned char addr[4];
addr[0] = static_cast<unsigned char>(tuple1);
addr[1] = static_cast<unsigned char>(tuple2);
addr[2] = static_cast<unsigned char>(tuple3);
addr[3] = static_cast<unsigned char>(tuple4);
struct in_addr* real_addr = reinterpret_cast<struct in_addr*>(addr);
return *real_addr;
}
static struct in6_addr generate_ipv6_addr(int* tuples) {
unsigned char addr[16];
for (int i = 0; i < 8; i++) {
addr[2*i] = (tuples[i] >> 8) & 0xFF;
addr[2*i+1] = tuples[i] & 0xFF;
}
struct in6_addr* real_addr = reinterpret_cast<struct in6_addr*>(addr);
return *real_addr;
}
TEST(SocketUtilityFunctions, Inet_ntoa) {
char* stringified_addr = inet_ntoa(generate_ipv4_addr(0,0,0,0));
ASSERT_TRUE(NULL != stringified_addr);
EXPECT_STREQ("0.0.0.0", stringified_addr);
stringified_addr = inet_ntoa(generate_ipv4_addr(127,0,0,1));
ASSERT_TRUE(NULL != stringified_addr);
EXPECT_STREQ("127.0.0.1", stringified_addr);
stringified_addr = inet_ntoa(generate_ipv4_addr(255,255,255,255));
ASSERT_TRUE(NULL != stringified_addr);
EXPECT_STREQ("255.255.255.255", stringified_addr);
}
TEST(SocketUtilityFunctions, Inet_ntop_ipv4) {
char stringified_addr[INET_ADDRSTRLEN];
struct in_addr real_addr = generate_ipv4_addr(0,0,0,0);
EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr,
stringified_addr, INET_ADDRSTRLEN));
EXPECT_STREQ("0.0.0.0", stringified_addr);
real_addr = generate_ipv4_addr(127,0,0,1);
EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr,
stringified_addr, INET_ADDRSTRLEN));
EXPECT_STREQ("127.0.0.1", stringified_addr);
real_addr = generate_ipv4_addr(255,255,255,255);
EXPECT_TRUE(NULL != inet_ntop(AF_INET, &real_addr,
stringified_addr, INET_ADDRSTRLEN));
EXPECT_STREQ("255.255.255.255", stringified_addr);
}
TEST(SocketUtilityFunctions, Inet_ntop_ipv6) {
char stringified_addr[INET6_ADDRSTRLEN];
{
int addr_tuples[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
struct in6_addr real_addr = generate_ipv6_addr(addr_tuples);
EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr,
stringified_addr, INET6_ADDRSTRLEN));
EXPECT_STREQ("0:0:0:0:0:0:0:0", stringified_addr);
}
{
int addr_tuples[8] = { 0x1234, 0xa, 0x12, 0x0000,
0x5678, 0x9abc, 0xdef, 0xffff };
struct in6_addr real_addr = generate_ipv6_addr(addr_tuples);
EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr,
stringified_addr, INET6_ADDRSTRLEN));
EXPECT_STREQ("1234:a:12:0:5678:9abc:def:ffff", stringified_addr);
}
{
int addr_tuples[8] = { 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff };
struct in6_addr real_addr = generate_ipv6_addr(addr_tuples);
EXPECT_TRUE(NULL != inet_ntop(AF_INET6, &real_addr,
stringified_addr, INET6_ADDRSTRLEN));
EXPECT_STREQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", stringified_addr);
}
}
TEST(SocketUtilityFunctions, Inet_ntop_failure) {
char addr_name[INET6_ADDRSTRLEN];
int addr_tuples[8] = { 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff };
struct in6_addr ipv6_addr = generate_ipv6_addr(addr_tuples);
struct in_addr ipv4_addr = generate_ipv4_addr(255,255,255,255);
EXPECT_TRUE(NULL == inet_ntop(AF_UNIX, &ipv6_addr,
addr_name, INET6_ADDRSTRLEN));
EXPECT_EQ(errno, EAFNOSUPPORT);
EXPECT_TRUE(NULL == inet_ntop(AF_INET, &ipv4_addr,
addr_name, INET_ADDRSTRLEN - 1));
EXPECT_EQ(errno, ENOSPC);
EXPECT_TRUE(NULL == inet_ntop(AF_INET6, &ipv6_addr,
addr_name, INET6_ADDRSTRLEN - 1));
EXPECT_EQ(errno, ENOSPC);
}
#endif // PROVIDES_SOCKETPAIR_API
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment