Coverage Report

Created: 2026-04-12 06:12

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