diff options
Diffstat (limited to 'test/packetdrill/wrap.c')
-rw-r--r-- | test/packetdrill/wrap.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/test/packetdrill/wrap.c b/test/packetdrill/wrap.c new file mode 100644 index 0000000..112af2a --- /dev/null +++ b/test/packetdrill/wrap.c @@ -0,0 +1,125 @@ +/* + * Copyright 2013 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * Wrappers for making L3-independent syscalls. + */ + +#include "wrap.h" + +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> +#include "checksum.h" +#include "gre.h" +#include "logging.h" +#include "netdev.h" +#include "packet.h" +#include "packet_checksum.h" +#include "packet_to_string.h" +#include "run.h" +#include "script.h" +#include "tcp_options_iterator.h" +#include "tcp_options_to_string.h" +#include "tcp_packet.h" + +int wrap_socket(enum ip_version_t ip_version, int type) +{ + int fd = -1; + + switch (ip_version) { + case IP_VERSION_4: + fd = socket(AF_INET, type, 0); + if (fd < 0) + die_perror("socket(AF_INET)"); + break; + + case IP_VERSION_4_MAPPED_6: + case IP_VERSION_6: + fd = socket(AF_INET6, type, 0); + if (fd < 0) + die_perror("socket(AF_INET6)"); + break; + + default: + die("bad ip_version (%d) in config\n", ip_version); + break; + } + + return fd; +} + +u16 wrap_bind_listen(int s, enum ip_version_t ip_version, u16 port) +{ + switch (ip_version) { + case IP_VERSION_4: { + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + memset(&addr, 0, addrlen); +#ifndef linux + addr.sin_len = addrlen; +#endif + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if (bind(s, (struct sockaddr *)&addr, addrlen) < 0) + die_perror("bind(AF_INET)"); + + memset(&addr, 0, sizeof(addr)); + if (getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) + die_perror("getsockname(AF_INET)"); + assert(addr.sin_family == AF_INET); + + if (listen(s, 100) < 0) + die_perror("listen(AF_INET)"); + + return ntohs(addr.sin_port); + } + + case IP_VERSION_4_MAPPED_6: + case IP_VERSION_6: { + struct sockaddr_in6 addr6; + socklen_t addrlen = sizeof(addr6); + + memset(&addr6, 0, addrlen); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(port); + + if (bind(s, (struct sockaddr *)&addr6, addrlen) < 0) + die_perror("bind(AF_INET6)"); + + memset(&addr6, 0, sizeof(addr6)); + if (getsockname(s, (struct sockaddr *)&addr6, &addrlen) < 0) + die_perror("getsockname(AF_INET6)"); + assert(addr6.sin6_family == AF_INET6); + + if (listen(s, 100) < 0) + die_perror("listen(AF_INET6)"); + + return ntohs(addr6.sin6_port); + } + + default: + die("bad ip_version (%d) in config\n", ip_version); + return 0; + } +} |