summaryrefslogtreecommitdiff
path: root/driver_aivdm.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2010-02-01 23:29:44 +0000
committerEric S. Raymond <esr@thyrsus.com>2010-02-01 23:29:44 +0000
commit0581665f9eef5ce929d64198c4f1c0f967001d22 (patch)
tree45a83c0601a6bb6a49d5bdde82106f058af84866 /driver_aivdm.c
parent702cf714ecf48b6496223974a9eb0502128cfdee (diff)
downloadgpsd-0581665f9eef5ce929d64198c4f1c0f967001d22.tar.gz
Add packet length checks to the C decoder
And the -m option to the Python decoder.
Diffstat (limited to 'driver_aivdm.c')
-rw-r--r--driver_aivdm.c116
1 files changed, 112 insertions, 4 deletions
diff --git a/driver_aivdm.c b/driver_aivdm.c
index ad8e906f..d1aac545 100644
--- a/driver_aivdm.c
+++ b/driver_aivdm.c
@@ -158,6 +158,12 @@ bool aivdm_decode(const char *buf, size_t buflen,
case 1: /* Position Report */
case 2:
case 3:
+ if (ais_context->bitlen != 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type %d size not 168 bits (%zd).\n",
+ ais->type,
+ ais_context->bitlen);
+ break;
+ }
ais->type1.status = UBITS(38, 4);
ais->type1.turn = SBITS(42, 8);
ais->type1.speed = UBITS(50, 10);
@@ -186,7 +192,8 @@ bool aivdm_decode(const char *buf, size_t buflen,
case 4: /* Base Station Report */
case 11: /* UTC/Date Response */
if (ais_context->bitlen != 168) {
- gpsd_report(LOG_ERROR, "AIVDM message type 4 size not 168 bits (%zd).\n",
+ gpsd_report(LOG_WARN, "AIVDM message type %d size not 168 bits (%zd).\n",
+ ais->type,
ais_context->bitlen);
break;
}
@@ -217,6 +224,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type4.epfd);
break;
case 5: /* Ship static and voyage related data */
+ if (ais_context->bitlen != 424) {
+ gpsd_report(LOG_WARN, "AIVDM message type 5 size not 424 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type5.ais_version = UBITS(38, 2);
ais->type5.imo = UBITS(40, 30);
UCHARS(70, ais->type5.callsign);
@@ -243,6 +255,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type5.destination);
break;
case 6: /* Addressed Binary Message */
+ if (ais_context->bitlen < 88 || ais_context->bitlen > 1008) {
+ gpsd_report(LOG_WARN, "AIVDM message type 6 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type6.seqno = UBITS(38, 2);
ais->type6.dest_mmsi = UBITS(40, 30);
ais->type6.retransmit = (bool)UBITS(70, 1);
@@ -262,6 +279,12 @@ bool aivdm_decode(const char *buf, size_t buflen,
case 13: /* Safety Related Acknowledge */
{
unsigned int mmsi[4];
+ if (ais_context->bitlen < 72 || ais_context->bitlen > 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type %d size is out of range (%zd).\n",
+ ais->type,
+ ais_context->bitlen);
+ break;
+ }
for (i = 0; i < sizeof(mmsi)/sizeof(mmsi[0]); i++)
if (ais_context->bitlen > 40 + 32*i)
mmsi[i] = UBITS(40 + 32*i, 30);
@@ -277,6 +300,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
break;
}
case 8: /* Binary Broadcast Message */
+ if (ais_context->bitlen < 56 || ais_context->bitlen > 1008) {
+ gpsd_report(LOG_WARN, "AIVDM message type 8 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
//ais->type8.spare = UBITS(38, 2);
ais->type8.app_id = UBITS(40, 16);
ais->type8.bitcount = ais_context->bitlen - 56;
@@ -288,6 +316,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type8.bitcount);
break;
case 9: /* Standard SAR Aircraft Position Report */
+ if (ais_context->bitlen != 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type 9 size not 168 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type9.alt = UBITS(38, 12);
ais->type9.speed = UBITS(50, 10);
ais->type9.accuracy = (bool)UBITS(60, 1);
@@ -312,12 +345,22 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type9.second);
break;
case 10: /* UTC/Date inquiry */
+ if (ais_context->bitlen != 72) {
+ gpsd_report(LOG_WARN, "AIVDM message type 10 size not 72 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
//ais->type10.spare = UBITS(38, 2);
ais->type10.dest_mmsi = UBITS(40, 30);
//ais->type10.spare2 = UBITS(70, 2);
gpsd_report(LOG_INF, "dest=%u\n", ais->type10.dest_mmsi);
break;
case 12: /* Safety Related Message */
+ if (ais_context->bitlen < 72 || ais_context->bitlen > 1008) {
+ gpsd_report(LOG_WARN, "AIVDM message type 12 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type12.seqno = UBITS(38, 2);
ais->type12.dest_mmsi = UBITS(40, 30);
ais->type12.retransmit = (bool)UBITS(70, 1);
@@ -330,6 +373,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type12.dest_mmsi);
break;
case 14: /* Safety Related Broadcast Message */
+ if (ais_context->bitlen < 40 || ais_context->bitlen > 1008) {
+ gpsd_report(LOG_WARN, "AIVDM message type 14 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
//ais->type14.spare = UBITS(38, 2);
from_sixbit((char *)ais_context->bits,
40, ais_context->bitlen-40,
@@ -337,6 +385,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
gpsd_report(LOG_INF, "\n");
break;
case 15: /* Interrogation */
+ if (ais_context->bitlen < 88 || ais_context->bitlen > 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type 15 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
(void)memset(&ais->type15, '\0', sizeof(ais->type15));
//ais->type14.spare = UBITS(38, 2);
ais->type15.mmsi1 = UBITS(40, 30);
@@ -357,6 +410,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
gpsd_report(LOG_INF, "\n");
break;
case 16: /* Assigned Mode Command */
+ if (ais_context->bitlen != 96 && ais_context->bitlen != 144) {
+ gpsd_report(LOG_WARN, "AIVDM message type 16 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type16.mmsi1 = UBITS(40, 30);
ais->type16.offset1 = UBITS(70, 12);
ais->type16.increment1 = UBITS(82, 10);
@@ -370,6 +428,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
gpsd_report(LOG_INF, "\n");
break;
case 17: /* GNSS Broadcast Binary Message */
+ if (ais_context->bitlen < 80 || ais_context->bitlen > 816) {
+ gpsd_report(LOG_WARN, "AIVDM message type 17 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
//ais->type17.spare = UBITS(38, 2);
ais->type17.lon = UBITS(40, 18);
ais->type17.lat = UBITS(58, 17);
@@ -380,6 +443,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
gpsd_report(LOG_INF, "\n");
break;
case 18: /* Standard Class B CS Position Report */
+ if (ais_context->bitlen != 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type 18 size not 168 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type18.reserved = UBITS(38, 8);
ais->type18.speed = UBITS(46, 10);
ais->type18.accuracy = UBITS(56, 1)!=0;
@@ -409,6 +477,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type18.second);
break;
case 19: /* Extended Class B CS Position Report */
+ if (ais_context->bitlen != 312) {
+ gpsd_report(LOG_WARN, "AIVDM message type 19 size not 312 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type19.reserved = UBITS(38, 8);
ais->type19.speed = UBITS(46, 10);
ais->type19.accuracy = UBITS(56, 1)!=0;
@@ -442,6 +515,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type19.shipname);
break;
case 20: /* Data Link Management Message */
+ if (ais_context->bitlen < 72 || ais_context->bitlen > 160) {
+ gpsd_report(LOG_WARN, "AIVDM message type 20 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
//ais->type20.spare = UBITS(38, 2);
ais->type20.offset1 = UBITS(40, 12);
ais->type20.number1 = UBITS(52, 4);
@@ -461,6 +539,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type20.increment4 = UBITS(149, 11);
break;
case 21: /* Aid-to-Navigation Report */
+ if (ais_context->bitlen < 272 || ais_context->bitlen > 360) {
+ gpsd_report(LOG_WARN, "AIVDM message type 21 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type21.aid_type = UBITS(38, 5);
from_sixbit((char *)ais_context->bits,
43, 21, ais->type21.name);
@@ -492,6 +575,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type19.second);
break;
case 22: /* Channel Management */
+ if (ais_context->bitlen != 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type 22 size not 168 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type22.channel_a = UBITS(40, 12);
ais->type22.channel_b = UBITS(52, 12);
ais->type22.txrx = UBITS(64, 4);
@@ -511,6 +599,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type22.zonesize = UBITS(142, 3);
break;
case 23: /* Group Assignment Command */
+ if (ais_context->bitlen != 160) {
+ gpsd_report(LOG_WARN, "AIVDM message type 23 size not 160 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type23.ne_lon = SBITS(40, 18);
ais->type23.ne_lat = SBITS(58, 17);
ais->type23.sw_lon = SBITS(75, 18);
@@ -524,10 +617,20 @@ bool aivdm_decode(const char *buf, size_t buflen,
case 24: /* Class B CS Static Data Report */
switch (UBITS(38, 2)) {
case 0:
+ if (ais_context->bitlen != 160) {
+ gpsd_report(LOG_WARN, "AIVDM message type 24A size not 160 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
UCHARS(40, ais_context->shipname);
//ais->type24.a.spare = UBITS(160, 8);
return false; /* data only partially decoded */
case 1:
+ if (ais_context->bitlen != 168) {
+ gpsd_report(LOG_WARN, "AIVDM message type 24B size not 168 bits (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
(void)strlcpy(ais->type24.shipname,
ais_context->shipname,
sizeof(ais_context->shipname));
@@ -550,14 +653,14 @@ bool aivdm_decode(const char *buf, size_t buflen,
case 25: /* Binary Message, Single Slot */
/* this check and the following one reject line noise */
if (ais_context->bitlen < 40 || ais_context->bitlen > 168) {
- gpsd_report(LOG_ERROR, "AIVDM message type 25 size not between 40 to 168 bits (%zd).\n",
+ gpsd_report(LOG_WARN, "AIVDM message type 25 size not between 40 to 168 bits (%zd).\n",
ais_context->bitlen);
break;
}
ais->type25.addressed = (bool)UBITS(38, 1);
ais->type25.structured = (bool)UBITS(39, 1);
- if (ais_context->bitlen < ( 40 + (16*ais->type25.structured) + (30*ais->type25.addressed) ) ) {
- gpsd_report(LOG_ERROR, "AIVDM message type 25 too short for mode.\n");
+ if (ais_context->bitlen < (40 + (16*ais->type25.structured) + (30*ais->type25.addressed))) {
+ gpsd_report(LOG_WARN, "AIVDM message type 25 too short for mode.\n");
break;
}
if (ais->type25.addressed)
@@ -585,6 +688,11 @@ bool aivdm_decode(const char *buf, size_t buflen,
ais->type25.bitcount);
break;
case 26: /* Binary Message, Multiple Slot */
+ if (ais_context->bitlen < 60 || ais_context->bitlen > 1004) {
+ gpsd_report(LOG_WARN, "AIVDM message type 26 size is out of range (%zd).\n",
+ ais_context->bitlen);
+ break;
+ }
ais->type26.addressed = (bool)UBITS(38, 1);
ais->type26.structured = (bool)UBITS(39, 1);
if (ais->type26.addressed)