wireguard-uapi 3.0.1

Control WireGuard interfaces.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
use crate::err::{ParseAttributeError, ParseDeviceError, ParseIpAddrError, ParseSockAddrError};
use crate::get::{AllowedIp, AllowedIpBuilder, Device, DeviceBuilder, Peer, PeerBuilder};
use crate::linux::attr::{
    NlaNested, WgAllowedIpAttribute, WgDeviceAttribute, WgPeerAttribute, NLA_TYPE_MASK,
};
use libc::{in6_addr, in_addr, AF_INET, AF_INET6};
use neli::{
    attr,
    genl::Nlattr,
    types::{Buffer, GenlBuffer},
};
use std::convert::TryFrom;
use std::mem::size_of;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::time::Duration;

type AttrHandle<'a, T> = attr::AttrHandle<'a, GenlBuffer<T, Buffer>, Nlattr<T, Buffer>>;

impl TryFrom<AttrHandle<'_, WgDeviceAttribute>> for Device {
    type Error = ParseDeviceError;

    fn try_from(handle: AttrHandle<WgDeviceAttribute>) -> Result<Self, Self::Error> {
        let mut device_builder = DeviceBuilder::default();

        for attr in handle.iter() {
            match attr.nla_type.nla_type & NLA_TYPE_MASK {
                WgDeviceAttribute::Unspec => {
                    // The embeddable-wg-library example ignores unspec, so we'll do the same.
                }
                WgDeviceAttribute::Ifindex => {
                    device_builder.ifindex(parse_nla_u32(attr.nla_payload.as_ref())?);
                }
                WgDeviceAttribute::Ifname => {
                    device_builder.ifname(parse_nla_nul_string(attr.nla_payload.as_ref())?);
                }
                WgDeviceAttribute::PrivateKey => {
                    device_builder.private_key(Some(parse_device_key(attr.nla_payload.as_ref())?));
                }
                WgDeviceAttribute::PublicKey => {
                    device_builder.public_key(Some(parse_device_key(attr.nla_payload.as_ref())?));
                }
                WgDeviceAttribute::ListenPort => {
                    device_builder.listen_port(parse_nla_u16(attr.nla_payload.as_ref())?);
                }
                WgDeviceAttribute::Fwmark => {
                    device_builder.fwmark(parse_nla_u32(attr.nla_payload.as_ref())?);
                }
                WgDeviceAttribute::Peers => {
                    device_builder.peers(parse_peers(attr.get_attr_handle::<NlaNested>()?)?);
                }
                WgDeviceAttribute::Flags => {
                    // This attribute is for set_device. Ignore it for get_device.
                }
                WgDeviceAttribute::UnrecognizedConst(i) => {
                    return Err(ParseDeviceError::UnknownDeviceAttributeError { id: i })
                }
            }
        }

        Ok(device_builder.build()?)
    }
}

pub fn extend_device(
    mut device: Device,
    handle: AttrHandle<'_, WgDeviceAttribute>,
) -> Result<Device, ParseDeviceError> {
    let next_peers = {
        let peers_attr = handle
            .iter()
            .find(|attr| attr.nla_type.nla_type & NLA_TYPE_MASK == WgDeviceAttribute::Peers)
            .expect("Unable to find additional peers to coalesce.");
        let handle = peers_attr.get_attr_handle()?;

        handle
            .iter()
            .map(Nlattr::<NlaNested, Buffer>::get_attr_handle::<WgPeerAttribute>)
            .map(|handle| {
                handle
                    .map_err(|err| err.into())
                    .and_then(parse_peer_builder)
            })
            .collect::<Result<Vec<PeerBuilder>, _>>()?
    };

    for next_peer in next_peers {
        let matching_last_peer = device
            .peers
            .last_mut()
            .filter(|last_peer| Some(last_peer.public_key) == next_peer.public_key);

        match matching_last_peer {
            Some(matching_last_peer) => matching_last_peer
                .allowed_ips
                .append(&mut next_peer.allowed_ips.unwrap_or_default()),
            None => device.peers.push(next_peer.build()?),
        }
    }

    Ok(device)
}

pub fn parse_peers(handle: AttrHandle<'_, NlaNested>) -> Result<Vec<Peer>, ParseDeviceError> {
    let mut peers = vec![];

    for peer in handle.iter() {
        let handle = peer.get_attr_handle()?;
        peers.push(Peer::try_from(handle)?);
    }

    Ok(peers)
}

pub fn parse_peer_builder(
    handle: AttrHandle<'_, WgPeerAttribute>,
) -> Result<PeerBuilder, ParseDeviceError> {
    let mut peer_builder = PeerBuilder::default();

    for attr in handle.iter() {
        match attr.nla_type.nla_type & NLA_TYPE_MASK {
            WgPeerAttribute::Unspec => {}
            WgPeerAttribute::Flags => {}
            WgPeerAttribute::PublicKey => {
                peer_builder.public_key(parse_device_key(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::PresharedKey => {
                peer_builder.preshared_key(parse_device_key(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::Endpoint => {
                peer_builder.endpoint(Some(parse_sockaddr_in(attr.nla_payload.as_ref())?));
            }
            WgPeerAttribute::PersistentKeepaliveInterval => {
                peer_builder
                    .persistent_keepalive_interval(parse_nla_u16(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::LastHandshakeTime => {
                peer_builder
                    .last_handshake_time(parse_last_handshake_time(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::RxBytes => {
                peer_builder.rx_bytes(parse_nla_u64(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::TxBytes => {
                peer_builder.tx_bytes(parse_nla_u64(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::AllowedIps => {
                let handle = attr.get_attr_handle()?;
                peer_builder.allowed_ips(parse_allowedips(handle)?);
            }
            WgPeerAttribute::ProtocolVersion => {
                peer_builder.protocol_version(parse_nla_u32(attr.nla_payload.as_ref())?);
            }
            WgPeerAttribute::UnrecognizedConst(i) => {
                return Err(ParseDeviceError::UnknownPeerAttributeError { id: i })
            }
        }
    }

    Ok(peer_builder)
}

impl TryFrom<AttrHandle<'_, WgPeerAttribute>> for Peer {
    type Error = ParseDeviceError;
    fn try_from(handle: AttrHandle<'_, WgPeerAttribute>) -> Result<Self, Self::Error> {
        let peer_builder = parse_peer_builder(handle)?;
        Ok(peer_builder.build()?)
    }
}

pub fn parse_allowedips(
    handle: AttrHandle<'_, NlaNested>,
) -> Result<Vec<AllowedIp>, ParseDeviceError> {
    let mut allowed_ips = vec![];

    for allowed_ip in handle.iter() {
        allowed_ips.push(AllowedIp::try_from(
            allowed_ip.get_attr_handle::<WgAllowedIpAttribute>()?,
        )?);
    }

    Ok(allowed_ips)
}

impl TryFrom<AttrHandle<'_, WgAllowedIpAttribute>> for AllowedIp {
    type Error = ParseDeviceError;

    fn try_from(handle: AttrHandle<'_, WgAllowedIpAttribute>) -> Result<Self, Self::Error> {
        let mut allowed_ip_builder = AllowedIpBuilder::default();

        for attr in handle.iter() {
            let payload = attr.nla_payload.as_ref();
            match attr.nla_type.nla_type {
                WgAllowedIpAttribute::Unspec => {}
                WgAllowedIpAttribute::Family => {
                    allowed_ip_builder.family(parse_nla_u16(payload)?);
                }
                WgAllowedIpAttribute::IpAddr => {
                    let addr = match payload.len() {
                        len if len == size_of::<in_addr>() => IpAddr::V4(parse_in_addr(payload)?),
                        len if len == size_of::<in6_addr>() => IpAddr::V6(parse_in6_addr(payload)?),
                        len => {
                            return Err(ParseDeviceError::from(ParseAttributeError::from(
                                ParseIpAddrError::InvalidIpAddrLengthError { found: len },
                            )))
                        }
                    };
                    allowed_ip_builder.ipaddr(addr);
                }
                WgAllowedIpAttribute::CidrMask => {
                    allowed_ip_builder.cidr_mask(parse_nla_u8(payload)?);
                }
                WgAllowedIpAttribute::UnrecognizedConst(i) => {
                    return Err(ParseDeviceError::UnknownAllowedIpAttributeError { id: i })
                }
            }
        }

        Ok(allowed_ip_builder.build()?)
    }
}

macro_rules! create_parse_nla_int {
    ($func_name: ident, $int_type: ident, $bytes: expr) => {
        pub fn $func_name(buf: &[u8]) -> Result<$int_type, ParseAttributeError> {
            Some(buf.len())
                .filter(|&len| len == $bytes)
                .ok_or_else(|| ParseAttributeError::StaticLengthError {
                    expected: $bytes,
                    found: buf.len(),
                })?;

            let mut arr = [0u8; $bytes];
            arr.copy_from_slice(&buf);
            Ok($int_type::from_ne_bytes(arr))
        }
    };
}

create_parse_nla_int!(parse_nla_u8, u8, size_of::<u8>());
create_parse_nla_int!(parse_nla_u16, u16, size_of::<u16>());
create_parse_nla_int!(parse_nla_u32, u32, size_of::<u32>());
create_parse_nla_int!(parse_nla_u64, u64, size_of::<u64>());
create_parse_nla_int!(parse_nla_i64, i64, size_of::<i64>());

pub fn parse_nla_u16_be(buf: &[u8]) -> Result<u16, ParseAttributeError> {
    Some(buf.len()).filter(|&len| len == 2).ok_or({
        ParseAttributeError::StaticLengthError {
            expected: 2,
            found: buf.len(),
        }
    })?;

    let mut arr = [0u8; 2];
    arr.copy_from_slice(buf);
    Ok(u16::from_be_bytes(arr))
}

pub fn parse_nla_nul_string(payload: &[u8]) -> Result<String, ParseAttributeError> {
    // Although payload is a known length, a null-terminated C string is still
    // sent over netlink. We should check that this was the case before dropping
    // the last character (which should be null).
    let mut payload = payload.to_vec();

    payload
        .pop()
        .filter(|char| char == &0)
        .ok_or(ParseAttributeError::InvalidCStringError)?;

    Ok(String::from_utf8(payload)?)
}

pub fn parse_device_key(buf: &[u8]) -> Result<[u8; 32], ParseAttributeError> {
    Some(buf.len()).filter(|&len| len == 32).ok_or({
        ParseAttributeError::StaticLengthError {
            expected: 32,
            found: buf.len(),
        }
    })?;

    let mut key = [0u8; 32];
    key.copy_from_slice(buf);
    Ok(key)
}

pub fn parse_sockaddr_in(buf: &[u8]) -> Result<SocketAddr, ParseAttributeError> {
    let family = parse_nla_u16(&buf[0..2])?;

    // The port bytes are always in network byte order (or big endian) according to man 7 ip.
    let port = parse_nla_u16_be(&buf[2..4])?;

    let addr = match libc::c_int::from(family) {
        AF_INET => IpAddr::V4(parse_in_addr(&buf[4..8])?),
        AF_INET6 => IpAddr::V6(parse_in6_addr(&buf[8..24])?),
        id => return Err(ParseSockAddrError::UnrecognizedAddressFamilyError { id }.into()),
    };

    Ok(SocketAddr::new(addr, port))
}

pub fn parse_last_handshake_time(buf: &[u8]) -> Result<Duration, ParseAttributeError> {
    Some(buf.len()).filter(|&len| len == 16).ok_or({
        ParseAttributeError::StaticLengthError {
            expected: 16,
            found: buf.len(),
        }
    })?;

    // WireGuard uses __kernel__timespec for last handshake time.
    // https://git.zx2c4.com/WireGuard/commit/?id=c870c7af53f44a37814dfc76ceb8ad88e290fcd8
    //
    // The following try_from calls should only fail if negative values are returned. Otherwise a
    // positive valued i64 will fit in a u32 and u64.
    let secs = parse_nla_i64(&buf[0..8])?;
    let secs = u64::try_from(secs)?;
    let nanos = parse_nla_i64(&buf[8..16])?;
    let nanos = u32::try_from(nanos)?;

    Ok(Duration::new(secs, nanos))
}

pub fn parse_in_addr(buf: &[u8]) -> Result<Ipv4Addr, ParseAttributeError> {
    // https://linux.die.net/man/7/ip
    Some(buf.len()).filter(|&len| len == 4).ok_or({
        ParseAttributeError::StaticLengthError {
            expected: 4,
            found: buf.len(),
        }
    })?;
    Ok(Ipv4Addr::new(buf[0], buf[1], buf[2], buf[3]))
}

pub fn parse_in6_addr(buf: &[u8]) -> Result<Ipv6Addr, ParseAttributeError> {
    // http://man7.org/linux/man-pages/man7/ipv6.7.html
    Some(buf.len()).filter(|&len| len == 16).ok_or({
        ParseAttributeError::StaticLengthError {
            expected: 16,
            found: buf.len(),
        }
    })?;
    Ok(Ipv6Addr::new(
        parse_nla_u16_be(&buf[0..2])?,
        parse_nla_u16_be(&buf[2..4])?,
        parse_nla_u16_be(&buf[4..6])?,
        parse_nla_u16_be(&buf[6..8])?,
        parse_nla_u16_be(&buf[8..10])?,
        parse_nla_u16_be(&buf[10..12])?,
        parse_nla_u16_be(&buf[12..14])?,
        parse_nla_u16_be(&buf[14..16])?,
    ))
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::linux::cmd::WgCmd;
    use anyhow::Error;
    use neli::{err::DeError, genl::Genlmsghdr};

    // This device comes from the configuration example in "man wg", but with
    // the third peer removed since it specifies an domain endpoint only valid
    // in the context of wg-quick.
    fn get_device_from_man() -> anyhow::Result<Device> {
        Ok(Device {
            ifindex: 6,
            ifname: "test".to_string(),
            private_key: Some(parse_device_key(&base64::decode(
                "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=",
            )?)?),
            public_key: Some(parse_device_key(&base64::decode(
                "HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=",
            )?)?),
            listen_port: 51820,
            fwmark: 0,
            peers: vec![
                Peer {
                    public_key: parse_device_key(&base64::decode(
                        "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg",
                    )?)?,
                    preshared_key: [0u8; 32],
                    endpoint: Some("192.95.5.67:1234".parse()?),
                    persistent_keepalive_interval: 0,
                    last_handshake_time: Duration::new(0, 0),
                    rx_bytes: 0,
                    tx_bytes: 0,
                    allowed_ips: vec![
                        AllowedIp {
                            family: libc::AF_INET as u16,
                            ipaddr: "10.192.122.3".parse()?,
                            cidr_mask: 32,
                        },
                        AllowedIp {
                            family: libc::AF_INET as u16,
                            ipaddr: "10.192.124.0".parse()?,
                            cidr_mask: 24,
                        },
                    ],
                    protocol_version: 1,
                },
                Peer {
                    public_key: parse_device_key(&base64::decode(
                        "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=",
                    )?)?,
                    preshared_key: [0u8; 32],
                    endpoint: Some("[2607:5300:60:6b0::c05f:543]:2468".parse()?),
                    persistent_keepalive_interval: 0,
                    last_handshake_time: Duration::new(0, 0),
                    rx_bytes: 0,
                    tx_bytes: 0,
                    allowed_ips: vec![
                        AllowedIp {
                            family: libc::AF_INET as u16,
                            ipaddr: "10.192.122.4".parse()?,
                            cidr_mask: 32,
                        },
                        AllowedIp {
                            family: libc::AF_INET as u16,
                            ipaddr: "192.168.0.0".parse()?,
                            cidr_mask: 16,
                        },
                    ],
                    protocol_version: 1,
                },
            ],
        })
    }

    fn create_test_genlmsghdr(
        payload: &[u8],
    ) -> Result<Genlmsghdr<WgCmd, WgDeviceAttribute>, DeError> {
        use neli::FromBytesWithInput;
        Genlmsghdr::from_bytes_with_input(&mut std::io::Cursor::new(payload), payload.len())
    }

    #[test]
    fn parse_device_example_from_man_page() -> Result<(), Error> {
        let payload = vec![
            0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x6c, 0xca, 0x00, 0x00, 0x08, 0x00,
            0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00,
            0x09, 0x00, 0x02, 0x00, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00,
            0x03, 0x00, 0xc8, 0x09, 0xf3, 0xe5, 0x31, 0x7e, 0x95, 0x75, 0xc9, 0xb5, 0xed, 0x78,
            0xb6, 0x38, 0xb7, 0xce, 0x53, 0x0d, 0xab, 0xe8, 0x5d, 0xda, 0xb6, 0x14, 0x22, 0x02,
            0x41, 0x80, 0x1d, 0xdf, 0x06, 0x69, 0x24, 0x00, 0x04, 0x00, 0x1c, 0x88, 0x28, 0xf7,
            0x13, 0x73, 0x24, 0xc5, 0x8b, 0x28, 0x04, 0x92, 0x86, 0x24, 0xea, 0x23, 0x26, 0xf1,
            0x67, 0x45, 0x37, 0xc0, 0x62, 0xe2, 0x51, 0xe2, 0x75, 0x3c, 0xa7, 0xfc, 0xca, 0x4c,
            0xc0, 0x01, 0x08, 0x80, 0xd8, 0x00, 0x00, 0x80, 0x24, 0x00, 0x01, 0x00, 0xc5, 0x32,
            0x01, 0x03, 0x9a, 0xdb, 0xa1, 0x4b, 0xe7, 0x1f, 0x88, 0x6d, 0xa1, 0xd8, 0xdb, 0xe9,
            0xee, 0xbd, 0xed, 0x08, 0xcb, 0x11, 0x1b, 0x75, 0x34, 0x00, 0x78, 0x99, 0x9a, 0xa9,
            0xf0, 0x38, 0x24, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x06, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00,
            0x14, 0x00, 0x04, 0x00, 0x02, 0x00, 0x04, 0xd2, 0xc0, 0x5f, 0x05, 0x43, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x09, 0x80, 0x1c, 0x00, 0x00, 0x80,
            0x05, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0xc0, 0x7a, 0x03, 0x1c, 0x00, 0x00, 0x80,
            0x05, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x02, 0x00,
            0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0xc0, 0x7c, 0x00, 0xe4, 0x00, 0x00, 0x80,
            0x24, 0x00, 0x01, 0x00, 0x4e, 0xb3, 0x2f, 0x4a, 0x83, 0xf8, 0x8d, 0x84, 0x25, 0x63,
            0xa4, 0x48, 0xcc, 0x18, 0x1b, 0xb2, 0xc4, 0x2a, 0x63, 0x7b, 0xf1, 0x23, 0x63, 0xe2,
            0xfb, 0x2e, 0xf5, 0x94, 0xe5, 0x96, 0x5d, 0x7d, 0x24, 0x00, 0x02, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x14, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x0c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
            0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x09, 0xa4,
            0x00, 0x00, 0x00, 0x00, 0x26, 0x07, 0x53, 0x00, 0x00, 0x60, 0x06, 0xb0, 0x00, 0x00,
            0x00, 0x00, 0xc0, 0x5f, 0x05, 0x43, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x09, 0x80,
            0x1c, 0x00, 0x00, 0x80, 0x05, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x0a, 0xc0, 0x7a, 0x04,
            0x1c, 0x00, 0x00, 0x80, 0x05, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00,
            0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0xc0, 0xa8, 0x00, 0x00,
        ];
        let genlmsghdr = create_test_genlmsghdr(&payload)?;
        let device = Device::try_from(genlmsghdr.get_attr_handle())?;

        assert_eq!(device, get_device_from_man()?);

        Ok(())
    }

    // Ensure backwards compatability with pre-5.2 kernels. See issue #9 for
    // context on changes to NLA_F_NESTED.
    #[test]
    fn parse_device_example_from_man_page_pre_five_point_two_kernel() -> Result<(), Error> {
        let payload = vec![
            1, 1, 0, 0, 6, 0, 6, 0, 108, 202, 0, 0, 8, 0, 7, 0, 0, 0, 0, 0, 8, 0, 1, 0, 6, 0, 0, 0,
            9, 0, 2, 0, 116, 101, 115, 116, 0, 0, 0, 0, 36, 0, 3, 0, 200, 9, 243, 229, 49, 126,
            149, 117, 201, 181, 237, 120, 182, 56, 183, 206, 83, 13, 171, 232, 93, 218, 182, 20,
            34, 2, 65, 128, 29, 223, 6, 105, 36, 0, 4, 0, 28, 136, 40, 247, 19, 115, 36, 197, 139,
            40, 4, 146, 134, 36, 234, 35, 38, 241, 103, 69, 55, 192, 98, 226, 81, 226, 117, 60,
            167, 252, 202, 76, 192, 1, 8, 0, 216, 0, 0, 0, 36, 0, 1, 0, 197, 50, 1, 3, 154, 219,
            161, 75, 231, 31, 136, 109, 161, 216, 219, 233, 238, 189, 237, 8, 203, 17, 27, 117, 52,
            0, 120, 153, 154, 169, 240, 56, 36, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            12, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 10, 0, 1, 0, 0, 0, 20, 0, 4, 0, 2, 0, 4,
            210, 192, 95, 5, 67, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 9, 0, 28, 0, 0, 0, 5, 0, 3, 0, 32,
            0, 0, 0, 6, 0, 1, 0, 2, 0, 0, 0, 8, 0, 2, 0, 10, 192, 122, 3, 28, 0, 0, 0, 5, 0, 3, 0,
            24, 0, 0, 0, 6, 0, 1, 0, 2, 0, 0, 0, 8, 0, 2, 0, 10, 192, 124, 0, 228, 0, 0, 0, 36, 0,
            1, 0, 78, 179, 47, 74, 131, 248, 141, 132, 37, 99, 164, 72, 204, 24, 27, 178, 196, 42,
            99, 123, 241, 35, 99, 226, 251, 46, 245, 148, 229, 150, 93, 125, 36, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            20, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0,
            12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 10, 0,
            1, 0, 0, 0, 32, 0, 4, 0, 10, 0, 9, 164, 0, 0, 0, 0, 38, 7, 83, 0, 0, 96, 6, 176, 0, 0,
            0, 0, 192, 95, 5, 67, 0, 0, 0, 0, 60, 0, 9, 0, 28, 0, 0, 0, 5, 0, 3, 0, 32, 0, 0, 0, 6,
            0, 1, 0, 2, 0, 0, 0, 8, 0, 2, 0, 10, 192, 122, 4, 28, 0, 0, 0, 5, 0, 3, 0, 16, 0, 0, 0,
            6, 0, 1, 0, 2, 0, 0, 0, 8, 0, 2, 0, 192, 168, 0, 0, 20, 0, 0, 0, 3, 0, 2, 0, 0, 0, 0,
            0, 250, 117, 199, 159, 0, 0, 0, 0,
        ];
        let genlmsghdr = create_test_genlmsghdr(&payload)?;
        let device = Device::try_from(genlmsghdr.get_attr_handle())?;

        assert_eq!(device, get_device_from_man()?);

        Ok(())
    }

    #[test]
    fn parse_device_with_large_peer() -> Result<(), Error> {
        let first_payload = [
            0, 1, 0, 0, 6, 0, 6, 0, 108, 202, 0, 0, 8, 0, 7, 0, 0, 0, 0, 0, 8, 0, 1, 0, 6, 0, 0, 0,
            9, 0, 2, 0, 116, 101, 115, 116, 0, 0, 0, 0, 36, 0, 3, 0, 200, 9, 243, 229, 49, 126,
            149, 117, 201, 181, 237, 120, 182, 56, 183, 206, 83, 13, 171, 232, 93, 218, 182, 20,
            34, 2, 65, 128, 29, 223, 6, 105, 36, 0, 4, 0, 28, 136, 40, 247, 19, 115, 36, 197, 139,
            40, 4, 146, 134, 36, 234, 35, 38, 241, 103, 69, 55, 192, 98, 226, 81, 226, 117, 60,
            167, 252, 202, 76, 60, 14, 8, 0, 56, 14, 0, 0, 36, 0, 1, 0, 197, 50, 1, 3, 154, 219,
            161, 75, 231, 31, 136, 109, 161, 216, 219, 233, 238, 189, 237, 8, 203, 17, 27, 117, 52,
            0, 120, 153, 154, 169, 240, 56, 36, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 0, 0, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            12, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 10, 0, 1, 0, 0, 0, 20, 0, 4, 0, 2, 0, 4,
            210, 192, 95, 5, 67, 0, 0, 0, 0, 0, 0, 0, 0, 156, 13, 9, 0, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 1, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0,
            0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            3, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 40, 0,
            0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 8, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 10, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 15, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 17, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 19, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 24, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 26, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 28, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 33, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 35, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 37, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 42, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 44, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 46, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 51, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 53, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 55, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 58, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 60, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 62, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 64, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 69, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 71, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 73, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 78, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 80, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 40, 0, 0, 0, 5, 0, 3, 0, 128,
            0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 82, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1,
            0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 87,
        ];
        let second_payload = [
            0, 1, 0, 0, 6, 0, 6, 0, 108, 202, 0, 0, 8, 0, 7, 0, 0, 0, 0, 0, 8, 0, 1, 0, 6, 0, 0, 0,
            9, 0, 2, 0, 116, 101, 115, 116, 0, 0, 0, 0, 36, 0, 3, 0, 200, 9, 243, 229, 49, 126,
            149, 117, 201, 181, 237, 120, 182, 56, 183, 206, 83, 13, 171, 232, 93, 218, 182, 20,
            34, 2, 65, 128, 29, 223, 6, 105, 36, 0, 4, 0, 28, 136, 40, 247, 19, 115, 36, 197, 139,
            40, 4, 146, 134, 36, 234, 35, 38, 241, 103, 69, 55, 192, 98, 226, 81, 226, 117, 60,
            167, 252, 202, 76, 8, 10, 8, 0, 4, 10, 0, 0, 36, 0, 1, 0, 197, 50, 1, 3, 154, 219, 161,
            75, 231, 31, 136, 109, 161, 216, 219, 233, 238, 189, 237, 8, 203, 17, 27, 117, 52, 0,
            120, 153, 154, 169, 240, 56, 220, 9, 9, 0, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 40, 0,
            0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10,
            0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 40, 0, 0, 0, 5,
            0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 91, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0,
            20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 93, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0,
            0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            95, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 40, 0,
            0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 98, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10,
            0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 40, 0, 0, 0, 5,
            0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 100, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0,
            20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 101, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 102, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0,
            0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 104, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 40,
            0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0,
            10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 111, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 113, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 115, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0,
            0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 117, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 119,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 40,
            0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0,
            10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 124, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 126, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 128, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0,
            0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 130, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 132,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 40,
            0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0,
            10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 137, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0,
            0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 138, 40, 0, 0, 0, 5, 0,
            3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 139, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20,
            0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 40, 0, 0, 0, 5, 0, 3, 0,
            128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 141, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0,
            0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 143, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0,
            6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 145,
            40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0,
            1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 40,
            0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, 40, 0, 0, 0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0,
            10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 40, 0, 0,
            0, 5, 0, 3, 0, 128, 0, 0, 0, 6, 0, 1, 0, 10, 0, 0, 0, 20, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 150,
        ];

        let genlmsghdr = create_test_genlmsghdr(&first_payload)?;
        let device = Device::try_from(genlmsghdr.get_attr_handle())?;

        let genlmsghdr = create_test_genlmsghdr(&second_payload)?;
        let device = extend_device(device, genlmsghdr.get_attr_handle())?;

        assert_eq!(
            device,
            Device {
                ifindex: 6,
                ifname: "test".to_string(),
                private_key: Some(parse_device_key(&base64::decode(
                    "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk="
                )?)?),
                public_key: Some(parse_device_key(&base64::decode(
                    "HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw="
                )?)?),
                listen_port: 51820,
                fwmark: 0,
                peers: vec![Peer {
                    public_key: parse_device_key(&base64::decode(
                        "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg="
                    )?)?,
                    preshared_key: [0u8; 32],
                    endpoint: Some("192.95.5.67:1234".parse()?),
                    persistent_keepalive_interval: 0,
                    last_handshake_time: Duration::new(0, 0),
                    rx_bytes: 0,
                    tx_bytes: 0,
                    allowed_ips: (1..=150)
                        .step_by(1)
                        .map(|h| AllowedIp {
                            family: libc::AF_INET6 as u16,
                            ipaddr: IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, h)),
                            cidr_mask: 128,
                        })
                        .collect(),
                    protocol_version: 1,
                }]
            }
        );

        Ok(())
    }
}