unit-test-client.c 30 KB

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