Coverage Report

Created: 2026-06-10 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gpsd/gpsd-3.27.6~dev/drivers/driver_ais.c
Line
Count
Source
1
/*
2
 * Driver for AIS messages.
3
 *
4
 * See the file AIVDM.txt on the GPSD website for documentation and references.
5
 * AIVDM de-armoring is handled elsewhere; this is the binary-packet driver.
6
 *
7
 * Code for message types 1-15, 18-21, and 24 has been tested against
8
 * live data with known-good decodings. Code for message types 16-17,
9
 * 22-23, and 25-27 has not.
10
 * For the special IMO messages (types 6 and 8), only the following have been
11
 * tested against known-good decodings:
12
 *  - IMO236 met/hydro message: Type=8, DAC=1, FI=11
13
 *  - IMO289 met/hydro message: Type=8, DAC=1, FI=31
14
 *
15
 * This file is Copyright 2010 by the GPSD project
16
 * SPDX-License-Identifier: BSD-2-clause
17
 */
18
19
#include "../include/gpsd_config.h"   // must be before all includes
20
21
#include <ctype.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "../include/gpsd.h"
26
#include "../include/bits.h"
27
28
/*
29
 * Parse the data from the device
30
 */
31
32
// beginning at bitvec bit start, unpack count sixbit characters
33
static void from_sixbit_untrimmed(const struct gpsd_errout_t *errout,
34
                                  const unsigned char *bitvec,
35
                                  const size_t bitlen,
36
                                  const unsigned start,
37
                                  unsigned count, char *to,
38
                                  const size_t to_sz)
39
8.01k
{
40
8.01k
    const char sixchr[65] =
41
8.01k
        "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?";
42
8.01k
    unsigned i;
43
44
8.01k
    if (bitlen <= start) {
45
133
        GPSD_LOG(LOG_WARN, errout, "AIVDM bitlen %zu <=  start %u\n",
46
133
                 bitlen, start);
47
133
        to[0] = '\0';
48
133
        return;
49
133
    }
50
7.88k
    if (to_sz <= count) {
51
0
        count = to_sz - 1;
52
0
    }
53
54
    // six-bit to ASCII
55
61.4k
    for (i = 0; i < count; i++) {
56
58.2k
        char newchar = sixchr[ubits(bitvec, start + 6 * i, 6U, false)];
57
58
58.2k
        if ('@' == newchar) {
59
4.67k
            break;
60
4.67k
        }
61
53.5k
        to[i] = newchar;
62
53.5k
    }
63
7.88k
    to[i] = '\0';
64
7.88k
}
65
66
// trim spaces on right end
67
static void trim_spaces_on_right_end(char* to, size_t max)
68
8.01k
{
69
8.01k
    long long i;
70
71
    // pacify Coverity 498043, overflow
72
11.5k
    for (i = strnlen(to, max) - 1; i >= 0; i--) {
73
9.04k
        if (' ' == to[i] ||
74
5.50k
            '@' == to[i]) {
75
3.54k
            to[i] = '\0';
76
5.50k
        } else {
77
5.50k
            break;
78
5.50k
        }
79
9.04k
    }
80
8.01k
}
81
82
/* beginning at bitvec bit start, unpack count sixbit characters
83
 * and remove trailing spaces */
84
static void from_sixbit(const struct gpsd_errout_t *errout,
85
                        const unsigned char *bitvec, const size_t bitlen,
86
                        const unsigned start,
87
                        const unsigned count, char *to, const size_t to_sz)
88
7.75k
{
89
7.75k
       from_sixbit_untrimmed(errout, bitvec, bitlen, start, count, to, to_sz);
90
7.75k
       trim_spaces_on_right_end(to, count);
91
7.75k
}
92
93
102k
#define UBITS(s, l)     ubits(bits, s, l, false)
94
14.9k
#define SBITS(s, l)     sbits(bits, s, l, false)
95
#define UCHARS(start, to)  \
96
7.41k
    from_sixbit(errout, bits, bitlen, start, sizeof(to) - 1, to, sizeof(to))
97
98
#define ENDCHARS(start, to, to_sz)  \
99
346
    from_sixbit(errout, bits, bitlen, start, (bitlen - start) / 6, to, to_sz)
100
101
/* decode an AIS binary packet
102
 *
103
 * Return: True on success
104
 *         False on failure
105
 */
106
bool ais_binary_decode(const struct gpsd_errout_t *errout,
107
                       struct ais_t *ais,
108
                       const unsigned char *bits, size_t bitlen,
109
                       struct ais_type24_queue_t *type24_queue)
110
12.0k
{
111
12.0k
    unsigned int u;
112
113
12.0k
    ais->type = UBITS(0, 6);
114
12.0k
    ais->repeat = UBITS(6, 2);
115
12.0k
    ais->mmsi = UBITS(8, 30);
116
12.0k
    GPSD_LOG(LOG_INF, errout, "AIVDM message type %d, MMSI %09d:\n",
117
12.0k
             ais->type, ais->mmsi);
118
119
12.0k
#define PERMISSIVE_LENGTH_CHECK(correct) \
120
12.0k
        if (bitlen < correct) { \
121
668
            GPSD_LOG(LOG_ERROR, errout, \
122
668
                     "AIVDM message type %d size < %d bits (%zd).\n",   \
123
668
                     ais->type, correct, bitlen);                       \
124
668
            return false; \
125
1.77k
        } else if (bitlen > correct) { \
126
849
            GPSD_LOG(LOG_WARN, errout, \
127
849
                     "AIVDM message type %d size > %d bits (%zd).\n",   \
128
849
                     ais->type, correct, bitlen);                       \
129
849
        }
130
131
12.0k
#define RANGE_CHECK(min, max) \
132
12.0k
        if (bitlen < min || bitlen > max) { \
133
2.31k
            GPSD_LOG(LOG_ERROR, errout, \
134
2.31k
                     "AIVDM message type %d size is out of range (%zd).\n", \
135
2.31k
                     ais->type, bitlen);                                \
136
2.31k
            return false; \
137
2.31k
        }
138
139
    /*
140
     * Something about the shape of this switch statement confuses
141
     * GNU indent so badly that there is no point in trying to be
142
     * finer-grained than leaving it all alone.
143
     */
144
    // *INDENT-OFF*
145
12.0k
    switch (ais->type) {
146
286
    case 1:     // Position Report
147
286
        FALLTHROUGH
148
371
    case 2:
149
371
        FALLTHROUGH
150
464
    case 3:
151
        // per https://www.navcen.uscg.gov/ais-class-a-reports
152
        // In 2023, most of our samples are 168, but some are 163 and 204.
153
464
        RANGE_CHECK(163, 204)
154
144
        ais->type1.status       = UBITS(38, 4);
155
144
        ais->type1.turn         = SBITS(42, 8);
156
144
        ais->type1.speed        = UBITS(50, 10);
157
144
        ais->type1.accuracy     = UBITS(60, 1) != 0;
158
144
        ais->type1.lon          = SBITS(61, 28);
159
144
        ais->type1.lat          = SBITS(89, 27);
160
144
        ais->type1.course       = UBITS(116, 12);
161
144
        ais->type1.heading      = UBITS(128, 9);
162
144
        ais->type1.second       = UBITS(137, 6);
163
144
        ais->type1.maneuver     = UBITS(143, 2);
164
        // ais->type1.spare     = UBITS(145, 3);
165
144
        ais->type1.raim         = UBITS(148, 1) != 0;
166
144
        if(bitlen >= 168) {
167
77
            ais->type1.radio        = UBITS(149, 19);
168
77
        } else {
169
            // less than 168, as of 2023 we have no examples of this.
170
67
            ais->type1.radio        = UBITS(149, bitlen - 149);
171
67
        }
172
144
        break;
173
154
    case 4:     // Base Station Report
174
154
        FALLTHROUGH
175
347
    case 11:    // UTC/Date Response
176
347
        PERMISSIVE_LENGTH_CHECK(168)
177
205
        ais->type4.year         = UBITS(38, 14);
178
205
        ais->type4.month        = UBITS(52, 4);
179
205
        ais->type4.day          = UBITS(56, 5);
180
205
        ais->type4.hour         = UBITS(61, 5);
181
205
        ais->type4.minute       = UBITS(66, 6);
182
205
        ais->type4.second       = UBITS(72, 6);
183
205
        ais->type4.accuracy     = UBITS(78, 1) != 0;
184
205
        ais->type4.lon          = SBITS(79, 28);
185
205
        ais->type4.lat          = SBITS(107, 27);
186
205
        ais->type4.epfd         = UBITS(134, 4);
187
        //ais->type4.spare      = UBITS(138, 10);
188
205
        ais->type4.raim         = UBITS(148, 1) != 0;
189
205
        ais->type4.radio        = UBITS(149, 19);
190
205
        break;
191
546
    case 5: // Ship static and voyage related data
192
546
        if (424 != bitlen) {
193
483
            GPSD_LOG(LOG_WARN, errout,
194
483
                     "AIVDM message type 5 size not 424 bits (%zd).\n",
195
483
                     bitlen);
196
            /*
197
             * For unknown reasons, a lot of transmitters in the wild ship
198
             * with a length of 420 or 422.  This is a recoverable error.
199
             */
200
483
            if (420 > bitlen) {
201
148
                return false;
202
148
            }
203
483
        }
204
398
        ais->type5.ais_version  = UBITS(38, 2);
205
398
        ais->type5.imo          = UBITS(40, 30);
206
398
        UCHARS(70, ais->type5.callsign);
207
398
        UCHARS(112, ais->type5.shipname);
208
398
        ais->type5.shiptype     = UBITS(232, 8);
209
398
        ais->type5.to_bow       = UBITS(240, 9);
210
398
        ais->type5.to_stern     = UBITS(249, 9);
211
398
        ais->type5.to_port      = UBITS(258, 6);
212
398
        ais->type5.to_starboard = UBITS(264, 6);
213
398
        ais->type5.epfd         = UBITS(270, 4);
214
398
        ais->type5.month        = UBITS(274, 4);
215
398
        ais->type5.day          = UBITS(278, 5);
216
398
        ais->type5.hour         = UBITS(283, 5);
217
398
        ais->type5.minute       = UBITS(288, 6);
218
398
        ais->type5.draught      = UBITS(294, 8);
219
398
        UCHARS(302, ais->type5.destination);
220
398
        if (423 <= bitlen) {
221
261
            ais->type5.dte          = UBITS(422, 1);
222
261
        }
223
        //ais->type5.spare        = UBITS(423, 1);
224
398
        break;
225
1.97k
    case 6:   // Addressed Binary Message
226
1.97k
        RANGE_CHECK(88, 1008);
227
1.87k
        ais->type6.seqno          = UBITS(38, 2);
228
1.87k
        ais->type6.dest_mmsi      = UBITS(40, 30);
229
1.87k
        ais->type6.retransmit     = UBITS(70, 1) != 0;
230
        //ais->type6.spare        = UBITS(71, 1);
231
1.87k
        ais->type6.dac            = UBITS(72, 10);
232
1.87k
        ais->type6.fid            = UBITS(82, 6);
233
1.87k
        ais->type6.bitcount       = bitlen - 88;
234
        // not strictly required - helps stability in testing
235
1.87k
        (void)memset(ais->type6.bitdata, '\0', sizeof(ais->type6.bitdata));
236
1.87k
        ais->type6.structured = false;
237
        // Inland AIS
238
1.87k
        GPSD_LOG(LOG_PROG, errout, "AIVDM: type 6 dac %u fid %u bitlen %zu\n",
239
1.87k
                 ais->type6.dac, ais->type6.fid, bitlen);
240
1.87k
        if (200 == ais->type6.dac) {
241
502
            switch (ais->type6.fid) {
242
145
            case 21:    // ETA at lock/bridge/terminal
243
145
                if (248 != bitlen) {
244
76
                    break;
245
76
                }
246
69
                UCHARS(88, ais->type6.dac200fid21.country);
247
69
                UCHARS(100, ais->type6.dac200fid21.locode);
248
69
                UCHARS(118, ais->type6.dac200fid21.section);
249
69
                UCHARS(148, ais->type6.dac200fid21.terminal);
250
69
                UCHARS(178, ais->type6.dac200fid21.hectometre);
251
69
                ais->type6.dac200fid21.month    = UBITS(208, 4);
252
69
                ais->type6.dac200fid21.day      = UBITS(212, 5);
253
69
                ais->type6.dac200fid21.hour     = UBITS(217, 5);
254
69
                ais->type6.dac200fid21.minute   = UBITS(222, 6);
255
69
                ais->type6.dac200fid21.tugs     = UBITS(228, 3);
256
69
                ais->type6.dac200fid21.airdraught       = UBITS(231, 12);
257
                // skip 5 bits
258
69
                ais->type6.structured = true;
259
69
                break;
260
171
            case 22:    // RTA at lock/bridge/terminal
261
171
                if (232 != bitlen) {
262
68
                    break;
263
68
                }
264
103
                UCHARS(88, ais->type6.dac200fid22.country);
265
103
                UCHARS(100, ais->type6.dac200fid22.locode);
266
103
                UCHARS(118, ais->type6.dac200fid22.section);
267
103
                UCHARS(148, ais->type6.dac200fid22.terminal);
268
103
                UCHARS(178, ais->type6.dac200fid22.hectometre);
269
103
                ais->type6.dac200fid22.month    = UBITS(208, 4);
270
103
                ais->type6.dac200fid22.day      = UBITS(212, 5);
271
103
                ais->type6.dac200fid22.hour     = UBITS(217, 5);
272
103
                ais->type6.dac200fid22.minute   = UBITS(222, 6);
273
103
                ais->type6.dac200fid22.status   = UBITS(228, 2);
274
                // skip 2 bits
275
103
                ais->type6.structured = true;
276
103
                break;
277
117
            case 55:    // Number of Persons On Board
278
117
                if (168 != bitlen) {
279
67
                    break;
280
67
                }
281
50
                ais->type6.dac200fid55.crew       = UBITS(88, 8);
282
50
                ais->type6.dac200fid55.passengers = UBITS(96, 13);
283
50
                ais->type6.dac200fid55.personnel  = UBITS(109, 8);
284
                // skip 51 bits
285
50
                ais->type6.structured = true;
286
50
                break;
287
502
            }
288
1.37k
        } else if (235 == ais->type6.dac ||
289
1.31k
                   250 == ais->type6.dac) {
290
        // UK and Republic Of Ireland
291
64
            switch (ais->type6.fid) {
292
0
            case 10:    // GLA - AtoN monitoring data
293
0
                if (136 != bitlen) {
294
0
                    break;
295
0
                }
296
0
                ais->type6.dac235fid10.ana_int  = UBITS(88, 10);
297
0
                ais->type6.dac235fid10.ana_ext1 = UBITS(98, 10);
298
0
                ais->type6.dac235fid10.ana_ext2 = UBITS(108, 10);
299
0
                ais->type6.dac235fid10.racon    = UBITS(118, 2);
300
0
                ais->type6.dac235fid10.light    = UBITS(120, 2);
301
0
                ais->type6.dac235fid10.alarm    = UBITS(122, 1);
302
0
                ais->type6.dac235fid10.stat_ext = UBITS(123, 8);
303
0
                ais->type6.dac235fid10.off_pos  = UBITS(131, 1);
304
                // skip 4 bits
305
0
                ais->type6.structured = true;
306
0
                break;
307
64
            }
308
1.31k
        } else if (1 == ais->type6.dac) {
309
            // International
310
1.21k
            switch (ais->type6.fid) {
311
73
            case 12:    // IMO236 - Dangerous cargo indication
312
73
                UCHARS(88, ais->type6.dac1fid12.lastport);
313
73
                ais->type6.dac1fid12.lmonth     = UBITS(118, 4);
314
73
                ais->type6.dac1fid12.lday       = UBITS(122, 5);
315
73
                ais->type6.dac1fid12.lhour      = UBITS(127, 5);
316
73
                ais->type6.dac1fid12.lminute    = UBITS(132, 6);
317
73
                UCHARS(138, ais->type6.dac1fid12.nextport);
318
73
                ais->type6.dac1fid12.nmonth     = UBITS(168, 4);
319
73
                ais->type6.dac1fid12.nday       = UBITS(172, 5);
320
73
                ais->type6.dac1fid12.nhour      = UBITS(177, 5);
321
73
                ais->type6.dac1fid12.nminute    = UBITS(182, 6);
322
73
                UCHARS(188, ais->type6.dac1fid12.dangerous);
323
73
                UCHARS(308, ais->type6.dac1fid12.imdcat);
324
73
                ais->type6.dac1fid12.unid       = UBITS(332, 13);
325
73
                ais->type6.dac1fid12.amount     = UBITS(345, 10);
326
73
                ais->type6.dac1fid12.unit       = UBITS(355, 2);
327
                // skip 3 bits
328
73
                ais->type6.structured = true;
329
73
                break;
330
212
            case 14:    // IMO236 - Tidal Window
331
                // similar to fid 32.
332
212
                RANGE_CHECK(87, 1008);
333
212
                ais->type6.dac1fid32.month      = UBITS(88, 4);
334
212
                ais->type6.dac1fid32.day        = UBITS(92, 5);
335
1.32k
#define ARRAY_BASE 97
336
1.32k
#define ELEMENT_SIZE 93
337
212
                if ((ARRAY_BASE +
338
212
                     ELEMENT_SIZE * ROWS(ais->type6.dac1fid32.tidals)) <
339
212
                    bitlen) {
340
77
                    bitlen = ARRAY_BASE +
341
77
                             ELEMENT_SIZE * ROWS(ais->type6.dac1fid32.tidals);
342
77
                }
343
625
                for (u = 0; ARRAY_BASE + (ELEMENT_SIZE*u) <= bitlen; u++) {
344
413
                    int a = ARRAY_BASE + (ELEMENT_SIZE*u);
345
413
                    struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u];
346
413
                    tp->lat       = SBITS(a + 0, 27);
347
413
                    tp->lon       = SBITS(a + 27, 28);
348
413
                    tp->from_hour = UBITS(a + 55, 5);
349
413
                    tp->from_min  = UBITS(a + 60, 6);
350
413
                    tp->to_hour   = UBITS(a + 66, 5);
351
413
                    tp->to_min    = UBITS(a + 71, 6);
352
413
                    tp->cdir      = UBITS(a + 77, 9);
353
413
                    tp->cspeed    = UBITS(a + 86, 7);
354
413
                }
355
212
                ais->type6.dac1fid32.ntidals = u;
356
212
#undef ARRAY_BASE
357
212
#undef ELEMENT_SIZE
358
212
                ais->type6.structured = true;
359
212
                break;
360
103
            case 15:
361
                // IMO236 - Extended Ship Static and Voyage Related Data
362
103
                RANGE_CHECK(67, 1008);
363
103
                ais->type6.dac1fid15.airdraught = UBITS(56, 11);
364
103
                ais->type6.structured = true;
365
103
                break;
366
75
            case 16:    // IMO236 - Number of persons on board
367
75
                if (136 == ais->type6.bitcount) {
368
0
                    ais->type6.dac1fid16.persons = UBITS(88, 13);  // 289
369
75
                } else {
370
75
                    ais->type6.dac1fid16.persons = UBITS(55, 13);  // 236
371
75
                }
372
75
                ais->type6.structured = true;
373
75
                break;
374
68
            case 18:    // IMO289 - Clearance time to enter port
375
                // FIXME: sometimes bitlen == 168!
376
68
                ais->type6.dac1fid18.linkage    = UBITS(88, 10);
377
68
                ais->type6.dac1fid18.month      = UBITS(98, 4);
378
68
                ais->type6.dac1fid18.day        = UBITS(102, 5);
379
68
                ais->type6.dac1fid18.hour       = UBITS(107, 5);
380
68
                ais->type6.dac1fid18.minute     = UBITS(112, 6);
381
68
                UCHARS(118, ais->type6.dac1fid18.portname);
382
68
                UCHARS(238, ais->type6.dac1fid18.destination);
383
68
                ais->type6.dac1fid18.lon        = SBITS(268, 25);
384
68
                ais->type6.dac1fid18.lat        = SBITS(293, 24);
385
                // skip 43 bits
386
68
                ais->type6.structured = true;
387
68
                break;
388
68
            case 20:    // IMO289 - Berthing data - addressed
389
68
                RANGE_CHECK(360, 1008);
390
0
                ais->type6.dac1fid20.linkage      = UBITS(88, 10);
391
0
                ais->type6.dac1fid20.berth_length = UBITS(98, 9);
392
0
                ais->type6.dac1fid20.berth_depth  = UBITS(107, 8);
393
0
                ais->type6.dac1fid20.position     = UBITS(115, 3);
394
0
                ais->type6.dac1fid20.month        = UBITS(118, 4);
395
0
                ais->type6.dac1fid20.day          = UBITS(122, 5);
396
0
                ais->type6.dac1fid20.hour         = UBITS(127, 5);
397
0
                ais->type6.dac1fid20.minute       = UBITS(132, 6);
398
0
                ais->type6.dac1fid20.availability = UBITS(138, 1);
399
0
                ais->type6.dac1fid20.agent        = UBITS(139, 2);
400
0
                ais->type6.dac1fid20.fuel         = UBITS(141, 2);
401
0
                ais->type6.dac1fid20.chandler     = UBITS(143, 2);
402
0
                ais->type6.dac1fid20.stevedore    = UBITS(145, 2);
403
0
                ais->type6.dac1fid20.electrical   = UBITS(147, 2);
404
0
                ais->type6.dac1fid20.water        = UBITS(149, 2);
405
0
                ais->type6.dac1fid20.customs      = UBITS(151, 2);
406
0
                ais->type6.dac1fid20.cartage      = UBITS(153, 2);
407
0
                ais->type6.dac1fid20.crane        = UBITS(155, 2);
408
0
                ais->type6.dac1fid20.lift         = UBITS(157, 2);
409
0
                ais->type6.dac1fid20.medical      = UBITS(159, 2);
410
0
                ais->type6.dac1fid20.navrepair    = UBITS(161, 2);
411
0
                ais->type6.dac1fid20.provisions   = UBITS(163, 2);
412
0
                ais->type6.dac1fid20.shiprepair   = UBITS(165, 2);
413
0
                ais->type6.dac1fid20.surveyor     = UBITS(167, 2);
414
0
                ais->type6.dac1fid20.steam        = UBITS(169, 2);
415
0
                ais->type6.dac1fid20.tugs         = UBITS(171, 2);
416
0
                ais->type6.dac1fid20.solidwaste   = UBITS(173, 2);
417
0
                ais->type6.dac1fid20.liquidwaste  = UBITS(175, 2);
418
0
                ais->type6.dac1fid20.hazardouswaste = UBITS(177, 2);
419
0
                ais->type6.dac1fid20.ballast      = UBITS(179, 2);
420
0
                ais->type6.dac1fid20.additional   = UBITS(181, 2);
421
0
                ais->type6.dac1fid20.regional1    = UBITS(183, 2);
422
0
                ais->type6.dac1fid20.regional2    = UBITS(185, 2);
423
0
                ais->type6.dac1fid20.future1      = UBITS(187, 2);
424
0
                ais->type6.dac1fid20.future2      = UBITS(189, 2);
425
0
                UCHARS(191, ais->type6.dac1fid20.berth_name);
426
0
                ais->type6.dac1fid20.berth_lon    = SBITS(311, 25);
427
0
                ais->type6.dac1fid20.berth_lat    = SBITS(336, 24);
428
0
                ais->type6.structured = true;
429
0
                break;
430
4
            case 23:        // IMO289 - Area notice - addressed
431
4
                break;
432
174
            case 25:    // IMO289 - Dangerous cargo indication
433
174
                RANGE_CHECK(100, 1008);
434
88
                ais->type6.dac1fid25.unit       = UBITS(88, 2);
435
88
                ais->type6.dac1fid25.amount     = UBITS(90, 10);
436
88
                if ((100 + 17 * ROWS(ais->type6.dac1fid25.cargos)) < bitlen) {
437
1
                    bitlen = 100 + 17 * ROWS(ais->type6.dac1fid25.cargos);
438
1
                }
439
440
730
                for (u = 0; 100 + u * 17 < bitlen; u++) {
441
642
                    ais->type6.dac1fid25.cargos[u].code =
442
642
                        UBITS(100 + u * 17, 4);
443
642
                    ais->type6.dac1fid25.cargos[u].subtype =
444
642
                        UBITS(104 + u * 17, 13);
445
642
                }
446
88
                ais->type6.dac1fid25.ncargos = u;
447
88
                ais->type6.structured = true;
448
88
                break;
449
165
            case 28:    // IMO289 - Route info - addressed
450
165
                RANGE_CHECK(149, 1008);
451
99
                ais->type6.dac1fid28.linkage    = UBITS(88, 10);
452
99
                ais->type6.dac1fid28.sender     = UBITS(98, 3);
453
99
                ais->type6.dac1fid28.rtype      = UBITS(101, 5);
454
99
                ais->type6.dac1fid28.month      = UBITS(106, 4);
455
99
                ais->type6.dac1fid28.day        = UBITS(110, 5);
456
99
                ais->type6.dac1fid28.hour       = UBITS(115, 5);
457
99
                ais->type6.dac1fid28.minute     = UBITS(120, 6);
458
99
                ais->type6.dac1fid28.duration   = UBITS(126, 18);
459
99
                ais->type6.dac1fid28.waycount   = UBITS(144, 5);
460
2.36k
#define ARRAY_BASE 149
461
2.36k
#define ELEMENT_SIZE 55
462
99
                if ((ARRAY_BASE +
463
99
                     ELEMENT_SIZE * ROWS(ais->type6.dac1fid28.waypoints)) <
464
99
                    bitlen) {
465
0
                    bitlen = ARRAY_BASE +
466
0
                        ELEMENT_SIZE * ROWS(ais->type6.dac1fid28.waypoints);
467
0
                }
468
99
                for (u = 0;
469
2.36k
                     u < (unsigned char)ais->type6.dac1fid28.waycount; u++) {
470
2.27k
                    int a = ARRAY_BASE + (ELEMENT_SIZE*u);
471
2.27k
                    ais->type6.dac1fid28.waypoints[u].lon = SBITS(a + 0, 28);
472
2.27k
                    ais->type6.dac1fid28.waypoints[u].lat = SBITS(a + 28, 27);
473
2.27k
                }
474
99
#undef ARRAY_BASE
475
99
#undef ELEMENT_SIZE
476
99
                ais->type6.structured = true;
477
99
                break;
478
52
            case 30:    // IMO289 - Text description - addressed
479
52
                RANGE_CHECK(98, 1008);
480
52
                ais->type6.dac1fid30.linkage   = UBITS(88, 10);
481
52
                ENDCHARS(98, ais->type6.dac1fid30.text,
482
52
                         sizeof(ais->type6.dac1fid30.text));
483
52
                ais->type6.structured = true;
484
52
                break;
485
162
            case 32:    // IMO289 - Tidal Window
486
                // similar to fid 14.
487
162
                RANGE_CHECK(97, 1008);
488
95
                ais->type6.dac1fid32.month      = UBITS(88, 4);
489
95
                ais->type6.dac1fid32.day        = UBITS(92, 5);
490
683
#define ARRAY_BASE 97
491
683
#define ELEMENT_SIZE 88
492
95
                if ((ARRAY_BASE +
493
95
                     ELEMENT_SIZE * ROWS(ais->type6.dac1fid32.tidals)) <
494
95
                    bitlen) {
495
23
                    bitlen = ARRAY_BASE +
496
23
                             ELEMENT_SIZE * ROWS(ais->type6.dac1fid32.tidals);
497
23
                }
498
330
                for (u = 0; ARRAY_BASE + (ELEMENT_SIZE * u) <= bitlen; u++) {
499
235
                    unsigned a = ARRAY_BASE + (ELEMENT_SIZE * u);
500
235
                    struct tidal_t *tp = &ais->type6.dac1fid32.tidals[u];
501
502
235
                    tp->lon       = SBITS(a + 0, 25);
503
235
                    tp->lat       = SBITS(a + 25, 24);
504
235
                    tp->from_hour = UBITS(a + 49, 5);
505
235
                    tp->from_min  = UBITS(a + 54, 6);
506
235
                    tp->to_hour   = UBITS(a + 60, 5);
507
235
                    tp->to_min    = UBITS(a + 65, 6);
508
235
                    tp->cdir      = UBITS(a + 71, 9);
509
235
                    tp->cspeed    = UBITS(a + 80, 8);
510
235
                }
511
95
                ais->type6.dac1fid32.ntidals = u;
512
95
#undef ARRAY_BASE
513
95
#undef ELEMENT_SIZE
514
95
                ais->type6.structured = true;
515
95
                break;
516
1.21k
            }
517
1.21k
        }
518
1.58k
        if (!ais->type6.structured) {
519
502
            (void)memcpy(ais->type6.bitdata, bits + (88 / CHAR_BIT),
520
502
                         BITS_TO_BYTES(ais->type6.bitcount));
521
502
        }
522
1.58k
        break;
523
237
    case 7:    // Binary acknowledge
524
237
        FALLTHROUGH
525
533
    case 13:   // Safety Related Acknowledge
526
533
    {
527
533
        unsigned int mmsi[4];
528
533
        unsigned seqno[4];
529
533
        RANGE_CHECK(72, 168);
530
1.84k
        for (u = 0; u < sizeof(mmsi)/sizeof(mmsi[0]); u++) {
531
1.47k
            if (40 + 32 * u < bitlen) {
532
920
                mmsi[u] = UBITS(40 + 32 * u, 30);
533
920
                seqno[u] = UBITS(72 + 32 * u, 2);
534
920
            } else {
535
556
                mmsi[u] = 0;
536
556
                seqno[u] = 0;
537
556
            }
538
1.47k
        }
539
369
        ais->type7.mmsi1 = mmsi[0];
540
369
        ais->type7.seqno1 = seqno[0];
541
369
        ais->type7.mmsi2 = mmsi[1];
542
369
        ais->type7.seqno2 = seqno[1];
543
369
        ais->type7.mmsi3 = mmsi[2];
544
369
        ais->type7.seqno3 = seqno[2];
545
369
        ais->type7.mmsi4 = mmsi[3];
546
369
        ais->type7.seqno4 = seqno[3];
547
369
        break;
548
533
    }
549
1.29k
    case 8: // Binary Broadcast Message
550
1.29k
        RANGE_CHECK(56, 1008);
551
        //ais->type8.spare        = UBITS(38, 2);
552
1.16k
        ais->type8.dac            = UBITS(40, 10);
553
1.16k
        ais->type8.fid            = UBITS(50, 6);
554
1.16k
        ais->type8.bitcount       = bitlen - 56;
555
        // not strictly required - helps stability in testing
556
1.16k
        (void)memset(ais->type8.bitdata, '\0', sizeof(ais->type8.bitdata));
557
1.16k
        ais->type8.structured = false;
558
1.16k
        GPSD_LOG(LOG_PROG, errout, "AIVDM: type 8 dac %u fid %u bitlen %zu\n",
559
1.16k
                 ais->type8.dac, ais->type8.fid, bitlen);
560
1.16k
        if (1 == ais->type8.dac) {
561
1.02k
            switch (ais->type8.fid) {
562
73
            case 11:        // IMO236 - Meteorological/Hydrological data
563
                // layout is almost identical to FID=31 from IMO289
564
                // FIXME: we get length 352??
565
73
                RANGE_CHECK(346, 352);
566
0
                ais->type8.dac1fid11.lat        = SBITS(56, 24);
567
0
                ais->type8.dac1fid11.lon        = SBITS(80, 25);
568
0
                ais->type8.dac1fid11.day        = UBITS(105, 5);
569
0
                ais->type8.dac1fid11.hour       = UBITS(110, 5);
570
0
                ais->type8.dac1fid11.minute     = UBITS(115, 6);
571
0
                ais->type8.dac1fid11.wspeed     = UBITS(121, 7);
572
0
                ais->type8.dac1fid11.wgust      = UBITS(128, 7);
573
0
                ais->type8.dac1fid11.wdir       = UBITS(135, 9);
574
0
                ais->type8.dac1fid11.wgustdir   = UBITS(144, 9);
575
0
                ais->type8.dac1fid11.airtemp    = UBITS(153, 11);
576
0
                ais->type8.dac1fid11.humidity   = UBITS(164, 7);
577
0
                ais->type8.dac1fid11.dewpoint   = UBITS(171, 10);
578
0
                ais->type8.dac1fid11.pressure   = UBITS(181, 9);
579
0
                ais->type8.dac1fid11.pressuretend       = UBITS(190, 2);
580
0
                ais->type8.dac1fid11.visibility = UBITS(192, 8);
581
0
                ais->type8.dac1fid11.waterlevel = UBITS(200, 9);
582
0
                ais->type8.dac1fid11.leveltrend = UBITS(209, 2);
583
0
                ais->type8.dac1fid11.cspeed     = UBITS(211, 8);
584
0
                ais->type8.dac1fid11.cdir       = UBITS(219, 9);
585
0
                ais->type8.dac1fid11.cspeed2    = UBITS(228, 8);
586
0
                ais->type8.dac1fid11.cdir2      = UBITS(236, 9);
587
0
                ais->type8.dac1fid11.cdepth2    = UBITS(245, 5);
588
0
                ais->type8.dac1fid11.cspeed3    = UBITS(250, 8);
589
0
                ais->type8.dac1fid11.cdir3      = UBITS(258, 9);
590
0
                ais->type8.dac1fid11.cdepth3    = UBITS(267, 5);
591
0
                ais->type8.dac1fid11.waveheight = UBITS(272, 8);
592
0
                ais->type8.dac1fid11.waveperiod = UBITS(280, 6);
593
0
                ais->type8.dac1fid11.wavedir    = UBITS(286, 9);
594
0
                ais->type8.dac1fid11.swellheight        = UBITS(295, 8);
595
0
                ais->type8.dac1fid11.swellperiod        = UBITS(303, 6);
596
0
                ais->type8.dac1fid11.swelldir   = UBITS(309, 9);
597
0
                ais->type8.dac1fid11.seastate   = UBITS(318, 4);
598
0
                ais->type8.dac1fid11.watertemp  = UBITS(322, 10);
599
0
                ais->type8.dac1fid11.preciptype = UBITS(332, 3);
600
0
                ais->type8.dac1fid11.salinity   = UBITS(335, 9);
601
0
                ais->type8.dac1fid11.ice        = UBITS(344, 2);
602
0
                ais->type8.structured = true;
603
0
                break;
604
67
            case 13:        // IMO236 - Fairway closed
605
67
                UCHARS(56, ais->type8.dac1fid13.reason);
606
67
                UCHARS(176, ais->type8.dac1fid13.closefrom);
607
67
                UCHARS(296, ais->type8.dac1fid13.closeto);
608
67
                ais->type8.dac1fid13.radius     = UBITS(416, 10);
609
67
                ais->type8.dac1fid13.extunit    = UBITS(426, 2);
610
67
                ais->type8.dac1fid13.fday       = UBITS(428, 5);
611
67
                ais->type8.dac1fid13.fmonth     = UBITS(433, 4);
612
67
                ais->type8.dac1fid13.fhour      = UBITS(437, 5);
613
67
                ais->type8.dac1fid13.fminute    = UBITS(442, 6);
614
67
                ais->type8.dac1fid13.tday       = UBITS(448, 5);
615
67
                ais->type8.dac1fid13.tmonth     = UBITS(453, 4);
616
67
                ais->type8.dac1fid13.thour      = UBITS(457, 5);
617
67
                ais->type8.dac1fid13.tminute    = UBITS(462, 6);
618
                // skip 4 bits
619
67
                ais->type8.structured = true;
620
67
                break;
621
66
            case 15:        // IMO236 - Extended ship and voyage
622
66
                ais->type8.dac1fid15.airdraught = UBITS(56, 11);
623
                // skip 5 bits
624
66
                ais->type8.structured = true;
625
66
                break;
626
107
            case 16:        // Number of Persons On Board
627
107
                if (136 == ais->type8.bitcount) {
628
66
                    ais->type8.dac1fid16.persons = UBITS(88, 13);  // 289
629
66
                    ais->type8.structured = true;
630
66
                } else if (72 == ais->type8.bitcount) {
631
0
                    ais->type8.dac1fid16.persons = UBITS(55, 13);  // 236
632
0
                    ais->type8.structured = true;
633
0
                }
634
107
                break;
635
275
            case 17:        // IMO289 - VTS-generated/synthetic targets
636
275
                RANGE_CHECK(56, 1008);
637
2.74k
#define ARRAY_BASE 56
638
2.74k
#define ELEMENT_SIZE 122
639
275
                if ((ARRAY_BASE +
640
275
                     ELEMENT_SIZE * ROWS(ais->type8.dac1fid17.targets)) <
641
275
                    bitlen) {
642
63
                    bitlen = ARRAY_BASE +
643
63
                             ELEMENT_SIZE * ROWS(ais->type8.dac1fid17.targets);
644
63
                }
645
1.34k
                for (u = 0; ARRAY_BASE + (ELEMENT_SIZE * u) <= bitlen; u++) {
646
1.06k
                    struct target_t *tp = &ais->type8.dac1fid17.targets[u];
647
1.06k
                    unsigned a = ARRAY_BASE + (ELEMENT_SIZE * u);
648
1.06k
                    tp->idtype = UBITS(a + 0, 2);
649
1.06k
                    switch (tp->idtype) {
650
242
                    case DAC1FID17_IDTYPE_MMSI:
651
242
                        tp->id.mmsi     = UBITS(a + 2, 42);
652
242
                        break;
653
142
                    case DAC1FID17_IDTYPE_IMO:
654
142
                        tp->id.imo      = UBITS(a + 2, 42);
655
142
                        break;
656
279
                    case DAC1FID17_IDTYPE_CALLSIGN:
657
279
                        UCHARS(a + 2, tp->id.callsign);
658
279
                        break;
659
405
                    default:
660
405
                        UCHARS(a + 2, tp->id.other);
661
405
                        break;
662
1.06k
                    }
663
                    // skip 4 bits
664
1.06k
                    tp->lat     = SBITS(a + 48, 24);
665
1.06k
                    tp->lon     = SBITS(a + 72, 25);
666
1.06k
                    tp->course  = UBITS(a + 97, 9);
667
1.06k
                    tp->second  = UBITS(a + 106, 6);
668
1.06k
                    tp->speed   = UBITS(a + 112, 10);
669
1.06k
                }
670
275
                ais->type8.dac1fid17.ntargets = u;
671
275
#undef ARRAY_BASE
672
275
#undef ELEMENT_SIZE
673
275
                ais->type8.structured = true;
674
275
                break;
675
67
            case 19:        // IMO289 - Marine Traffic Signal
676
67
                RANGE_CHECK(258, 1008);
677
50
                ais->type8.dac1fid19.linkage    = UBITS(56, 10);
678
50
                UCHARS(66, ais->type8.dac1fid19.station);
679
50
                ais->type8.dac1fid19.lon        = SBITS(186, 25);
680
50
                ais->type8.dac1fid19.lat        = SBITS(211, 24);
681
50
                ais->type8.dac1fid19.status     = UBITS(235, 2);
682
50
                ais->type8.dac1fid19.signal     = UBITS(237, 5);
683
50
                ais->type8.dac1fid19.hour       = UBITS(242, 5);
684
50
                ais->type8.dac1fid19.minute     = UBITS(247, 6);
685
50
                ais->type8.dac1fid19.nextsignal = UBITS(253, 5);
686
                // skip 102 bits
687
50
                ais->type8.structured = true;
688
50
                break;
689
0
            case 21:        // IMO289 - Weather obs. report from ship
690
0
                break;
691
0
            case 22:        // IMO289 - Area notice - broadcast
692
0
                break;
693
0
            case 24:
694
                // IMO289 - Extended ship static & voyage-related data
695
0
                break;
696
0
            case 26:        // IMO289 - Environmental
697
0
                break;
698
167
            case 27:        // IMO289 - Route information - broadcast
699
167
                RANGE_CHECK(117, 1008);
700
136
                ais->type8.dac1fid27.linkage    = UBITS(56, 10);
701
136
                ais->type8.dac1fid27.sender     = UBITS(66, 3);
702
136
                ais->type8.dac1fid27.rtype      = UBITS(69, 5);
703
136
                ais->type8.dac1fid27.month      = UBITS(74, 4);
704
136
                ais->type8.dac1fid27.day        = UBITS(78, 5);
705
136
                ais->type8.dac1fid27.hour       = UBITS(83, 5);
706
136
                ais->type8.dac1fid27.minute     = UBITS(88, 6);
707
136
                ais->type8.dac1fid27.duration   = UBITS(94, 18);
708
136
                ais->type8.dac1fid27.waycount   = UBITS(112, 5);
709
1.41k
#define ARRAY_BASE 117
710
1.41k
#define ELEMENT_SIZE 55
711
136
                if ((ARRAY_BASE +
712
136
                     ELEMENT_SIZE * ROWS(ais->type8.dac1fid27.waypoints)) <
713
136
                    bitlen) {
714
0
                    bitlen = ARRAY_BASE +
715
0
                         ELEMENT_SIZE * ROWS(ais->type8.dac1fid27.waypoints);
716
0
                }
717
1.41k
                for (u = 0; u < ais->type8.dac1fid27.waycount; u++) {
718
1.28k
                    int a = ARRAY_BASE + (ELEMENT_SIZE * u);
719
1.28k
                    ais->type8.dac1fid27.waypoints[u].lon = SBITS(a + 0, 28);
720
1.28k
                    ais->type8.dac1fid27.waypoints[u].lat = SBITS(a + 28, 27);
721
1.28k
                }
722
136
#undef ARRAY_BASE
723
136
#undef ELEMENT_SIZE
724
136
                ais->type8.structured = true;
725
136
                break;
726
63
            case 29:        // IMO289 - Text Description - broadcast
727
63
                ais->type8.dac1fid29.linkage   = UBITS(56, 10);
728
63
                ENDCHARS(66, ais->type8.dac1fid29.text,
729
63
                         sizeof(ais->type8.dac1fid29.text));
730
63
                ais->type8.structured = true;
731
63
                break;
732
76
            case 31:        // IMO289 - Meteorological/Hydrological data
733
76
                ais->type8.dac1fid31.lon        = SBITS(56, 25);
734
76
                ais->type8.dac1fid31.lat        = SBITS(81, 24);
735
76
                ais->type8.dac1fid31.accuracy   = (bool)UBITS(105, 1);
736
76
                ais->type8.dac1fid31.day        = UBITS(106, 5);
737
76
                ais->type8.dac1fid31.hour       = UBITS(111, 5);
738
76
                ais->type8.dac1fid31.minute     = UBITS(116, 6);
739
76
                ais->type8.dac1fid31.wspeed     = UBITS(122, 7);
740
76
                ais->type8.dac1fid31.wgust      = UBITS(129, 7);
741
76
                ais->type8.dac1fid31.wdir       = UBITS(136, 9);
742
76
                ais->type8.dac1fid31.wgustdir   = UBITS(145, 9);
743
76
                ais->type8.dac1fid31.airtemp    = SBITS(154, 11);
744
76
                ais->type8.dac1fid31.humidity   = UBITS(165, 7);
745
76
                ais->type8.dac1fid31.dewpoint   = SBITS(172, 10);
746
76
                ais->type8.dac1fid31.pressure   = UBITS(182, 9);
747
76
                ais->type8.dac1fid31.pressuretend       = UBITS(191, 2);
748
76
                ais->type8.dac1fid31.visgreater = UBITS(193, 1);
749
76
                ais->type8.dac1fid31.visibility = UBITS(194, 7);
750
76
                ais->type8.dac1fid31.waterlevel = UBITS(201, 12);
751
76
                ais->type8.dac1fid31.leveltrend = UBITS(213, 2);
752
76
                ais->type8.dac1fid31.cspeed     = UBITS(215, 8);
753
76
                ais->type8.dac1fid31.cdir       = UBITS(223, 9);
754
76
                ais->type8.dac1fid31.cspeed2    = UBITS(232, 8);
755
76
                ais->type8.dac1fid31.cdir2      = UBITS(240, 9);
756
76
                ais->type8.dac1fid31.cdepth2    = UBITS(249, 5);
757
76
                ais->type8.dac1fid31.cspeed3    = UBITS(254, 8);
758
76
                ais->type8.dac1fid31.cdir3      = UBITS(262, 9);
759
76
                ais->type8.dac1fid31.cdepth3    = UBITS(271, 5);
760
76
                ais->type8.dac1fid31.waveheight = UBITS(276, 8);
761
76
                ais->type8.dac1fid31.waveperiod = UBITS(284, 6);
762
76
                ais->type8.dac1fid31.wavedir    = UBITS(290, 9);
763
76
                ais->type8.dac1fid31.swellheight = UBITS(299, 8);
764
76
                ais->type8.dac1fid31.swellperiod = UBITS(307, 6);
765
76
                ais->type8.dac1fid31.swelldir   = UBITS(313, 9);
766
76
                ais->type8.dac1fid31.seastate   = UBITS(322, 4);
767
76
                ais->type8.dac1fid31.watertemp  = SBITS(326, 10);
768
76
                ais->type8.dac1fid31.preciptype = UBITS(336, 3);
769
76
                ais->type8.dac1fid31.salinity   = UBITS(339, 9);
770
76
                ais->type8.dac1fid31.ice        = UBITS(348, 2);
771
76
                ais->type8.structured = true;
772
76
                break;
773
1.02k
            }
774
1.02k
        } else if (200 == ais->type8.dac) {
775
0
            switch (ais->type8.fid) {
776
0
            case 10:    // Inland ship static and voyage related data
777
0
                if (168 != bitlen) {
778
0
                    break;
779
0
                }
780
0
                UCHARS(56, ais->type8.dac200fid10.vin);
781
0
                ais->type8.dac200fid10.length   = UBITS(104, 13);
782
0
                ais->type8.dac200fid10.beam     = UBITS(117, 10);
783
0
                ais->type8.dac200fid10.shiptype = UBITS(127, 14);
784
0
                ais->type8.dac200fid10.hazard   = UBITS(141, 3);
785
0
                ais->type8.dac200fid10.draught  = UBITS(144, 11);
786
0
                ais->type8.dac200fid10.loaded   = UBITS(155, 2);
787
0
                ais->type8.dac200fid10.speed_q  = (bool)UBITS(157, 1);
788
0
                ais->type8.dac200fid10.course_q = (bool)UBITS(158, 1);
789
0
                ais->type8.dac200fid10.heading_q = (bool)UBITS(159, 1);
790
                // skip 8 bits
791
                /*
792
                 * Attempt to prevent false matches with this message type
793
                 * by range-checking certain fields.
794
                 */
795
0
                if (DAC200FID10_HAZARD_MAX < ais->type8.dac200fid10.hazard ||
796
0
                    !isascii((int)ais->type8.dac200fid10.vin[0])) {
797
0
                    ais->type8.structured = false;
798
0
                } else {
799
0
                    ais->type8.structured = true;
800
0
                }
801
0
                break;
802
0
            case 23:    // EMMA warning
803
0
                if (256 != bitlen) {
804
0
                    break;
805
0
                }
806
0
                ais->type8.dac200fid23.start_year       = UBITS(56, 8);
807
0
                ais->type8.dac200fid23.start_month      = UBITS(64, 4);
808
0
                ais->type8.dac200fid23.start_day        = UBITS(68, 5);
809
0
                ais->type8.dac200fid23.end_year         = UBITS(73, 8);
810
0
                ais->type8.dac200fid23.end_month        = UBITS(81, 4);
811
0
                ais->type8.dac200fid23.end_day          = UBITS(85, 5);
812
0
                ais->type8.dac200fid23.start_hour       = UBITS(90, 5);
813
0
                ais->type8.dac200fid23.start_minute     = UBITS(95, 6);
814
0
                ais->type8.dac200fid23.end_hour         = UBITS(101, 5);
815
0
                ais->type8.dac200fid23.end_minute       = UBITS(106, 6);
816
0
                ais->type8.dac200fid23.start_lon        = SBITS(112, 28);
817
0
                ais->type8.dac200fid23.start_lat        = SBITS(140, 27);
818
0
                ais->type8.dac200fid23.end_lon          = SBITS(167, 28);
819
0
                ais->type8.dac200fid23.end_lat          = SBITS(195, 27);
820
0
                ais->type8.dac200fid23.type             = UBITS(222, 4);
821
0
                ais->type8.dac200fid23.min              = SBITS(226, 9);
822
0
                ais->type8.dac200fid23.max              = SBITS(235, 9);
823
0
                ais->type8.dac200fid23.intensity        = UBITS(244, 2);
824
0
                ais->type8.dac200fid23.wind             = UBITS(246, 4);
825
                // skip 6 bits
826
0
                ais->type8.structured = true;
827
0
                break;
828
0
            case 24:    // Water level
829
0
                if (168 != bitlen) {
830
0
                    break;
831
0
                }
832
0
                UCHARS(56, ais->type8.dac200fid24.country);
833
0
#define ARRAY_BASE 68
834
0
#define ELEMENT_SIZE 25
835
0
                for (u = 0; ARRAY_BASE + (ELEMENT_SIZE * u) < bitlen;
836
0
                     u++) {
837
0
                    int a = ARRAY_BASE + (ELEMENT_SIZE * u);
838
0
                    ais->type8.dac200fid24.gauges[u].id = UBITS(a + 0,  11);
839
0
                    ais->type8.dac200fid24.gauges[u].level = SBITS(a + 11, 14);
840
0
                }
841
0
                ais->type8.dac200fid24.ngauges = u;
842
0
#undef ARRAY_BASE
843
0
#undef ELEMENT_SIZE
844
                // skip 6 bits
845
0
                ais->type8.structured = true;
846
0
                break;
847
0
            case 40:    // Signal status
848
0
                if (168 != bitlen) {
849
0
                    break;
850
0
                }
851
0
                ais->type8.dac200fid40.lon              = SBITS(56, 28);
852
0
                ais->type8.dac200fid40.lat              = SBITS(84, 27);
853
0
                ais->type8.dac200fid40.form             = UBITS(111, 4);
854
0
                ais->type8.dac200fid40.facing           = UBITS(115, 9);
855
0
                ais->type8.dac200fid40.direction        = UBITS(124, 3);
856
0
                ais->type8.dac200fid40.status           = UBITS(127, 30);
857
                // skip 11 bits
858
0
                ais->type8.structured = true;
859
0
                break;
860
0
            }
861
0
        }
862
        // land here if we failed to match a known DAC/FID
863
1.04k
        if (!ais->type8.structured) {
864
243
            size_t number_of_bytes = BITS_TO_BYTES(ais->type8.bitcount);
865
243
            (void)memcpy(ais->type8.bitdata, bits + (56 / CHAR_BIT),
866
243
                         number_of_bytes);
867
243
            size_t valid_bits_in_last_byte = ais->type8.bitcount % CHAR_BIT;
868
243
            if(valid_bits_in_last_byte > 0) {
869
118
                    ais->type8.bitdata[number_of_bytes - 1] &=
870
118
                            (0xFF << (8 - valid_bits_in_last_byte));
871
118
            }
872
243
        }
873
1.04k
        break;
874
246
    case 9: // Standard SAR Aircraft Position Report
875
246
        PERMISSIVE_LENGTH_CHECK(168);
876
159
        ais->type9.alt          = UBITS(38, 12);
877
159
        ais->type9.speed        = UBITS(50, 10);
878
159
        ais->type9.accuracy     = (bool)UBITS(60, 1);
879
159
        ais->type9.lon          = SBITS(61, 28);
880
159
        ais->type9.lat          = SBITS(89, 27);
881
159
        ais->type9.course       = UBITS(116, 12);
882
159
        ais->type9.second       = UBITS(128, 6);
883
159
        ais->type9.regional     = UBITS(134, 8);
884
159
        ais->type9.dte          = UBITS(142, 1);
885
        //ais->type9.spare      = UBITS(143, 3);
886
159
        ais->type9.assigned     = UBITS(146, 1) != 0;
887
159
        ais->type9.raim         = UBITS(147, 1) != 0;
888
159
        ais->type9.radio        = UBITS(148, 20);
889
159
        break;
890
199
    case 10: // UTC/Date inquiry
891
199
        PERMISSIVE_LENGTH_CHECK(72);
892
        //ais->type10.spare        = UBITS(38, 2);
893
159
        ais->type10.dest_mmsi      = UBITS(40, 30);
894
        //ais->type10.spare2       = UBITS(70, 2);
895
159
        break;
896
215
    case 12: // Safety Related Message
897
215
        RANGE_CHECK(72, 1008);
898
95
        ais->type12.seqno          = UBITS(38, 2);
899
95
        ais->type12.dest_mmsi      = UBITS(40, 30);
900
95
        ais->type12.retransmit     = (bool)UBITS(70, 1);
901
        //ais->type12.spare        = UBITS(71, 1);
902
95
        ENDCHARS(72, ais->type12.text, sizeof(ais->type12.text));
903
95
        break;
904
155
    case 14:    // Safety Related Broadcast Message
905
155
        RANGE_CHECK(40, 960);
906
        //ais->type14.spare          = UBITS(38, 2);
907
71
        ENDCHARS(40, ais->type14.text, sizeof(ais->type14.text));
908
71
        break;
909
333
    case 15:    // Interrogation
910
333
        RANGE_CHECK(88, 168);
911
229
        (void)memset(&ais->type15, '\0', sizeof(ais->type15));
912
        //ais->type14.spare         = UBITS(38, 2);
913
229
        ais->type15.mmsi1           = UBITS(40, 30);
914
229
        ais->type15.type1_1         = UBITS(70, 6);
915
229
        ais->type15.offset1_1       = UBITS(76, 12);
916
        //ais->type14.spare2        = UBITS(88, 2);
917
229
        if (90 < bitlen) {
918
162
            ais->type15.type1_2       = UBITS(90, 6);
919
162
            ais->type15.offset1_2     = UBITS(96, 12);
920
            //ais->type14.spare3      = UBITS(108, 2);
921
162
            if (110 < bitlen) {
922
77
                ais->type15.mmsi2       = UBITS(110, 30);
923
77
                ais->type15.type2_1     = UBITS(140, 6);
924
77
                ais->type15.offset2_1   = UBITS(146, 12);
925
                //ais->type14.spare4    = UBITS(158, 2);
926
77
            }
927
162
        }
928
229
        break;
929
306
    case 16:    // Assigned Mode Command
930
306
        RANGE_CHECK(96, 168);
931
182
        ais->type16.mmsi1       = UBITS(40, 30);
932
182
        ais->type16.offset1     = UBITS(70, 12);
933
182
        ais->type16.increment1  = UBITS(82, 10);
934
182
        if (144 > bitlen) {
935
60
            ais->type16.mmsi2=ais->type16.offset2=ais->type16.increment2 = 0;
936
122
        } else {
937
122
            ais->type16.mmsi2   = UBITS(92, 30);
938
122
            ais->type16.offset2 = UBITS(122, 12);
939
122
            ais->type16.increment2      = UBITS(134, 10);
940
122
        }
941
182
        break;
942
288
    case 17:    // GNSS Broadcast Binary Message
943
288
        RANGE_CHECK(80, 816);
944
        //ais->type17.spare     = UBITS(38, 2);
945
132
        ais->type17.lon         = SBITS(40, 18);
946
132
        ais->type17.lat         = SBITS(58, 17);
947
        //ais->type17.spare     = UBITS(75, 5);
948
132
        ais->type17.bitcount    = bitlen - 80;
949
132
        (void)memcpy(ais->type17.bitdata, bits + (80 / CHAR_BIT),
950
132
                     BITS_TO_BYTES(ais->type17.bitcount));
951
132
        break;
952
262
    case 18:    // Standard Class B CS Position Report
953
        // Per https://www.navcen.uscg.gov/ais-class-b-reports
954
262
        PERMISSIVE_LENGTH_CHECK(168)
955
171
        ais->type18.reserved    = UBITS(38, 8);
956
171
        ais->type18.speed       = UBITS(46, 10);
957
171
        ais->type18.accuracy    = UBITS(56, 1) != 0;
958
171
        ais->type18.lon         = SBITS(57, 28);
959
171
        ais->type18.lat         = SBITS(85, 27);
960
171
        ais->type18.course      = UBITS(112, 12);
961
171
        ais->type18.heading     = UBITS(124, 9);
962
171
        ais->type18.second      = UBITS(133, 6);
963
171
        ais->type18.regional    = UBITS(139, 2);
964
171
        ais->type18.cs          = UBITS(141, 1) != 0;
965
171
        ais->type18.display     = UBITS(142, 1) != 0;
966
171
        ais->type18.dsc         = UBITS(143, 1) != 0;
967
171
        ais->type18.band        = UBITS(144, 1) != 0;
968
171
        ais->type18.msg22       = UBITS(145, 1) != 0;
969
171
        ais->type18.assigned    = UBITS(146, 1) != 0;
970
171
        ais->type18.raim        = UBITS(147, 1) != 0;
971
171
        ais->type18.radio       = UBITS(148, 20);
972
171
        break;
973
231
    case 19:    // Extended Class B CS Position Report
974
231
        PERMISSIVE_LENGTH_CHECK(312)
975
137
        ais->type19.reserved     = UBITS(38, 8);
976
137
        ais->type19.speed        = UBITS(46, 10);
977
137
        ais->type19.accuracy     = UBITS(56, 1) != 0;
978
137
        ais->type19.lon          = SBITS(57, 28);
979
137
        ais->type19.lat          = SBITS(85, 27);
980
137
        ais->type19.course       = UBITS(112, 12);
981
137
        ais->type19.heading      = UBITS(124, 9);
982
137
        ais->type19.second       = UBITS(133, 6);
983
137
        ais->type19.regional     = UBITS(139, 4);
984
137
        UCHARS(143, ais->type19.shipname);
985
137
        ais->type19.shiptype     = UBITS(263, 8);
986
137
        ais->type19.to_bow       = UBITS(271, 9);
987
137
        ais->type19.to_stern     = UBITS(280, 9);
988
137
        ais->type19.to_port      = UBITS(289, 6);
989
137
        ais->type19.to_starboard = UBITS(295, 6);
990
137
        ais->type19.epfd         = UBITS(301, 4);
991
137
        ais->type19.raim         = UBITS(305, 1) != 0;
992
137
        ais->type19.dte          = UBITS(306, 1) != 0;
993
137
        ais->type19.assigned     = UBITS(307, 1) != 0;
994
        //ais->type19.spare      = UBITS(308, 4);
995
137
        break;
996
283
    case 20:    // Data Link Management Message
997
283
        RANGE_CHECK(72, 186);
998
        //ais->type20.spare     = UBITS(38, 2);
999
94
        ais->type20.offset1     = UBITS(40, 12);
1000
94
        ais->type20.number1     = UBITS(52, 4);
1001
94
        ais->type20.timeout1    = UBITS(56, 3);
1002
94
        ais->type20.increment1  = UBITS(59, 11);
1003
94
        ais->type20.offset2     = UBITS(70, 12);
1004
94
        ais->type20.number2     = UBITS(82, 4);
1005
94
        ais->type20.timeout2    = UBITS(86, 3);
1006
94
        ais->type20.increment2  = UBITS(89, 11);
1007
94
        ais->type20.offset3     = UBITS(100, 12);
1008
94
        ais->type20.number3     = UBITS(112, 4);
1009
94
        ais->type20.timeout3    = UBITS(116, 3);
1010
94
        ais->type20.increment3  = UBITS(119, 11);
1011
94
        ais->type20.offset4     = UBITS(130, 12);
1012
94
        ais->type20.number4     = UBITS(142, 4);
1013
94
        ais->type20.timeout4    = UBITS(146, 3);
1014
94
        ais->type20.increment4  = UBITS(149, 11);
1015
94
        break;
1016
369
    case 21:    // Aid-to-Navigation Report
1017
        // Per https://www.navcen.uscg.gov/ais-class-b-reports
1018
369
        RANGE_CHECK(272, 368);
1019
262
        ais->type21.aid_type     = UBITS(38, 5);
1020
262
        from_sixbit_untrimmed(errout, bits, bitlen, 43, 20, ais->type21.name,
1021
262
                              sizeof(ais->type21.name));
1022
262
        ais->type21.accuracy     = UBITS(163, 1);
1023
262
        ais->type21.lon          = SBITS(164, 28);
1024
262
        ais->type21.lat          = SBITS(192, 27);
1025
262
        ais->type21.to_bow       = UBITS(219, 9);
1026
262
        ais->type21.to_stern     = UBITS(228, 9);
1027
262
        ais->type21.to_port      = UBITS(237, 6);
1028
262
        ais->type21.to_starboard = UBITS(243, 6);
1029
262
        ais->type21.epfd         = UBITS(249, 4);
1030
262
        ais->type21.second       = UBITS(253, 6);
1031
262
        ais->type21.off_position = UBITS(259, 1)!= 0;
1032
262
        ais->type21.regional     = UBITS(260, 8);
1033
262
        ais->type21.raim         = UBITS(268, 1) != 0;
1034
262
        ais->type21.virtual_aid  = UBITS(269, 1) != 0;
1035
262
        ais->type21.assigned     = UBITS(270, 1) != 0;
1036
        //ais->type21.spare      = UBITS(271, 1);
1037
262
        if (20 == strnlen(ais->type21.name, 21) &&
1038
65
            272 < bitlen) {
1039
65
            ENDCHARS(272, ais->type21.name + 20,
1040
65
                     sizeof(ais->type21.name) - 20);
1041
65
        }
1042
262
        trim_spaces_on_right_end(ais->type21.name, sizeof(ais->type21.name));
1043
262
        break;
1044
196
    case 22:    // Channel Management
1045
196
        PERMISSIVE_LENGTH_CHECK(168)
1046
129
        ais->type22.channel_a    = UBITS(40, 12);
1047
129
        ais->type22.channel_b    = UBITS(52, 12);
1048
129
        ais->type22.txrx         = UBITS(64, 4);
1049
129
        ais->type22.power        = UBITS(68, 1);
1050
129
        ais->type22.addressed    = UBITS(139, 1);
1051
129
        if (!ais->type22.addressed) {
1052
47
            ais->type22.area.ne_lon       = SBITS(69, 18);
1053
47
            ais->type22.area.ne_lat       = SBITS(87, 17);
1054
47
            ais->type22.area.sw_lon       = SBITS(104, 18);
1055
47
            ais->type22.area.sw_lat       = SBITS(122, 17);
1056
82
        } else {
1057
82
            ais->type22.mmsi.dest1        = UBITS(69, 30);
1058
82
            ais->type22.mmsi.dest2        = UBITS(104, 30);
1059
82
        }
1060
129
        ais->type22.band_a       = UBITS(140, 1);
1061
129
        ais->type22.band_b       = UBITS(141, 1);
1062
129
        ais->type22.zonesize     = UBITS(142, 3);
1063
129
        break;
1064
234
    case 23:    // Group Assignment Command
1065
234
        PERMISSIVE_LENGTH_CHECK(160)
1066
159
        ais->type23.ne_lon       = SBITS(40, 18);
1067
159
        ais->type23.ne_lat       = SBITS(58, 17);
1068
159
        ais->type23.sw_lon       = SBITS(75, 18);
1069
159
        ais->type23.sw_lat       = SBITS(93, 17);
1070
159
        ais->type23.stationtype  = UBITS(110, 4);
1071
159
        ais->type23.shiptype     = UBITS(114, 8);
1072
159
        ais->type23.txrx         = UBITS(144, 4);
1073
159
        ais->type23.interval     = UBITS(146, 4);
1074
159
        ais->type23.quiet        = UBITS(150, 4);
1075
159
        break;
1076
2.26k
    case 24:    // Class B CS Static Data Report
1077
2.26k
        switch (UBITS(38, 2)) {
1078
1.46k
        case 0:
1079
1.46k
            RANGE_CHECK(160, 168);
1080
            // save incoming 24A shipname/MMSI pairs in a circular queue
1081
1.27k
            {
1082
1.27k
                struct ais_type24a_t *saveptr =
1083
1.27k
                        &type24_queue->ships[type24_queue->index];
1084
1085
1.27k
                GPSD_LOG(LOG_PROG, errout, "AIVDM: 24A from %09u stashed.\n",
1086
1.27k
                         ais->mmsi);
1087
1.27k
                saveptr->mmsi = ais->mmsi;
1088
1.27k
                UCHARS(40, saveptr->shipname);
1089
1.27k
                ++type24_queue->index;
1090
1.27k
                type24_queue->index %= MAX_TYPE24_INTERLEAVE;
1091
1.27k
            }
1092
            //ais->type24.a.spare       = UBITS(160, 8);
1093
1094
1.27k
            UCHARS(40, ais->type24.shipname);
1095
1.27k
            ais->type24.part = part_a;
1096
1.27k
            return true;
1097
729
        case 1:
1098
729
            PERMISSIVE_LENGTH_CHECK(168)
1099
657
            ais->type24.shiptype = UBITS(40, 8);
1100
            /*
1101
             * In ITU-R 1371-4, there are new model and serial fields
1102
             * carved out of the right-hand end of vendorid, which is
1103
             * reduced from 7 chars to 3.  To cope with older AIS
1104
             * implementations conforming to revision 3 and older,
1105
             * unpack the trailing bits *both* ways; truly
1106
             * revision-4-conformant implementations will have up to
1107
             * four characters of trailing garbage on the vendorid,
1108
             * and older implementations will have garbafe in the
1109
             * model and serial fields.
1110
             */
1111
657
            UCHARS(48, ais->type24.vendorid);
1112
657
            ais->type24.model = UBITS(66, 4);
1113
657
            ais->type24.serial = UBITS(70, 20);
1114
657
            UCHARS(90, ais->type24.callsign);
1115
657
            if (AIS_AUXILIARY_MMSI(ais->mmsi)) {
1116
56
                ais->type24.mothership_mmsi   = UBITS(132, 30);
1117
601
            } else {
1118
601
                ais->type24.dim.to_bow        = UBITS(132, 9);
1119
601
                ais->type24.dim.to_stern      = UBITS(141, 9);
1120
601
                ais->type24.dim.to_port       = UBITS(150, 6);
1121
601
                ais->type24.dim.to_starboard  = UBITS(156, 6);
1122
601
            }
1123
            //ais->type24.b.spare           = UBITS(162, 8);
1124
1125
            // search the 24A queue for a matching MMSI
1126
4.72k
            for (u = 0; u < MAX_TYPE24_INTERLEAVE; u++) {
1127
4.31k
                if (type24_queue->ships[u].mmsi == ais->mmsi) {
1128
240
                    (void)strlcpy(ais->type24.shipname,
1129
240
                                  type24_queue->ships[u].shipname,
1130
240
                                  sizeof(ais->type24.shipname));
1131
240
                    GPSD_LOG(LOG_PROG, errout,
1132
240
                             "AIVDM 24B from %09u matches a 24A.\n",
1133
240
                             ais->mmsi);
1134
                    // prevent false match if a 24B is repeated
1135
240
                    type24_queue->ships[u].mmsi = 0;
1136
240
                    ais->type24.part = both;
1137
240
                    return true;
1138
240
                }
1139
4.31k
            }
1140
1141
            // no match, return Part B
1142
417
            ais->type24.part = part_b;
1143
417
            return true;
1144
65
        default:
1145
65
            GPSD_LOG(LOG_WARN, errout,
1146
65
                     "AIVDM message type 24 of subtype unknown.\n");
1147
65
            return false;
1148
2.26k
        }
1149
        // break;
1150
453
    case 25:    // Binary Message, Single Slot
1151
        // this check and the following one reject line noise
1152
453
        if (40 > bitlen ||
1153
372
            168 < bitlen) {
1154
150
            GPSD_LOG(LOG_WARN, errout,
1155
150
                     "AIVDM message type 25 size not between "
1156
150
                     "40 to 168 bits (%zd).\n", bitlen);
1157
150
            return false;
1158
150
        }
1159
303
        ais->type25.addressed   = (bool)UBITS(38, 1);
1160
303
        ais->type25.structured  = (bool)UBITS(39, 1);
1161
303
        if (bitlen < (unsigned)(40 + (16 * ais->type25.structured) +
1162
303
                                (30 * ais->type25.addressed))) {
1163
70
            GPSD_LOG(LOG_WARN, errout,
1164
70
                     "AIVDM message type 25 too short for mode.\n");
1165
70
            return false;
1166
70
        }
1167
233
        if (ais->type25.addressed) {
1168
180
            ais->type25.dest_mmsi   = UBITS(40, 30);
1169
180
        }
1170
233
        if (ais->type25.structured) {
1171
113
            ais->type25.app_id      = UBITS(40 + ais->type25.addressed * 30,16);
1172
113
        }
1173
233
        ais->type25.bitcount        = bitlen - 40 - 16 * ais->type25.structured;
1174
        // bit 40 is exactly 5 bytes in; 2 bytes is 16 bits
1175
233
        (void)memcpy(ais->type25.bitdata,
1176
233
                     bits + 5 + 2 * ais->type25.structured,
1177
233
                     BITS_TO_BYTES(ais->type25.bitcount));
1178
        // discard MMSI if addressed
1179
233
        if (ais->type25.addressed) {
1180
180
            shiftleft((unsigned char *)ais->type25.bitdata,
1181
180
                      ais->type25.bitcount, 30);
1182
180
            ais->type25.bitcount -= 30;
1183
180
        }
1184
233
        break;
1185
387
    case 26:    // Binary Message, Multiple Slot
1186
387
        RANGE_CHECK(60, 1004);
1187
263
        ais->type26.addressed   = (bool)UBITS(38, 1);
1188
263
        ais->type26.structured  = (bool)UBITS(39, 1);
1189
263
        if ((signed)bitlen < 40 + 16 * ais->type26.structured +
1190
263
                30 * ais->type26.addressed + 20) {
1191
68
            GPSD_LOG(LOG_WARN, errout,
1192
68
                     "AIVDM message type 26 too short for mode.\n");
1193
68
            return false;
1194
68
        }
1195
195
        if (ais->type26.addressed) {
1196
104
            ais->type26.dest_mmsi = UBITS(40, 30);
1197
104
        }
1198
195
        if (ais->type26.structured) {
1199
82
            ais->type26.app_id    = UBITS(40 + ais->type26.addressed * 30, 16);
1200
82
        }
1201
195
        ais->type26.bitcount      = bitlen - 60 - 16 * ais->type26.structured;
1202
195
        (void)memcpy(ais->type26.bitdata,
1203
195
                     bits + 5 + 2 * ais->type26.structured,
1204
195
                     BITS_TO_BYTES(ais->type26.bitcount));
1205
        // discard MMSI if addressed
1206
195
        if (ais->type26.addressed) {
1207
104
            shiftleft((unsigned char *)ais->type26.bitdata,
1208
104
                      ais->type26.bitcount, 30);
1209
104
            ais->type26.bitcount -= 30;
1210
104
        }
1211
195
        break;
1212
293
    case 27:    // Long Range AIS Broadcast message
1213
293
        if (96 != bitlen &&
1214
178
            168 != bitlen) {
1215
70
            GPSD_LOG(LOG_WARN, errout,
1216
70
                     "unexpected AIVDM message type 27 (%zd).\n",
1217
70
                     bitlen);
1218
70
            return false;
1219
70
        }
1220
223
        if (168 == bitlen) {
1221
            /*
1222
             * This is an implementation error observed in the wild,
1223
             * sending a full 168-bit slot rather than just 96 bits.
1224
             */
1225
108
            GPSD_LOG(LOG_WARN, errout,
1226
108
                     "oversized 168-bit AIVDM message type 27.\n");
1227
108
        }
1228
223
        ais->type27.accuracy    = (bool)UBITS(38, 1);
1229
223
        ais->type27.raim        = UBITS(39, 1) != 0;
1230
223
        ais->type27.status      = UBITS(40, 4);
1231
223
        ais->type27.lon         = SBITS(44, 18);
1232
223
        ais->type27.lat         = SBITS(62, 17);
1233
223
        ais->type27.speed       = UBITS(79, 6);
1234
223
        ais->type27.course      = UBITS(85, 9);
1235
223
        ais->type27.gnss        = (bool)UBITS(94, 1);
1236
223
        break;
1237
214
    default:
1238
214
        GPSD_LOG(LOG_ERROR, errout,
1239
214
                 "Unparsed AIVDM message type %d.\n",ais->type);
1240
214
        return false;
1241
12.0k
    }
1242
    // *INDENT-ON*
1243
6.37k
#undef UCHARS
1244
6.37k
#undef SBITS
1245
6.37k
#undef UBITS
1246
1247
    // data is fully decoded
1248
6.37k
    return true;
1249
12.0k
}
1250
// vim: set expandtab shiftwidth=4