unit-test-client.c 31 KB

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