unit-test-client.c 28 KB

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