/src/wireshark/wsutil/inet_cidr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ipv4.c |
2 | | * |
3 | | * Wireshark - Network traffic analyzer |
4 | | * By Gerald Combs <gerald@wireshark.org> |
5 | | * Copyright 1998 Gerald Combs |
6 | | * |
7 | | * SPDX-License-Identifier: GPL-2.0-or-later |
8 | | */ |
9 | | |
10 | | #include "inet_cidr.h" |
11 | | |
12 | | |
13 | | uint32_t |
14 | | ws_ipv4_get_subnet_mask(const uint32_t mask_length) |
15 | 130k | { |
16 | 130k | static const uint32_t masks[33] = { |
17 | 130k | 0x00000000, |
18 | 130k | 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, |
19 | 130k | 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, |
20 | 130k | 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, |
21 | 130k | 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, |
22 | 130k | 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, |
23 | 130k | 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, |
24 | 130k | 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, |
25 | 130k | 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff, |
26 | 130k | }; |
27 | | |
28 | 130k | ws_assert(mask_length <= 32); |
29 | | |
30 | 130k | return masks[mask_length]; |
31 | 130k | } |
32 | | |
33 | | static int |
34 | | compare_ipv4(const ipv4_addr_and_mask *a, const ipv4_addr_and_mask *b) |
35 | 0 | { |
36 | 0 | uint32_t addr_a, addr_b, nmask; |
37 | |
|
38 | 0 | nmask = MIN(a->nmask, b->nmask); |
39 | 0 | addr_a = a->addr & nmask; |
40 | 0 | addr_b = b->addr & nmask; |
41 | 0 | if (addr_a < addr_b) |
42 | 0 | return -1; |
43 | 0 | if (addr_a > addr_b) |
44 | 0 | return 1; |
45 | 0 | return 0; |
46 | 0 | } |
47 | | |
48 | | void |
49 | | ws_ipv4_addr_and_mask_init(ipv4_addr_and_mask *dst, ws_in4_addr src_addr, int src_bits) |
50 | 129k | { |
51 | 129k | dst->addr = g_ntohl(src_addr); |
52 | 129k | dst->nmask = ws_ipv4_get_subnet_mask(src_bits); |
53 | 129k | } |
54 | | |
55 | | bool |
56 | | ws_ipv4_addr_and_mask_contains(const ipv4_addr_and_mask *ipv4, const ws_in4_addr *in_addr) |
57 | 0 | { |
58 | 0 | ipv4_addr_and_mask addr_and_mask; |
59 | |
|
60 | 0 | addr_and_mask.addr = g_ntohl(*in_addr); |
61 | 0 | addr_and_mask.nmask = ws_ipv4_get_subnet_mask(32); |
62 | 0 | return compare_ipv4(ipv4, &addr_and_mask) == 0; |
63 | 0 | } |
64 | | |
65 | | static const uint8_t bitmasks[9] = |
66 | | { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; |
67 | | |
68 | | static int |
69 | | compare_ipv6(const ipv6_addr_and_prefix *a, const ipv6_addr_and_prefix *b) |
70 | 0 | { |
71 | 0 | uint32_t prefix; |
72 | 0 | int pos = 0; |
73 | |
|
74 | 0 | prefix = MIN(a->prefix, b->prefix); /* MIN() like IPv4 */ |
75 | 0 | prefix = MIN(prefix, 128); /* sanitize, max prefix is 128 */ |
76 | |
|
77 | 0 | while (prefix >= 8) { |
78 | 0 | int byte_a = (int) (a->addr.bytes[pos]); |
79 | 0 | int byte_b = (int) (b->addr.bytes[pos]); |
80 | |
|
81 | 0 | if (byte_a != byte_b) { |
82 | 0 | return byte_a - byte_b; |
83 | 0 | } |
84 | | |
85 | 0 | prefix -= 8; |
86 | 0 | pos++; |
87 | 0 | } |
88 | | |
89 | 0 | if (prefix != 0) { |
90 | 0 | int byte_a = (int) (a->addr.bytes[pos] & (bitmasks[prefix])); |
91 | 0 | int byte_b = (int) (b->addr.bytes[pos] & (bitmasks[prefix])); |
92 | |
|
93 | 0 | if (byte_a != byte_b) { |
94 | 0 | return byte_a - byte_b; |
95 | 0 | } |
96 | 0 | } |
97 | | |
98 | 0 | return 0; |
99 | 0 | } |
100 | | |
101 | | |
102 | | bool |
103 | | ws_ipv6_addr_and_prefix_contains(const ipv6_addr_and_prefix *ipv6, const ws_in6_addr *in_addr) |
104 | 0 | { |
105 | 0 | ipv6_addr_and_prefix addr_and_mask; |
106 | |
|
107 | 0 | addr_and_mask.addr = *in_addr; |
108 | 0 | addr_and_mask.prefix = 128; |
109 | 0 | return compare_ipv6(ipv6, &addr_and_mask) == 0; |
110 | 0 | } |