Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "utils/s2n_rfc5952.h"
17 : :
18 : : #include <stdio.h>
19 : : #include <sys/socket.h>
20 : : #include <sys/types.h>
21 : :
22 : : #include "error/s2n_errno.h"
23 : : #include "utils/s2n_safety.h"
24 : :
25 : : static uint8_t dec[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
26 : : static uint8_t hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
27 : :
28 : : S2N_RESULT s2n_inet_ntop(int af, const void *addr, struct s2n_blob *dst)
29 : 12 : {
30 : 12 : const uint8_t *bytes = addr;
31 : 12 : uint8_t *cursor = dst->data;
32 : :
33 [ + + ]: 12 : if (af == AF_INET) {
34 [ # # ][ - + ]: 4 : RESULT_ENSURE(dst->size >= sizeof("111.222.333.444"), S2N_ERR_SIZE_MISMATCH);
35 : :
36 [ + + ]: 20 : for (int i = 0; i < 4; i++) {
37 [ + + ]: 16 : if (bytes[i] / 100) {
38 : 11 : *cursor++ = dec[bytes[i] / 100];
39 : 11 : }
40 [ + + ]: 16 : if (bytes[i] >= 10) {
41 : 11 : *cursor++ = dec[(bytes[i] % 100) / 10];
42 : 11 : }
43 : 16 : *cursor++ = dec[(bytes[i] % 10)];
44 : 16 : *cursor++ = '.';
45 : 16 : }
46 : :
47 : 4 : *--cursor = '\0';
48 : :
49 : 4 : return S2N_RESULT_OK;
50 : 4 : }
51 : :
52 [ + + ]: 8 : if (af == AF_INET6) {
53 [ # # ][ - + ]: 7 : RESULT_ENSURE(dst->size >= sizeof("1111:2222:3333:4444:5555:6666:7777:8888"), S2N_ERR_SIZE_MISMATCH);
54 : :
55 : : /* See Section 4 of RFC5952 for the rules we are going to follow here
56 : : *
57 : : * Here's the general algorithm:
58 : : *
59 : : * 1/ Treat the bytes as 8 16-bit fields
60 : : * 2/ Find the longest run of 16-bit fields.
61 : : * 3/ or if there are two or more equal length longest runs, go with the left-most run
62 : : * 4/ Make that run ::
63 : : * 5/ Print the remaining 16-bit fields in lowercase hex, no leading zeroes
64 : : */
65 : :
66 : 7 : uint16_t octets[8] = { 0 };
67 : :
68 : 7 : int longest_run_start = 0;
69 : 7 : int longest_run_length = 0;
70 : 7 : int current_run_length = 0;
71 : :
72 : : /* 2001:db8::1:0:0:1 */
73 : :
74 : : /* Find the longest run of zeroes */
75 [ + + ]: 63 : for (int i = 0; i < 8; i++) {
76 : 56 : octets[i] = (bytes[i * 2] << 8) + bytes[(i * 2) + 1];
77 : :
78 [ + + ]: 56 : if (octets[i]) {
79 : 20 : current_run_length = 0;
80 : 36 : } else {
81 : 36 : current_run_length++;
82 : 36 : }
83 : :
84 [ + + ]: 56 : if (current_run_length > longest_run_length) {
85 : 34 : longest_run_length = current_run_length;
86 : 34 : longest_run_start = (i - current_run_length) + 1;
87 : 34 : }
88 : 56 : }
89 : :
90 [ + + ]: 36 : for (int i = 0; i < 8; i++) {
91 [ + + ][ + + ]: 29 : if (i == longest_run_start && longest_run_length > 1) {
92 [ + + ]: 6 : if (i == 0) {
93 : 3 : *cursor++ = ':';
94 : 3 : }
95 : :
96 [ + + ]: 6 : if (longest_run_length == 8) {
97 : 1 : *cursor++ = ':';
98 : 1 : }
99 : :
100 : 6 : i += longest_run_length - 1;
101 : :
102 : 23 : } else {
103 : 23 : uint8_t nibbles[4] = { (octets[i] & 0xF000) >> 12,
104 : 23 : (octets[i] & 0x0F00) >> 8,
105 : 23 : (octets[i] & 0x00F0) >> 4,
106 : 23 : (octets[i] & 0x000F) };
107 : :
108 : : /* Skip up to three leading zeroes */
109 : 23 : int j = 0;
110 [ + + ]: 72 : for (j = 0; j < 3; j++) {
111 [ + + ]: 57 : if (nibbles[j]) {
112 : 8 : break;
113 : 8 : }
114 : 57 : }
115 : :
116 [ + + ]: 66 : for (; j < 4; j++) {
117 : 43 : *cursor++ = hex[nibbles[j]];
118 : 43 : }
119 : 23 : }
120 : :
121 : 29 : *cursor++ = ':';
122 : 29 : }
123 : :
124 : 7 : *--cursor = '\0';
125 : :
126 : 7 : return S2N_RESULT_OK;
127 : 7 : }
128 : :
129 [ + - ]: 1 : RESULT_BAIL(S2N_ERR_INVALID_ARGUMENT);
130 : 1 : }
|