2 Raw socket (un) marshalling tests
4 Copyright (C) Martin Schwenke 2018
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 /* For ether_aton() */
26 #include <arpa/inet.h>
29 #include <net/ethernet.h>
32 #include <netinet/ether.h>
35 #include "common/system_socket.c"
37 #include "protocol/protocol_util.h"
39 static void test_types(void)
42 * We use this struct in the code but don't pack it due to
43 * portability concerns. It should have no padding.
50 assert(sizeof(ip4pkt) == sizeof(struct ip) + sizeof(struct tcphdr));
53 #ifdef HAVE_PACKETSOCKET
55 static void test_arp(const char *addr_str, const char *hwaddr_str, bool reply)
58 struct ether_addr *hw, *dhw;
60 size_t buflen = sizeof(buf);
65 ret = ctdb_sock_addr_from_string(addr_str, &addr, false);
68 hw = ether_aton(hwaddr_str);
71 switch (addr.ip.sin_family) {
73 ret = arp_build(buf, buflen, &addr.ip, hw, reply, &dhw, &len);
76 ret = ip6_na_build(buf, buflen, &addr.ip6, hw, &dhw, &len);
84 num_written = write(STDOUT_FILENO, buf, len);
85 assert(num_written != -1 && (size_t)num_written == len);
88 #else /* HAVE_PACKETSOCKET */
90 static void test_arp(const char *addr_str, const char *hwaddr_str, bool reply)
92 fprintf(stderr, "PACKETSOCKET not supported\n");
95 #endif /* HAVE_PACKETSOCKET */
97 static void test_tcp(const char *src_str,
103 ctdb_sock_addr src, dst;
107 struct ether_header *eth;
108 size_t expected_len, len;
110 char src_str_out[64], dst_str_out[64];
111 uint32_t seq_out, ack_out;
116 ret = ctdb_sock_addr_from_string(src_str, &src, true);
119 ret = ctdb_sock_addr_from_string(dst_str, &dst, true);
126 /* Need to fake this up */
127 eth = (struct ether_header *) buf;
128 memset(eth, 0, sizeof(*eth));
130 switch (src.ip.sin_family) {
132 eth->ether_type = htons(ETHERTYPE_IP);
134 ret = tcp4_build(buf + sizeof(struct ether_header),
135 sizeof(buf) - sizeof(struct ether_header),
144 eth->ether_type = htons(ETHERTYPE_IP6);
146 ret = tcp6_build(buf + sizeof(struct ether_header),
147 sizeof(buf) - sizeof(struct ether_header),
160 assert(len == expected_len);
162 num_written = write(STDOUT_FILENO,
163 buf + sizeof(struct ether_header),
165 assert(num_written != -1 && (size_t)num_written == len);
167 switch (ntohs(eth->ether_type)) {
169 ret = tcp4_extract(buf + sizeof(struct ether_header),
179 ret = tcp6_extract(buf + sizeof(struct ether_header),
194 assert(seq == seq_out);
195 assert(ack == ack_out);
196 assert((rst != 0) == (rst_out != 0));
197 assert(window == htons(1234));
199 ret = ctdb_sock_addr_to_buf(src_str_out, sizeof(src_str_out),
202 ret = strcmp(src_str, src_str_out);
205 ret = ctdb_sock_addr_to_buf(dst_str_out, sizeof(dst_str_out),
208 ret = strcmp(dst_str, dst_str_out);
212 static void usage(const char *prog)
214 fprintf(stderr, "usage: %s <cmd> [<arg> ...]\n", prog);
215 fprintf(stderr, " commands:\n");
216 fprintf(stderr, " types\n");
217 fprintf(stderr, " arp <ipaddr> <hwaddr> [reply]\n");
218 fprintf(stderr, " tcp <src> <dst> <seq> <ack> <rst>\n");
223 int main(int argc, char **argv)
230 if (strcmp(argv[1], "types") == 0) {
232 } else if (strcmp(argv[1], "arp") == 0) {
234 * Extra arg indicates that a reply should be
235 * constructed for IPv4 - value is ignored
237 if (argc != 4 && argc != 5) {
240 test_arp(argv[2], argv[3], (argc == 5));
241 } else if (strcmp(argv[1], "tcp") == 0) {
245 test_tcp(argv[2], argv[3], argv[4], argv[5], argv[6]);