unit-test-client.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. /*
  2. * Copyright © 2008-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <errno.h>
  22. #include <modbus.h>
  23. #include "unit-test.h"
  24. enum {
  25. TCP,
  26. TCP_PI,
  27. RTU
  28. };
  29. int test_raw_request(modbus_t *, int);
  30. int main(int argc, char *argv[])
  31. {
  32. uint8_t *tab_rp_bits = NULL;
  33. uint16_t *tab_rp_registers = NULL;
  34. uint16_t *tab_rp_registers_bad = NULL;
  35. modbus_t *ctx = NULL;
  36. int i;
  37. uint8_t value;
  38. int nb_points;
  39. int rc;
  40. float real;
  41. uint32_t ireal;
  42. uint32_t old_response_to_sec;
  43. uint32_t old_response_to_usec;
  44. uint32_t new_response_to_sec;
  45. uint32_t new_response_to_usec;
  46. uint32_t old_byte_to_sec;
  47. uint32_t old_byte_to_usec;
  48. int use_backend;
  49. if (argc > 1) {
  50. if (strcmp(argv[1], "tcp") == 0) {
  51. use_backend = TCP;
  52. } else if (strcmp(argv[1], "tcppi") == 0) {
  53. use_backend = TCP_PI;
  54. } else if (strcmp(argv[1], "rtu") == 0) {
  55. use_backend = RTU;
  56. } else {
  57. printf("Usage:\n %s [tcp|tcppi|rtu] - Modbus client for unit testing\n\n", argv[0]);
  58. exit(1);
  59. }
  60. } else {
  61. /* By default */
  62. use_backend = TCP;
  63. }
  64. if (use_backend == TCP) {
  65. ctx = modbus_new_tcp("127.0.0.1", 1502);
  66. } else if (use_backend == TCP_PI) {
  67. ctx = modbus_new_tcp_pi("::1", "1502");
  68. } else {
  69. ctx = modbus_new_rtu("/dev/ttyUSB1", 115200, 'N', 8, 1);
  70. }
  71. if (ctx == NULL) {
  72. fprintf(stderr, "Unable to allocate libmodbus context\n");
  73. return -1;
  74. }
  75. modbus_set_debug(ctx, TRUE);
  76. modbus_set_error_recovery(ctx,
  77. MODBUS_ERROR_RECOVERY_LINK |
  78. MODBUS_ERROR_RECOVERY_PROTOCOL);
  79. if (use_backend == RTU) {
  80. modbus_set_slave(ctx, SERVER_ID);
  81. }
  82. modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
  83. if (modbus_connect(ctx) == -1) {
  84. fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
  85. modbus_free(ctx);
  86. return -1;
  87. }
  88. modbus_get_response_timeout(ctx, &new_response_to_sec, &new_response_to_usec);
  89. printf("** UNIT TESTING **\n");
  90. printf("1/1 No response timeout modification on connect: ");
  91. if (old_response_to_sec == new_response_to_sec &&
  92. old_response_to_usec == new_response_to_usec) {
  93. printf("OK\n");
  94. } else {
  95. printf("FAILED\n");
  96. goto close;
  97. }
  98. /* Allocate and initialize the memory to store the bits */
  99. nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB;
  100. tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t));
  101. memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t));
  102. /* Allocate and initialize the memory to store the registers */
  103. nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ?
  104. UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
  105. tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t));
  106. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  107. printf("\nTEST WRITE/READ:\n");
  108. /** COIL BITS **/
  109. /* Single */
  110. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS, ON);
  111. printf("1/2 modbus_write_bit: ");
  112. if (rc == 1) {
  113. printf("OK\n");
  114. } else {
  115. printf("FAILED\n");
  116. goto close;
  117. }
  118. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, 1, tab_rp_bits);
  119. printf("2/2 modbus_read_bits: ");
  120. if (rc != 1) {
  121. printf("FAILED (nb points %d)\n", rc);
  122. goto close;
  123. }
  124. if (tab_rp_bits[0] != ON) {
  125. printf("FAILED (%0X != %0X)\n", tab_rp_bits[0], ON);
  126. goto close;
  127. }
  128. printf("OK\n");
  129. /* End single */
  130. /* Multiple bits */
  131. {
  132. uint8_t tab_value[UT_BITS_NB];
  133. modbus_set_bits_from_bytes(tab_value, 0, UT_BITS_NB, UT_BITS_TAB);
  134. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  135. UT_BITS_NB, tab_value);
  136. printf("1/2 modbus_write_bits: ");
  137. if (rc == UT_BITS_NB) {
  138. printf("OK\n");
  139. } else {
  140. printf("FAILED\n");
  141. goto close;
  142. }
  143. }
  144. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB, tab_rp_bits);
  145. printf("2/2 modbus_read_bits: ");
  146. if (rc != UT_BITS_NB) {
  147. printf("FAILED (nb points %d)\n", rc);
  148. goto close;
  149. }
  150. i = 0;
  151. nb_points = UT_BITS_NB;
  152. while (nb_points > 0) {
  153. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  154. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  155. if (value != UT_BITS_TAB[i]) {
  156. printf("FAILED (%0X != %0X)\n", value, UT_BITS_TAB[i]);
  157. goto close;
  158. }
  159. nb_points -= nb_bits;
  160. i++;
  161. }
  162. printf("OK\n");
  163. /* End of multiple bits */
  164. /** DISCRETE INPUTS **/
  165. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  166. UT_INPUT_BITS_NB, tab_rp_bits);
  167. printf("1/1 modbus_read_input_bits: ");
  168. if (rc != UT_INPUT_BITS_NB) {
  169. printf("FAILED (nb points %d)\n", rc);
  170. goto close;
  171. }
  172. i = 0;
  173. nb_points = UT_INPUT_BITS_NB;
  174. while (nb_points > 0) {
  175. int nb_bits = (nb_points > 8) ? 8 : nb_points;
  176. value = modbus_get_byte_from_bits(tab_rp_bits, i*8, nb_bits);
  177. if (value != UT_INPUT_BITS_TAB[i]) {
  178. printf("FAILED (%0X != %0X)\n", value, UT_INPUT_BITS_TAB[i]);
  179. goto close;
  180. }
  181. nb_points -= nb_bits;
  182. i++;
  183. }
  184. printf("OK\n");
  185. /** HOLDING REGISTERS **/
  186. /* Single register */
  187. rc = modbus_write_register(ctx, UT_REGISTERS_ADDRESS, 0x1234);
  188. printf("1/2 modbus_write_register: ");
  189. if (rc == 1) {
  190. printf("OK\n");
  191. } else {
  192. printf("FAILED\n");
  193. goto close;
  194. }
  195. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  196. 1, tab_rp_registers);
  197. printf("2/2 modbus_read_registers: ");
  198. if (rc != 1) {
  199. printf("FAILED (nb points %d)\n", rc);
  200. goto close;
  201. }
  202. if (tab_rp_registers[0] != 0x1234) {
  203. printf("FAILED (%0X != %0X)\n",
  204. tab_rp_registers[0], 0x1234);
  205. goto close;
  206. }
  207. printf("OK\n");
  208. /* End of single register */
  209. /* Many registers */
  210. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  211. UT_REGISTERS_NB, UT_REGISTERS_TAB);
  212. printf("1/5 modbus_write_registers: ");
  213. if (rc == UT_REGISTERS_NB) {
  214. printf("OK\n");
  215. } else {
  216. printf("FAILED\n");
  217. goto close;
  218. }
  219. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  220. UT_REGISTERS_NB, tab_rp_registers);
  221. printf("2/5 modbus_read_registers: ");
  222. if (rc != UT_REGISTERS_NB) {
  223. printf("FAILED (nb points %d)\n", rc);
  224. goto close;
  225. }
  226. for (i=0; i < UT_REGISTERS_NB; i++) {
  227. if (tab_rp_registers[i] != UT_REGISTERS_TAB[i]) {
  228. printf("FAILED (%0X != %0X)\n",
  229. tab_rp_registers[i],
  230. UT_REGISTERS_TAB[i]);
  231. goto close;
  232. }
  233. }
  234. printf("OK\n");
  235. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  236. 0, tab_rp_registers);
  237. printf("3/5 modbus_read_registers (0): ");
  238. if (rc != -1) {
  239. printf("FAILED (nb_points %d)\n", rc);
  240. goto close;
  241. }
  242. printf("OK\n");
  243. nb_points = (UT_REGISTERS_NB >
  244. UT_INPUT_REGISTERS_NB) ?
  245. UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB;
  246. memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t));
  247. /* Write registers to zero from tab_rp_registers and store read registers
  248. into tab_rp_registers. So the read registers must set to 0, except the
  249. first one because there is an offset of 1 register on write. */
  250. rc = modbus_write_and_read_registers(ctx,
  251. UT_REGISTERS_ADDRESS + 1,
  252. UT_REGISTERS_NB - 1,
  253. tab_rp_registers,
  254. UT_REGISTERS_ADDRESS,
  255. UT_REGISTERS_NB,
  256. tab_rp_registers);
  257. printf("4/5 modbus_write_and_read_registers: ");
  258. if (rc != UT_REGISTERS_NB) {
  259. printf("FAILED (nb points %d != %d)\n", rc, UT_REGISTERS_NB);
  260. goto close;
  261. }
  262. if (tab_rp_registers[0] != UT_REGISTERS_TAB[0]) {
  263. printf("FAILED (%0X != %0X)\n",
  264. tab_rp_registers[0], UT_REGISTERS_TAB[0]);
  265. }
  266. for (i=1; i < UT_REGISTERS_NB; i++) {
  267. if (tab_rp_registers[i] != 0) {
  268. printf("FAILED (%0X != %0X)\n",
  269. tab_rp_registers[i], 0);
  270. goto close;
  271. }
  272. }
  273. printf("OK\n");
  274. /* End of many registers */
  275. /** INPUT REGISTERS **/
  276. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  277. UT_INPUT_REGISTERS_NB,
  278. tab_rp_registers);
  279. printf("1/1 modbus_read_input_registers: ");
  280. if (rc != UT_INPUT_REGISTERS_NB) {
  281. printf("FAILED (nb points %d)\n", rc);
  282. goto close;
  283. }
  284. for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
  285. if (tab_rp_registers[i] != UT_INPUT_REGISTERS_TAB[i]) {
  286. printf("FAILED (%0X != %0X)\n",
  287. tab_rp_registers[i], UT_INPUT_REGISTERS_TAB[i]);
  288. goto close;
  289. }
  290. }
  291. printf("OK\n");
  292. printf("\nTEST FLOATS\n");
  293. /** FLOAT **/
  294. printf("1/4 Set float: ");
  295. modbus_set_float(UT_REAL, tab_rp_registers);
  296. if (tab_rp_registers[1] == (UT_IREAL >> 16) &&
  297. tab_rp_registers[0] == (UT_IREAL & 0xFFFF)) {
  298. printf("OK\n");
  299. } else {
  300. /* Avoid *((uint32_t *)tab_rp_registers)
  301. * https://github.com/stephane/libmodbus/pull/104 */
  302. ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
  303. ireal |= (uint32_t) tab_rp_registers[1] << 16;
  304. printf("FAILED (%x != %x)\n", ireal, UT_IREAL);
  305. goto close;
  306. }
  307. printf("2/4 Get float: ");
  308. real = modbus_get_float(tab_rp_registers);
  309. if (real == UT_REAL) {
  310. printf("OK\n");
  311. } else {
  312. printf("FAILED (%f != %f)\n", real, UT_REAL);
  313. goto close;
  314. }
  315. printf("3/4 Set float in DBCA order: ");
  316. modbus_set_float_dcba(UT_REAL, tab_rp_registers);
  317. if (tab_rp_registers[1] == (UT_IREAL_DCBA >> 16) &&
  318. tab_rp_registers[0] == (UT_IREAL_DCBA & 0xFFFF)) {
  319. printf("OK\n");
  320. } else {
  321. ireal = (uint32_t) tab_rp_registers[0] & 0xFFFF;
  322. ireal |= (uint32_t) tab_rp_registers[1] << 16;
  323. printf("FAILED (%x != %x)\n", ireal, UT_IREAL_DCBA);
  324. goto close;
  325. }
  326. printf("4/4 Get float in DCBA order: ");
  327. real = modbus_get_float_dcba(tab_rp_registers);
  328. if (real == UT_REAL) {
  329. printf("OK\n");
  330. } else {
  331. printf("FAILED (%f != %f)\n", real, UT_REAL);
  332. goto close;
  333. }
  334. printf("\nAt this point, error messages doesn't mean the test has failed\n");
  335. /** ILLEGAL DATA ADDRESS **/
  336. printf("\nTEST ILLEGAL DATA ADDRESS:\n");
  337. /* The mapping begins at 0 and ends at address + nb_points so
  338. * the addresses are not valid. */
  339. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  340. UT_BITS_NB + 1, tab_rp_bits);
  341. printf("* modbus_read_bits: ");
  342. if (rc == -1 && errno == EMBXILADD) {
  343. printf("OK\n");
  344. } else {
  345. printf("FAILED\n");
  346. goto close;
  347. }
  348. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  349. UT_INPUT_BITS_NB + 1, tab_rp_bits);
  350. printf("* modbus_read_input_bits: ");
  351. if (rc == -1 && errno == EMBXILADD)
  352. printf("OK\n");
  353. else {
  354. printf("FAILED\n");
  355. goto close;
  356. }
  357. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  358. UT_REGISTERS_NB + 1, tab_rp_registers);
  359. printf("* modbus_read_registers: ");
  360. if (rc == -1 && errno == EMBXILADD)
  361. printf("OK\n");
  362. else {
  363. printf("FAILED\n");
  364. goto close;
  365. }
  366. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  367. UT_INPUT_REGISTERS_NB + 1,
  368. tab_rp_registers);
  369. printf("* modbus_read_input_registers: ");
  370. if (rc == -1 && errno == EMBXILADD)
  371. printf("OK\n");
  372. else {
  373. printf("FAILED\n");
  374. goto close;
  375. }
  376. rc = modbus_write_bit(ctx, UT_BITS_ADDRESS + UT_BITS_NB, ON);
  377. printf("* modbus_write_bit: ");
  378. if (rc == -1 && errno == EMBXILADD) {
  379. printf("OK\n");
  380. } else {
  381. printf("FAILED\n");
  382. goto close;
  383. }
  384. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS + UT_BITS_NB,
  385. UT_BITS_NB, tab_rp_bits);
  386. printf("* modbus_write_coils: ");
  387. if (rc == -1 && errno == EMBXILADD) {
  388. printf("OK\n");
  389. } else {
  390. printf("FAILED\n");
  391. goto close;
  392. }
  393. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
  394. UT_REGISTERS_NB, tab_rp_registers);
  395. printf("* modbus_write_registers: ");
  396. if (rc == -1 && errno == EMBXILADD) {
  397. printf("OK\n");
  398. } else {
  399. printf("FAILED\n");
  400. goto close;
  401. }
  402. /** TOO MANY DATA **/
  403. printf("\nTEST TOO MANY DATA ERROR:\n");
  404. rc = modbus_read_bits(ctx, UT_BITS_ADDRESS,
  405. MODBUS_MAX_READ_BITS + 1, tab_rp_bits);
  406. printf("* modbus_read_bits: ");
  407. if (rc == -1 && errno == EMBMDATA) {
  408. printf("OK\n");
  409. } else {
  410. printf("FAILED\n");
  411. goto close;
  412. }
  413. rc = modbus_read_input_bits(ctx, UT_INPUT_BITS_ADDRESS,
  414. MODBUS_MAX_READ_BITS + 1, tab_rp_bits);
  415. printf("* modbus_read_input_bits: ");
  416. if (rc == -1 && errno == EMBMDATA) {
  417. printf("OK\n");
  418. } else {
  419. printf("FAILED\n");
  420. goto close;
  421. }
  422. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  423. MODBUS_MAX_READ_REGISTERS + 1,
  424. tab_rp_registers);
  425. printf("* modbus_read_registers: ");
  426. if (rc == -1 && errno == EMBMDATA) {
  427. printf("OK\n");
  428. } else {
  429. printf("FAILED\n");
  430. goto close;
  431. }
  432. rc = modbus_read_input_registers(ctx, UT_INPUT_REGISTERS_ADDRESS,
  433. MODBUS_MAX_READ_REGISTERS + 1,
  434. tab_rp_registers);
  435. printf("* modbus_read_input_registers: ");
  436. if (rc == -1 && errno == EMBMDATA) {
  437. printf("OK\n");
  438. } else {
  439. printf("FAILED\n");
  440. goto close;
  441. }
  442. rc = modbus_write_bits(ctx, UT_BITS_ADDRESS,
  443. MODBUS_MAX_WRITE_BITS + 1, tab_rp_bits);
  444. printf("* modbus_write_bits: ");
  445. if (rc == -1 && errno == EMBMDATA) {
  446. printf("OK\n");
  447. } else {
  448. goto close;
  449. printf("FAILED\n");
  450. }
  451. rc = modbus_write_registers(ctx, UT_REGISTERS_ADDRESS,
  452. MODBUS_MAX_WRITE_REGISTERS + 1,
  453. tab_rp_registers);
  454. printf("* modbus_write_registers: ");
  455. if (rc == -1 && errno == EMBMDATA) {
  456. printf("OK\n");
  457. } else {
  458. printf("FAILED\n");
  459. goto close;
  460. }
  461. /** SLAVE REPLY **/
  462. printf("\nTEST SLAVE REPLY:\n");
  463. modbus_set_slave(ctx, INVALID_SERVER_ID);
  464. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  465. UT_REGISTERS_NB, tab_rp_registers);
  466. if (use_backend == RTU) {
  467. const int RAW_REQ_LENGTH = 6;
  468. uint8_t raw_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0x01, 0x01 };
  469. /* Too many points */
  470. uint8_t raw_invalid_req[] = { INVALID_SERVER_ID, 0x03, 0x00, 0x01, 0xFF, 0xFF };
  471. const int RAW_REP_LENGTH = 7;
  472. uint8_t raw_rep[] = { INVALID_SERVER_ID, 0x03, 0x04, 0, 0, 0, 0 };
  473. uint8_t rsp[MODBUS_RTU_MAX_ADU_LENGTH];
  474. /* No response in RTU mode */
  475. printf("1/5-A No response from slave %d: ", INVALID_SERVER_ID);
  476. if (rc == -1 && errno == ETIMEDOUT) {
  477. printf("OK\n");
  478. } else {
  479. printf("FAILED\n");
  480. goto close;
  481. }
  482. /* The slave raises a timeout on a confirmation to ignore because if an
  483. * indication for another slave is received, a confirmation must follow */
  484. /* Send a pair of indication/confirmation to the slave with a different
  485. * slave ID to simulate a communication on a RS485 bus. At first, the
  486. * slave will see the indication message then the confirmation, and it must
  487. * ignore both. */
  488. modbus_send_raw_request(ctx, raw_req, RAW_REQ_LENGTH * sizeof(uint8_t));
  489. modbus_send_raw_request(ctx, raw_rep, RAW_REP_LENGTH * sizeof(uint8_t));
  490. rc = modbus_receive_confirmation(ctx, rsp);
  491. printf("1/5-B No response from slave %d on indication/confirmation messages: ",
  492. INVALID_SERVER_ID);
  493. if (rc == -1 && errno == ETIMEDOUT) {
  494. printf("OK\n");
  495. } else {
  496. printf("FAILED (%d)\n", rc);
  497. goto close;
  498. }
  499. /* Send an INVALID request for another slave */
  500. modbus_send_raw_request(ctx, raw_invalid_req, RAW_REQ_LENGTH * sizeof(uint8_t));
  501. rc = modbus_receive_confirmation(ctx, rsp);
  502. printf("1/5-C No response from slave %d with invalid request: ",
  503. INVALID_SERVER_ID);
  504. if (rc == -1 && errno == ETIMEDOUT) {
  505. printf("OK\n");
  506. } else {
  507. printf("FAILED (%d)\n", rc);
  508. goto close;
  509. }
  510. } else {
  511. /* Response in TCP mode */
  512. printf("1/4 Response from slave %d: ", INVALID_SERVER_ID);
  513. if (rc == UT_REGISTERS_NB) {
  514. printf("OK\n");
  515. } else {
  516. printf("FAILED\n");
  517. goto close;
  518. }
  519. }
  520. rc = modbus_set_slave(ctx, MODBUS_BROADCAST_ADDRESS);
  521. if (rc == -1) {
  522. printf("Invalid broacast address\n");
  523. goto close;
  524. }
  525. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  526. UT_REGISTERS_NB, tab_rp_registers);
  527. printf("2/5 Reply after a broadcast query: ");
  528. if (rc == UT_REGISTERS_NB) {
  529. printf("OK\n");
  530. } else {
  531. printf("FAILED\n");
  532. goto close;
  533. }
  534. /* Restore slave */
  535. if (use_backend == RTU) {
  536. modbus_set_slave(ctx, SERVER_ID);
  537. } else {
  538. modbus_set_slave(ctx, MODBUS_TCP_SLAVE);
  539. }
  540. printf("3/5 Report slave ID: \n");
  541. /* tab_rp_bits is used to store bytes */
  542. rc = modbus_report_slave_id(ctx, tab_rp_bits);
  543. if (rc == -1) {
  544. printf("FAILED\n");
  545. goto close;
  546. }
  547. /* Slave ID is an arbitraty number for libmodbus */
  548. if (rc > 0) {
  549. printf("OK Slave ID is %d\n", tab_rp_bits[0]);
  550. } else {
  551. printf("FAILED\n");
  552. goto close;
  553. }
  554. /* Run status indicator */
  555. if (rc > 1 && tab_rp_bits[1] == 0xFF) {
  556. printf("OK Run Status Indicator is %s\n", tab_rp_bits[1] ? "ON" : "OFF");
  557. } else {
  558. printf("FAILED\n");
  559. goto close;
  560. }
  561. /* Print additional data as string */
  562. if (rc > 2) {
  563. printf("Additional data: ");
  564. for (i=2; i < rc; i++) {
  565. printf("%c", tab_rp_bits[i]);
  566. }
  567. printf("\n");
  568. }
  569. printf("5/5 Response with an invalid TID or slave: ");
  570. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE,
  571. 1, tab_rp_registers);
  572. if (rc == -1) {
  573. printf("OK\n");
  574. } else {
  575. printf("FAILED\n");
  576. goto close;
  577. }
  578. /* Save original timeout */
  579. modbus_get_response_timeout(ctx, &old_response_to_sec, &old_response_to_usec);
  580. modbus_get_byte_timeout(ctx, &old_byte_to_sec, &old_byte_to_usec);
  581. rc = modbus_set_response_timeout(ctx, 0, 0);
  582. printf("1/6 Invalid response timeout (zero): ");
  583. if (rc == -1 && errno == EINVAL) {
  584. printf("OK\n");
  585. } else {
  586. printf("FAILED\n");
  587. goto close;
  588. }
  589. rc = modbus_set_response_timeout(ctx, 0, 1000000);
  590. printf("2/6 Invalid response timeout (too large us): ");
  591. if (rc == -1 && errno == EINVAL) {
  592. printf("OK\n");
  593. } else {
  594. printf("FAILED\n");
  595. goto close;
  596. }
  597. rc = modbus_set_byte_timeout(ctx, 0, 1000000);
  598. printf("3/6 Invalid byte timeout (too large us): ");
  599. if (rc == -1 && errno == EINVAL) {
  600. printf("OK\n");
  601. } else {
  602. printf("FAILED\n");
  603. goto close;
  604. }
  605. modbus_set_response_timeout(ctx, 0, 1);
  606. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  607. UT_REGISTERS_NB, tab_rp_registers);
  608. printf("4/6 1us response timeout: ");
  609. if (rc == -1 && errno == ETIMEDOUT) {
  610. printf("OK\n");
  611. } else {
  612. printf("FAILED (can fail on some platforms)\n");
  613. }
  614. /* A wait and flush operation is done by the error recovery code of
  615. * libmodbus but after a sleep of current response timeout
  616. * so 0 can't be too short!
  617. */
  618. usleep(old_response_to_sec * 1000000 + old_response_to_usec);
  619. modbus_flush(ctx);
  620. /* Trigger a special behaviour on server to wait for 0.5 second before
  621. * replying whereas allowed timeout is 0.2 second */
  622. modbus_set_response_timeout(ctx, 0, 200000);
  623. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SLEEP_500_MS,
  624. 1, tab_rp_registers);
  625. printf("5/6 Too short response timeout (0.2s < 0.5s): ");
  626. if (rc == -1 && errno == ETIMEDOUT) {
  627. printf("OK\n");
  628. } else {
  629. printf("FAILED\n");
  630. goto close;
  631. }
  632. /* Wait for reply (0.2 + 0.4 > 0.5 s) and flush before continue */
  633. usleep(400000);
  634. modbus_flush(ctx);
  635. modbus_set_response_timeout(ctx, 0, 600000);
  636. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SLEEP_500_MS,
  637. 1, tab_rp_registers);
  638. printf("6/6 Adequate response timeout (0.6s > 0.5s): ");
  639. if (rc == 1) {
  640. printf("OK\n");
  641. } else {
  642. printf("FAILED\n");
  643. goto close;
  644. }
  645. /* Disable the byte timeout.
  646. The full response must be available in the 600ms interval */
  647. modbus_set_byte_timeout(ctx, 0, 0);
  648. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SLEEP_500_MS,
  649. 1, tab_rp_registers);
  650. printf("7/7 Disable byte timeout: ");
  651. if (rc == 1) {
  652. printf("OK\n");
  653. } else {
  654. printf("FAILED\n");
  655. goto close;
  656. }
  657. /* Restore original response timeout */
  658. modbus_set_response_timeout(ctx, old_response_to_sec,
  659. old_response_to_usec);
  660. if (use_backend == TCP) {
  661. /* Test server is only able to test byte timeout with the TCP backend */
  662. /* Timeout of 3ms between bytes */
  663. modbus_set_byte_timeout(ctx, 0, 3000);
  664. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS,
  665. 1, tab_rp_registers);
  666. printf("1/2 Too small byte timeout (3ms < 5ms): ");
  667. if (rc == -1 && errno == ETIMEDOUT) {
  668. printf("OK\n");
  669. } else {
  670. printf("FAILED\n");
  671. goto close;
  672. }
  673. /* Wait remaing bytes before flushing */
  674. usleep(11 * 5000);
  675. modbus_flush(ctx);
  676. /* Timeout of 10ms between bytes */
  677. modbus_set_byte_timeout(ctx, 0, 7000);
  678. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS,
  679. 1, tab_rp_registers);
  680. printf("2/2 Adapted byte timeout (7ms > 5ms): ");
  681. if (rc == 1) {
  682. printf("OK\n");
  683. } else {
  684. printf("FAILED\n");
  685. goto close;
  686. }
  687. }
  688. /* Restore original byte timeout */
  689. modbus_set_byte_timeout(ctx, old_byte_to_sec, old_byte_to_usec);
  690. /** BAD RESPONSE **/
  691. printf("\nTEST BAD RESPONSE ERROR:\n");
  692. /* Allocate only the required space */
  693. tab_rp_registers_bad = (uint16_t *) malloc(
  694. UT_REGISTERS_NB_SPECIAL * sizeof(uint16_t));
  695. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS,
  696. UT_REGISTERS_NB_SPECIAL, tab_rp_registers_bad);
  697. printf("* modbus_read_registers: ");
  698. if (rc == -1 && errno == EMBBADDATA) {
  699. printf("OK\n");
  700. } else {
  701. printf("FAILED\n");
  702. goto close;
  703. }
  704. free(tab_rp_registers_bad);
  705. /** MANUAL EXCEPTION **/
  706. printf("\nTEST MANUAL EXCEPTION:\n");
  707. rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS_SPECIAL,
  708. UT_REGISTERS_NB, tab_rp_registers);
  709. printf("* modbus_read_registers at special address: ");
  710. if (rc == -1 && errno == EMBXSBUSY) {
  711. printf("OK\n");
  712. } else {
  713. printf("FAILED\n");
  714. goto close;
  715. }
  716. /** RAW REQUEST */
  717. if (test_raw_request(ctx, use_backend) == -1) {
  718. goto close;
  719. }
  720. printf("\nALL TESTS PASS WITH SUCCESS.\n");
  721. close:
  722. /* Free the memory */
  723. free(tab_rp_bits);
  724. free(tab_rp_registers);
  725. /* Close the connection */
  726. modbus_close(ctx);
  727. modbus_free(ctx);
  728. return 0;
  729. }
  730. int test_raw_request(modbus_t *ctx, int use_backend)
  731. {
  732. int rc;
  733. int i, j;
  734. const int RAW_REQ_LENGTH = 6;
  735. uint8_t raw_req[] = {
  736. /* slave */
  737. (use_backend == RTU) ? SERVER_ID : 0xFF,
  738. /* function, addr 1, 5 values */
  739. MODBUS_FC_READ_HOLDING_REGISTERS, 0x00, 0x01, 0x0, 0x05,
  740. };
  741. /* Write and read registers request */
  742. uint8_t raw_rw_req[] = {
  743. /* slave */
  744. (use_backend == RTU) ? SERVER_ID : 0xFF,
  745. /* function, addr to read, nb to read */
  746. MODBUS_FC_WRITE_AND_READ_REGISTERS,
  747. /* Read */
  748. 0, 0,
  749. (MODBUS_MAX_WR_READ_REGISTERS + 1) >> 8,
  750. (MODBUS_MAX_WR_READ_REGISTERS + 1) & 0xFF,
  751. /* Write */
  752. 0, 0,
  753. 0, 1,
  754. /* Write byte count */
  755. 1 * 2,
  756. /* One data to write... */
  757. 0x12, 0x34
  758. };
  759. /* See issue #143, test with MAX_WR_WRITE_REGISTERS */
  760. int req_length;
  761. uint8_t rsp[MODBUS_TCP_MAX_ADU_LENGTH];
  762. int tab_function[] = {
  763. MODBUS_FC_READ_COILS,
  764. MODBUS_FC_READ_DISCRETE_INPUTS,
  765. MODBUS_FC_READ_HOLDING_REGISTERS,
  766. MODBUS_FC_READ_INPUT_REGISTERS
  767. };
  768. int tab_nb_max[] = {
  769. MODBUS_MAX_READ_BITS + 1,
  770. MODBUS_MAX_READ_BITS + 1,
  771. MODBUS_MAX_READ_REGISTERS + 1,
  772. MODBUS_MAX_READ_REGISTERS + 1
  773. };
  774. int length;
  775. int offset;
  776. const int EXCEPTION_RC = 2;
  777. if (use_backend == RTU) {
  778. length = 3;
  779. offset = 1;
  780. } else {
  781. length = 7;
  782. offset = 7;
  783. }
  784. printf("\nTEST RAW REQUESTS:\n");
  785. req_length = modbus_send_raw_request(ctx, raw_req,
  786. RAW_REQ_LENGTH * sizeof(uint8_t));
  787. printf("* modbus_send_raw_request: ");
  788. if (req_length == (length + 5)) {
  789. printf("OK\n");
  790. } else {
  791. printf("FAILED (%d)\n", req_length);
  792. return -1;
  793. }
  794. printf("* modbus_receive_confirmation: ");
  795. rc = modbus_receive_confirmation(ctx, rsp);
  796. if (rc == (length + 12)) {
  797. printf("OK\n");
  798. } else {
  799. printf("FAILED (%d)\n", rc);
  800. return -1;
  801. }
  802. /* Try to crash server with raw requests to bypass checks of client. */
  803. /* Address */
  804. raw_req[2] = 0;
  805. raw_req[3] = 0;
  806. /* Try to read more values than a response could hold for all data
  807. * types.
  808. */
  809. for (i=0; i<4; i++) {
  810. raw_req[1] = tab_function[i];
  811. for (j=0; j<2; j++) {
  812. if (j == 0) {
  813. /* Try to read zero values on first iteration */
  814. raw_req[4] = 0x00;
  815. raw_req[5] = 0x00;
  816. } else {
  817. /* Try to read max values + 1 on second iteration */
  818. raw_req[4] = (tab_nb_max[i] >> 8) & 0xFF;
  819. raw_req[5] = tab_nb_max[i] & 0xFF;
  820. }
  821. req_length = modbus_send_raw_request(ctx, raw_req,
  822. RAW_REQ_LENGTH * sizeof(uint8_t));
  823. if (j == 0) {
  824. printf("* try to read 0 values with function %d: ", tab_function[i]);
  825. } else {
  826. printf("* try an exploit with function %d: ", tab_function[i]);
  827. }
  828. rc = modbus_receive_confirmation(ctx, rsp);
  829. if (rc == (length + EXCEPTION_RC) &&
  830. rsp[offset] == (0x80 + tab_function[i]) &&
  831. rsp[offset + 1] == MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE) {
  832. printf("OK\n");
  833. } else {
  834. printf("FAILED\n");
  835. return -1;
  836. }
  837. }
  838. }
  839. /* Modbus write and read multiple registers */
  840. i = 0;
  841. tab_function[i] = MODBUS_FC_WRITE_AND_READ_REGISTERS;
  842. for (j=0; j<2; j++) {
  843. if (j == 0) {
  844. /* Try to read zero values on first iteration */
  845. raw_rw_req[4] = 0x00;
  846. raw_rw_req[5] = 0x00;
  847. } else {
  848. /* Try to read max values + 1 on second iteration */
  849. raw_rw_req[4] = (MODBUS_MAX_WR_READ_REGISTERS + 1) >> 8;
  850. raw_rw_req[5] = (MODBUS_MAX_WR_READ_REGISTERS + 1) & 0xFF;
  851. }
  852. req_length = modbus_send_raw_request(ctx, raw_rw_req, 13 * sizeof(uint8_t));
  853. if (j == 0) {
  854. printf("* try to read 0 values with function %d: ", tab_function[i]);
  855. } else {
  856. printf("* try an exploit with function %d: ", tab_function[i]);
  857. }
  858. rc = modbus_receive_confirmation(ctx, rsp);
  859. if (rc == length + EXCEPTION_RC &&
  860. rsp[offset] == (0x80 + tab_function[i]) &&
  861. rsp[offset + 1] == MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE) {
  862. printf("OK\n");
  863. } else {
  864. printf("FAILED\n");
  865. return -1;
  866. }
  867. }
  868. return 0;
  869. }