self-connect.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Author: Dmitry Safonov <dima@arista.com> */
  3. #include <inttypes.h>
  4. #include "aolib.h"
  5. static union tcp_addr local_addr;
  6. static void __setup_lo_intf(const char *lo_intf,
  7. const char *addr_str, uint8_t prefix)
  8. {
  9. if (inet_pton(TEST_FAMILY, addr_str, &local_addr) != 1)
  10. test_error("Can't convert local ip address");
  11. if (ip_addr_add(lo_intf, TEST_FAMILY, local_addr, prefix))
  12. test_error("Failed to add %s ip address", lo_intf);
  13. if (link_set_up(lo_intf))
  14. test_error("Failed to bring %s up", lo_intf);
  15. if (ip_route_add(lo_intf, TEST_FAMILY, local_addr, local_addr))
  16. test_error("Failed to add a local route %s", lo_intf);
  17. }
  18. static void setup_lo_intf(const char *lo_intf)
  19. {
  20. #ifdef IPV6_TEST
  21. __setup_lo_intf(lo_intf, "::1", 128);
  22. #else
  23. __setup_lo_intf(lo_intf, "127.0.0.1", 8);
  24. #endif
  25. }
  26. static void tcp_self_connect(const char *tst, unsigned int port,
  27. bool different_keyids, bool check_restore)
  28. {
  29. struct tcp_counters before, after;
  30. uint64_t before_aogood, after_aogood;
  31. struct netstat *ns_before, *ns_after;
  32. const size_t nr_packets = 20;
  33. struct tcp_ao_repair ao_img;
  34. struct tcp_sock_state img;
  35. sockaddr_af addr;
  36. int sk;
  37. tcp_addr_to_sockaddr_in(&addr, &local_addr, htons(port));
  38. sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
  39. if (sk < 0)
  40. test_error("socket()");
  41. if (different_keyids) {
  42. if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 5, 7))
  43. test_error("setsockopt(TCP_AO_ADD_KEY)");
  44. if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 7, 5))
  45. test_error("setsockopt(TCP_AO_ADD_KEY)");
  46. } else {
  47. if (test_add_key(sk, DEFAULT_TEST_PASSWORD, local_addr, -1, 100, 100))
  48. test_error("setsockopt(TCP_AO_ADD_KEY)");
  49. }
  50. if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0)
  51. test_error("bind()");
  52. ns_before = netstat_read();
  53. before_aogood = netstat_get(ns_before, "TCPAOGood", NULL);
  54. if (test_get_tcp_counters(sk, &before))
  55. test_error("test_get_tcp_counters()");
  56. if (__test_connect_socket(sk, "lo", (struct sockaddr *)&addr,
  57. sizeof(addr), 0) < 0) {
  58. ns_after = netstat_read();
  59. netstat_print_diff(ns_before, ns_after);
  60. test_error("failed to connect()");
  61. }
  62. if (test_client_verify(sk, 100, nr_packets)) {
  63. test_fail("%s: tcp connection verify failed", tst);
  64. close(sk);
  65. return;
  66. }
  67. ns_after = netstat_read();
  68. after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
  69. if (test_get_tcp_counters(sk, &after))
  70. test_error("test_get_tcp_counters()");
  71. if (!check_restore) {
  72. /* to debug: netstat_print_diff(ns_before, ns_after); */
  73. netstat_free(ns_before);
  74. }
  75. netstat_free(ns_after);
  76. if (after_aogood <= before_aogood) {
  77. test_fail("%s: TCPAOGood counter mismatch: %" PRIu64 " <= %" PRIu64,
  78. tst, after_aogood, before_aogood);
  79. close(sk);
  80. return;
  81. }
  82. if (test_assert_counters(tst, &before, &after, TEST_CNT_GOOD)) {
  83. close(sk);
  84. return;
  85. }
  86. if (!check_restore) {
  87. test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
  88. tst, before_aogood, after_aogood);
  89. close(sk);
  90. return;
  91. }
  92. test_enable_repair(sk);
  93. test_sock_checkpoint(sk, &img, &addr);
  94. #ifdef IPV6_TEST
  95. addr.sin6_port = htons(port + 1);
  96. #else
  97. addr.sin_port = htons(port + 1);
  98. #endif
  99. test_ao_checkpoint(sk, &ao_img);
  100. test_kill_sk(sk);
  101. sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
  102. if (sk < 0)
  103. test_error("socket()");
  104. test_enable_repair(sk);
  105. __test_sock_restore(sk, "lo", &img, &addr, &addr, sizeof(addr));
  106. if (different_keyids) {
  107. if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
  108. local_addr, -1, 7, 5))
  109. test_error("setsockopt(TCP_AO_ADD_KEY)");
  110. if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
  111. local_addr, -1, 5, 7))
  112. test_error("setsockopt(TCP_AO_ADD_KEY)");
  113. } else {
  114. if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0,
  115. local_addr, -1, 100, 100))
  116. test_error("setsockopt(TCP_AO_ADD_KEY)");
  117. }
  118. test_ao_restore(sk, &ao_img);
  119. test_disable_repair(sk);
  120. test_sock_state_free(&img);
  121. if (test_client_verify(sk, 100, nr_packets)) {
  122. test_fail("%s: tcp connection verify failed", tst);
  123. close(sk);
  124. return;
  125. }
  126. ns_after = netstat_read();
  127. after_aogood = netstat_get(ns_after, "TCPAOGood", NULL);
  128. /* to debug: netstat_print_diff(ns_before, ns_after); */
  129. netstat_free(ns_before);
  130. netstat_free(ns_after);
  131. close(sk);
  132. if (after_aogood <= before_aogood) {
  133. test_fail("%s: TCPAOGood counter mismatch: %" PRIu64 " <= %" PRIu64,
  134. tst, after_aogood, before_aogood);
  135. return;
  136. }
  137. test_ok("%s: connect TCPAOGood %" PRIu64 " => %" PRIu64,
  138. tst, before_aogood, after_aogood);
  139. }
  140. static void *client_fn(void *arg)
  141. {
  142. unsigned int port = test_server_port;
  143. setup_lo_intf("lo");
  144. tcp_self_connect("self-connect(same keyids)", port++, false, false);
  145. /* expecting rnext to change based on the first segment RNext != Current */
  146. trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
  147. port, port, 0, -1, -1, -1, -1, -1, 7, 5, -1);
  148. tcp_self_connect("self-connect(different keyids)", port++, true, false);
  149. tcp_self_connect("self-connect(restore)", port, false, true);
  150. port += 2; /* restore test restores over different port */
  151. trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
  152. port, port, 0, -1, -1, -1, -1, -1, 7, 5, -1);
  153. /* intentionally on restore they are added to the socket in different order */
  154. trace_ao_event_expect(TCP_AO_RNEXT_REQUEST, local_addr, local_addr,
  155. port + 1, port + 1, 0, -1, -1, -1, -1, -1, 5, 7, -1);
  156. tcp_self_connect("self-connect(restore, different keyids)", port, true, true);
  157. port += 2; /* restore test restores over different port */
  158. return NULL;
  159. }
  160. int main(int argc, char *argv[])
  161. {
  162. test_init(5, client_fn, NULL);
  163. return 0;
  164. }