| /* |
| * Copyright (c) 2015 Intel Corporation |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1) Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2) Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3) Neither the name of Intel Corporation nor the names of its contributors |
| * may be used to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <stdio.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <poll.h> |
| #include <errno.h> |
| #include <arpa/inet.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdbool.h> |
| #include <net/if.h> |
| #include <linux/sockios.h> |
| #include <ifaddrs.h> |
| |
| #define SERVER_PORT 4242 |
| #define CLIENT_PORT 8484 |
| #define MAX_BUF_SIZE 1280 /* min IPv6 MTU, the actual data is smaller */ |
| #define MAX_TIMEOUT 1 /* in seconds */ |
| |
| #define ENTRY(e, expect_result) { sizeof(e), e, expect_result } |
| #define ENTRY_OK(e) ENTRY(e, true) |
| #define ENTRY_FAIL(e) ENTRY(e, false) |
| |
| static const unsigned char A[] = { 'A' }; |
| static const unsigned char null_byte[] = { 0x00 }; |
| static const unsigned char foobar[] = { 'f','o','o','b','a','r' }; |
| static const unsigned char small_binary[] = { 0x20, 0xff, 0x00, 0x56 }; |
| |
| /* Next entry is 1280 bytes long which is the maximum length the IP stack |
| * can support. |
| */ |
| static const unsigned char lorem_ipsum[] = \ |
| "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue non neque vel tempor. In id porta nibh, ut cursus tortor. Morbi eleifend tristique vehicula. Nunc vitae risus mauris. Praesent vel imperdiet dolor, et ultricies nibh. Aliquam erat volutpat. Maecenas pellentesque dolor vitae dictum tincidunt. Fusce vel nibh nec leo tristique auctor eu a massa. Nam et tellus ac tortor sollicitudin semper vitae nec tortor. Aliquam nec lacus velit. Maecenas ornare ullamcorper justo non auctor. Donec aliquam feugiat turpis, quis elementum sem rutrum ut. Sed eu ullamcorper libero, ut suscipit magna." |
| "\n" |
| "Donec vehicula magna ut varius aliquam. Ut vitae commodo nulla, quis ornare dolor. Nulla tortor sem, venenatis eu iaculis id, commodo ut massa. Sed est lorem, euismod vitae enim sed, hendrerit gravida felis. Donec eros lacus, auctor ut ultricies eget, lobortis quis nisl. Aliquam sit amet blandit eros. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque egestas nisl leo, sed consectetur leo ornare eu. Suspendisse vitae urna vel purus maximus finibus. Proin sed sollicitudin turpis. Mauris interdum neque eu tellus pellentesque, id fringilla nisi fermentum. Suspendisse gravida pharetra sodales orci aliquam\n"; |
| |
| /* 256 bytes of binary data */ |
| static const unsigned char array_256[] = { |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00 |
| }; |
| |
| /* 1280 bytes of binary data */ |
| static const unsigned char array_1280[] = { |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00, |
| 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, |
| 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, |
| 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, |
| 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, |
| 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, |
| 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, |
| 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, |
| 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
| 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, |
| 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
| 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, |
| 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, |
| 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
| 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, |
| 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, |
| 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, |
| 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
| 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, |
| 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, |
| 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, |
| 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, |
| 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, |
| 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, |
| 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, |
| 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, |
| 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, |
| 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, |
| 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, |
| 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
| 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x00 |
| }; |
| |
| static struct { |
| int len; |
| const unsigned char *buf; |
| bool expecting_reply; |
| } data[] = { |
| ENTRY_OK(A), |
| ENTRY_OK(foobar), |
| ENTRY_OK(small_binary), |
| ENTRY_OK("a bit longer data message"), |
| ENTRY_OK(lorem_ipsum), |
| ENTRY_OK(null_byte), |
| ENTRY_OK(array_256), |
| ENTRY_FAIL(array_1280), /* too long message will be discarded */ |
| |
| { 0, 0 } |
| }; |
| |
| static inline void reverse(unsigned char *buf, int len) |
| { |
| int i, last = len - 1; |
| |
| for(i = 0; i < len/2; i++) { |
| unsigned char tmp = buf[i]; |
| buf[i] = buf[last - i]; |
| buf[last - i] = tmp; |
| } |
| } |
| |
| static int get_ifindex(const char *name) |
| { |
| struct ifreq ifr; |
| int sk, err; |
| |
| if (!name) |
| return -1; |
| |
| sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); |
| if (sk < 0) |
| return -1; |
| |
| memset(&ifr, 0, sizeof(ifr)); |
| strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1); |
| |
| err = ioctl(sk, SIOCGIFINDEX, &ifr); |
| |
| close(sk); |
| |
| if (err < 0) |
| return -1; |
| |
| return ifr.ifr_ifindex; |
| } |
| |
| static int get_address(int ifindex, int family, void *address) |
| { |
| struct ifaddrs *ifaddr, *ifa; |
| int err = -ENOENT; |
| char name[IF_NAMESIZE]; |
| |
| if (!if_indextoname(ifindex, name)) |
| return -EINVAL; |
| |
| if (getifaddrs(&ifaddr) < 0) { |
| err = -errno; |
| fprintf(stderr, "Cannot get addresses err %d/%s", |
| err, strerror(-err)); |
| return err; |
| } |
| |
| for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { |
| if (!ifa->ifa_addr) |
| continue; |
| |
| if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 && |
| ifa->ifa_addr->sa_family == family) { |
| if (family == AF_INET) { |
| struct sockaddr_in *in4 = (struct sockaddr_in *) |
| ifa->ifa_addr; |
| if (in4->sin_addr.s_addr == INADDR_ANY) |
| continue; |
| if ((in4->sin_addr.s_addr & IN_CLASSB_NET) == |
| ((in_addr_t) 0xa9fe0000)) |
| continue; |
| memcpy(address, &in4->sin_addr, |
| sizeof(struct in_addr)); |
| } else if (family == AF_INET6) { |
| struct sockaddr_in6 *in6 = |
| (struct sockaddr_in6 *)ifa->ifa_addr; |
| if (memcmp(&in6->sin6_addr, &in6addr_any, |
| sizeof(struct in6_addr)) == 0) |
| continue; |
| if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) |
| continue; |
| |
| memcpy(address, &in6->sin6_addr, |
| sizeof(struct in6_addr)); |
| } else { |
| err = -EINVAL; |
| goto out; |
| } |
| |
| err = 0; |
| break; |
| } |
| } |
| |
| out: |
| freeifaddrs(ifaddr); |
| return err; |
| } |
| |
| extern int optind, opterr, optopt; |
| extern char *optarg; |
| |
| /* The application returns: |
| * < 0 : connection or similar error |
| * 0 : no errors, all tests passed |
| * > 0 : could not send all the data to server |
| */ |
| int main(int argc, char**argv) |
| { |
| int c, ret, fd, i = 0, timeout = -1; |
| bool flood = false, multicast = false; |
| struct sockaddr_in6 addr6_send = { 0 }, addr6_recv = { 0 }; |
| struct sockaddr_in addr4_send = { 0 }, addr4_recv = { 0 }; |
| struct sockaddr *addr_send, *addr_recv; |
| int family, addr_len; |
| unsigned char buf[MAX_BUF_SIZE]; |
| const struct in6_addr any = IN6ADDR_ANY_INIT; |
| const char *target = NULL, *interface = NULL; |
| fd_set rfds; |
| struct timeval tv = {}; |
| int ifindex = -1; |
| void *address = NULL; |
| bool forever = false, help = false; |
| |
| opterr = 0; |
| |
| while ((c = getopt(argc, argv, "Fi:eh")) != -1) { |
| switch (c) { |
| case 'F': |
| flood = true; |
| break; |
| case 'i': |
| interface = optarg; |
| break; |
| case 'e': |
| forever = true; |
| break; |
| case 'h': |
| help = true; |
| break; |
| } |
| } |
| |
| if (optind < argc) |
| target = argv[optind]; |
| |
| if (!target || help) { |
| printf("usage: %s [-i iface] [-F] <IPv{6|4} address of the echo-server>\n", |
| argv[0]); |
| printf("\n-i Use this network interface, needed if using " |
| "multicast server address.\n"); |
| printf("-e Do not quit, send packets forever\n"); |
| printf("-F (flood) option will prevent the client from " |
| "waiting the data.\n" |
| " The -F option will stress test the server.\n"); |
| exit(-EINVAL); |
| } |
| |
| if (inet_pton(AF_INET6, target, &addr6_send.sin6_addr) != 1) { |
| if (inet_pton(AF_INET, target, &addr4_send.sin_addr) != 1) { |
| printf("Invalid address family\n"); |
| exit(-EINVAL); |
| } else { |
| if (IN_MULTICAST(addr4_recv.sin_addr.s_addr)) |
| multicast = true; |
| |
| addr_send = (struct sockaddr *)&addr4_send; |
| addr_recv = (struct sockaddr *)&addr4_recv; |
| addr4_send.sin_port = htons(SERVER_PORT); |
| addr4_recv.sin_family = AF_INET; |
| addr4_recv.sin_addr.s_addr = INADDR_ANY; |
| addr4_recv.sin_port = htons(CLIENT_PORT); |
| family = AF_INET; |
| addr_len = sizeof(addr4_send); |
| address = &addr4_recv.sin_addr; |
| } |
| } else { |
| if (IN6_IS_ADDR_MULTICAST(&addr6_send.sin6_addr)) |
| multicast = true; |
| |
| addr_send = (struct sockaddr *)&addr6_send; |
| addr_recv = (struct sockaddr *)&addr6_recv; |
| addr6_send.sin6_port = htons(SERVER_PORT); |
| addr6_recv.sin6_family = AF_INET6; |
| addr6_recv.sin6_addr = any; |
| addr6_recv.sin6_port = htons(CLIENT_PORT); |
| family = AF_INET6; |
| addr_len = sizeof(addr6_send); |
| address = &addr6_recv.sin6_addr; |
| } |
| |
| addr_send->sa_family = family; |
| addr_recv->sa_family = family; |
| |
| fd = socket(family, SOCK_DGRAM, IPPROTO_UDP); |
| if (fd < 0) { |
| perror("socket"); |
| exit(-errno); |
| } |
| |
| if (interface) { |
| struct ifreq ifr; |
| char addr_buf[INET6_ADDRSTRLEN]; |
| |
| memset(&ifr, 0, sizeof(ifr)); |
| snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface); |
| |
| if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, |
| (void *)&ifr, sizeof(ifr)) < 0) { |
| perror("SO_BINDTODEVICE"); |
| exit(-errno); |
| } |
| |
| ifindex = get_ifindex(interface); |
| if (ifindex < 0) { |
| printf("Invalid interface %s\n", interface); |
| exit(-EINVAL); |
| } |
| |
| get_address(ifindex, family, address); |
| |
| printf("Binding to %s\n", inet_ntop(family, address, |
| addr_buf, sizeof(addr_buf))); |
| } |
| |
| if (multicast) { |
| if (!interface) { |
| printf("Need to use -i option for multicast " |
| "addresses.\n"); |
| exit(-EINVAL); |
| } |
| } |
| |
| ret = bind(fd, addr_recv, addr_len); |
| if (ret < 0) { |
| perror("bind"); |
| exit(-errno); |
| } |
| |
| again: |
| do { |
| while (data[i].buf) { |
| ret = sendto(fd, data[i].buf, data[i].len, 0, |
| addr_send, addr_len); |
| if (ret < 0) { |
| perror("send"); |
| goto out; |
| } |
| |
| if (flood) { |
| i++; |
| continue; |
| } |
| |
| FD_ZERO(&rfds); |
| FD_SET(fd, &rfds); |
| tv.tv_sec = MAX_TIMEOUT; |
| tv.tv_usec = 0; |
| |
| ret = select(fd + 1, &rfds, NULL, NULL, &tv); |
| if (ret < 0) { |
| perror("select"); |
| goto out; |
| } else if (ret == 0) { |
| if (data[i].expecting_reply) { |
| fprintf(stderr, |
| "Timeout while waiting " |
| "idx %d len %d\n", |
| i, data[i].len); |
| timeout = i; |
| } |
| i++; |
| continue; |
| } else if (!FD_ISSET(fd, &rfds)) { |
| fprintf(stderr, "Invalid fd\n"); |
| ret = i; |
| goto out; |
| } |
| |
| ret = recv(fd, buf, sizeof(buf), 0); |
| if (ret <= 0) { |
| perror("recv"); |
| ret = -EINVAL; |
| goto out; |
| } |
| |
| reverse(buf, ret); |
| |
| if (data[i].len != ret || |
| memcmp(data[i].buf, buf, ret) != 0) { |
| fprintf(stderr, |
| "Check failed idx %d len %d\n", |
| i, ret); |
| ret = i; |
| goto out; |
| } else { |
| printf("."); |
| fflush(stdout); |
| } |
| |
| i++; |
| } |
| |
| if (flood) |
| i = 0; |
| |
| } while (flood); |
| |
| if (forever) { |
| i = 0; |
| goto again; |
| } |
| |
| ret = timeout + 1; |
| |
| printf("\n"); |
| |
| out: |
| close(fd); |
| |
| exit(ret); |
| } |