Skip to content

Commit 2506ccb

Browse files
committed
Do not return or modify values that do not exist
1 parent 4d885db commit 2506ccb

File tree

1 file changed

+99
-74
lines changed

1 file changed

+99
-74
lines changed

src/Modbus.cpp

Lines changed: 99 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,6 @@ bool Modbus::regOutOfBounds (word address, word value) {
124124
return false;
125125
}
126126

127-
//-------------------------------------------------------------------------------
128-
int Modbus::setAdditionalServerData (const char data[]) {
129-
130-
free (_additional_data);
131-
if (data) {
132-
size_t l = strlen (data) + 1;
133-
134-
_additional_data = (char *) malloc (l);
135-
if (_additional_data) {
136-
137-
strcpy (_additional_data, data);
138-
return l;
139-
}
140-
}
141-
return 0;
142-
}
143-
144127
//-------------------------------------------------------------------------------
145128
// protected
146129
void Modbus::receivePDU (byte *frame) {
@@ -204,6 +187,7 @@ void Modbus::receivePDU (byte *frame) {
204187
}
205188

206189
//-------------------------------------------------------------------------------
190+
// private
207191
void Modbus::exceptionResponse (byte fcode, byte excode) {
208192
//Clean frame buffer
209193
free (_frame);
@@ -215,6 +199,40 @@ void Modbus::exceptionResponse (byte fcode, byte excode) {
215199
_reply = MB_REPLY_NORMAL;
216200
}
217201

202+
/* Func 06: Write Single Register
203+
Request
204+
Function code 1 Byte 0x06
205+
Register Address 2 Bytes 0x0000 to 0xFFFF
206+
Register Value 2 Bytes 0x0000 to 0xFFFF
207+
Response
208+
Function code 1 Byte 0x06
209+
Register Address 2 Bytes 0x0000 to 0xFFFF
210+
Register Value 2 Bytes 0x0000 to 0xFFFF
211+
*/
212+
//-------------------------------------------------------------------------------
213+
// private
214+
void Modbus::writeSingleRegister (word reg, word value) {
215+
216+
if (hregOutOfBounds (reg, value)) {
217+
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
218+
return;
219+
}
220+
221+
//Check Address and execute (reg exists?)
222+
if (!setHreg (reg, value)) {
223+
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS);
224+
return;
225+
}
226+
227+
//Check for failure ? Why ???
228+
/*
229+
if (hreg (reg) != value) {
230+
exceptionResponse (MB_FC_WRITE_REG, MB_EX_SLAVE_FAILURE);
231+
return;
232+
}
233+
*/
234+
_reply = MB_REPLY_ECHO; // reply with received frame
235+
}
218236

219237
/*
220238
Func 03: Read Holding Registers
@@ -228,21 +246,23 @@ void Modbus::exceptionResponse (byte fcode, byte excode) {
228246
Register value N* x 2 Bytes
229247
N = Quantity of Registers
230248
*/
249+
//-------------------------------------------------------------------------------
250+
// private
231251
void Modbus::readRegisters (word startreg, word numregs) {
232252
//Check value (numregs)
233253
if (numregs < 1 || numregs > 125) {
234254
exceptionResponse (MB_FC_READ_REGS, MB_EX_ILLEGAL_VALUE);
235255
return;
236256
}
237257

238-
//Check Address
239-
//*** See comments on readCoils method.
240-
if (!searchRegister (startreg + TRegister::HregOffset)) {
241-
exceptionResponse (MB_FC_READ_REGS, MB_EX_ILLEGAL_ADDRESS);
242-
return;
258+
//Check Address (startreg...startreg + numregs - 1)
259+
for (word k = 0; k < numregs; k++) {
260+
if (!searchRegister (startreg + TRegister::HregOffset + k)) {
261+
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
262+
return;
263+
}
243264
}
244265

245-
246266
//Clean frame buffer
247267
free (_frame);
248268
_len = 0;
@@ -275,39 +295,6 @@ void Modbus::readRegisters (word startreg, word numregs) {
275295
_reply = MB_REPLY_NORMAL;
276296
}
277297

278-
/* Func 06: Write Single Register
279-
Request
280-
Function code 1 Byte 0x06
281-
Register Address 2 Bytes 0x0000 to 0xFFFF
282-
Register Value 2 Bytes 0x0000 to 0xFFFF
283-
Response
284-
Function code 1 Byte 0x06
285-
Register Address 2 Bytes 0x0000 to 0xFFFF
286-
Register Value 2 Bytes 0x0000 to 0xFFFF
287-
*/
288-
void Modbus::writeSingleRegister (word reg, word value) {
289-
290-
if (hregOutOfBounds (reg, value)) {
291-
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
292-
return;
293-
}
294-
295-
//Check Address and execute (reg exists?)
296-
if (!setHreg (reg, value)) {
297-
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS);
298-
return;
299-
}
300-
301-
//Check for failure ?
302-
/*
303-
if (hreg (reg) != value) {
304-
exceptionResponse (MB_FC_WRITE_REG, MB_EX_SLAVE_FAILURE);
305-
return;
306-
}
307-
*/
308-
_reply = MB_REPLY_ECHO; // reply with received frame
309-
}
310-
311298
/* Func 16: Write Multiple registers
312299
Request
313300
Function code 1 Byte 0x10
@@ -321,14 +308,16 @@ void Modbus::writeSingleRegister (word reg, word value) {
321308
Starting Address 2 Bytes 0x0000 to 0xFFFF
322309
Quantity of Registers 2 Bytes 1 to 123 (0x7B)
323310
*/
311+
//-------------------------------------------------------------------------------
312+
// private
324313
void Modbus::writeMultipleRegisters (byte *frame, word startreg, word numoutputs, byte bytecount) {
325314
//Check value
326315
if (numoutputs < 1 || numoutputs > 123 || bytecount != 2 * numoutputs) {
327316
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_VALUE);
328317
return;
329318
}
330319

331-
//Check Address (startreg...startreg + numregs)
320+
//Check Address (startreg...startreg + numregs - 1)
332321
for (word k = 0; k < numoutputs; k++) {
333322
if (!searchRegister (startreg + TRegister::HregOffset + k)) {
334323
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
@@ -380,21 +369,26 @@ void Modbus::writeMultipleRegisters (byte *frame, word startreg, word numoutputs
380369
Coil Status n Byte n = N or N+1
381370
N = Quantity of Outputs / 8, if the remainder is different of 0 -> N = N+1
382371
*/
372+
//-------------------------------------------------------------------------------
373+
// private
383374
void Modbus::readCoils (word startreg, word numregs) {
384375
//Check value (numregs)
385376
if (numregs < 1 || numregs > 2000) {
386377
exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_VALUE);
387378
return;
388379
}
389380

390-
//Check Address
391-
//Check only startreg. Is this correct?
392381
//When I check all registers in range I got errors in ScadaBR
393382
//I think that ScadaBR request more than one in the single request
394383
//when you have more then one datapoint configured from same type.
395-
if (!searchRegister (startreg + TRegister::CoilOffset)) {
396-
exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
397-
return;
384+
// epsilonrt -> We absolutely must not return values that do not exist !!
385+
386+
//Check Address (startreg...startreg + numregs - 1)
387+
for (word k = 0; k < numregs; k++) {
388+
if (!searchRegister (startreg + TRegister::CoilOffset + k)) {
389+
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
390+
return;
391+
}
398392
}
399393

400394
//Clean frame buffer
@@ -452,18 +446,21 @@ void Modbus::readCoils (word startreg, word numregs) {
452446
N = Quantity of Inputs / 8 if the remainder is different of 0  N = N+1
453447
Error
454448
*/
449+
//-------------------------------------------------------------------------------
450+
// private
455451
void Modbus::readInputStatus (word startreg, word numregs) {
456452
//Check value (numregs)
457453
if (numregs < 0x0001 || numregs > 0x07D0) {
458454
exceptionResponse (MB_FC_READ_INPUT_STAT, MB_EX_ILLEGAL_VALUE);
459455
return;
460456
}
461457

462-
//Check Address
463-
//*** See comments on readCoils method.
464-
if (!searchRegister (startreg + TRegister::IstsOffset)) {
465-
exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
466-
return;
458+
//Check Address (startreg...startreg + numregs - 1)
459+
for (word k = 0; k < numregs; k++) {
460+
if (!searchRegister (startreg + TRegister::IstsOffset + k)) {
461+
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
462+
return;
463+
}
467464
}
468465

469466
//Clean frame buffer
@@ -520,18 +517,21 @@ void Modbus::readInputStatus (word startreg, word numregs) {
520517
Input Registers N* x 2 Bytes
521518
N = Quantity of Input Registers
522519
*/
520+
//-------------------------------------------------------------------------------
521+
// private
523522
void Modbus::readInputRegisters (word startreg, word numregs) {
524523
//Check value (numregs)
525524
if (numregs < 0x0001 || numregs > 0x007D) {
526525
exceptionResponse (MB_FC_READ_INPUT_REGS, MB_EX_ILLEGAL_VALUE);
527526
return;
528527
}
529528

530-
//Check Address
531-
//*** See comments on readCoils method.
532-
if (!searchRegister (startreg + TRegister::IregOffset)) {
533-
exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
534-
return;
529+
//Check Address (startreg...startreg + numregs - 1)
530+
for (word k = 0; k < numregs; k++) {
531+
if (!searchRegister (startreg + TRegister::IregOffset + k)) {
532+
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
533+
return;
534+
}
535535
}
536536

537537
//Clean frame buffer
@@ -576,6 +576,8 @@ void Modbus::readInputRegisters (word startreg, word numregs) {
576576
Output Address 2 Bytes 0x0000 to 0xFFFF
577577
Output Value 2 Bytes 0x0000 or 0xFF00
578578
*/
579+
//-------------------------------------------------------------------------------
580+
// private
579581
void Modbus::writeSingleCoil (word reg, word status) {
580582
//Check value (status)
581583
if (status != 0xFF00 && status != 0x0000) {
@@ -584,16 +586,18 @@ void Modbus::writeSingleCoil (word reg, word status) {
584586
}
585587

586588
//Check Address and execute (reg exists?)
587-
if (!setCoil (reg, (bool) status)) {
589+
if (!setCoil (reg, status != 0)) {
588590
exceptionResponse (MB_FC_WRITE_COIL, MB_EX_ILLEGAL_ADDRESS);
589591
return;
590592
}
591593

592-
//Check for failure
594+
//Check for failure ?? Why ?
595+
/*
593596
if (coil (reg) != (bool) status) {
594597
exceptionResponse (MB_FC_WRITE_COIL, MB_EX_SLAVE_FAILURE);
595598
return;
596599
}
600+
*/
597601

598602
_reply = MB_REPLY_ECHO; // reply with received frame
599603
}
@@ -610,6 +614,8 @@ void Modbus::writeSingleCoil (word reg, word status) {
610614
Starting Address 2 Bytes 0x0000 to 0xFFFF
611615
Quantity of Outputs 2 Bytes 0x0001 to 0x07B0
612616
*/
617+
//-------------------------------------------------------------------------------
618+
// private
613619
void Modbus::writeMultipleCoils (byte *frame, word startreg, word numoutputs, byte bytecount) {
614620
//Check value
615621
word bytecount_calc = numoutputs / 8;
@@ -673,6 +679,8 @@ void Modbus::writeMultipleCoils (byte *frame, word startreg, word numoutputs, by
673679
Run Indicator Status 1 Byte 0x00 = OFF, 0xFF = ON
674680
Additional Data
675681
*/
682+
//-------------------------------------------------------------------------------
683+
// private
676684
void Modbus::reportServerId() {
677685
//Clean frame buffer
678686
free (_frame);
@@ -695,5 +703,22 @@ void Modbus::reportServerId() {
695703
_reply = MB_REPLY_NORMAL;
696704
}
697705

706+
//-------------------------------------------------------------------------------
707+
int Modbus::setAdditionalServerData (const char data[]) {
708+
709+
free (_additional_data);
710+
if (data) {
711+
size_t l = strlen (data) + 1;
712+
713+
_additional_data = (char *) malloc (l);
714+
if (_additional_data) {
715+
716+
strcpy (_additional_data, data);
717+
return l;
718+
}
719+
}
720+
return 0;
721+
}
722+
698723
//-------------------------------------------------------------------------------
699724
#endif // USE_HOLDING_REGISTERS_ONLY not defined

0 commit comments

Comments
 (0)