]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOSX/mdns_objects/mdns_tlv.c
mDNSResponder-1310.40.42.tar.gz
[apple/mdnsresponder.git] / mDNSMacOSX / mdns_objects / mdns_tlv.c
1 /*
2 * Copyright (c) 2020 Apple Inc. 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 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "mdns_tlv.h"
18
19 #include <CoreUtils/CoreUtils.h>
20
21 //======================================================================================================================
22 // MARK: - Type-Length Headers
23
24 typedef struct
25 {
26 uint8_t type[2];
27 uint8_t length[2];
28 } mdns_tl16_t;
29
30 check_compile_time(sizeof(mdns_tl16_t) == 4);
31
32 //======================================================================================================================
33 // MARK: - Local Prototypes
34
35 static uint16_t
36 _mdns_tl16_get_type(const mdns_tl16_t *tl);
37
38 static uint16_t
39 _mdns_tl16_get_length(const mdns_tl16_t *tl);
40
41 static void
42 _mdns_tl16_init(mdns_tl16_t *tl, uint16_t type, uint16_t length);
43
44 //======================================================================================================================
45 // MARK: - Public Functions
46
47 OSStatus
48 mdns_tlv16_get_value(const uint8_t * const start, const uint8_t * const end, const uint16_t type,
49 size_t * const out_length, const uint8_t ** const out_value, const uint8_t ** const out_ptr)
50 {
51 OSStatus err;
52 require_action_quiet(start <= end, exit, err = kRangeErr);
53
54 const uint8_t *ptr = start;
55 while ((end - ptr) > 0) {
56 const mdns_tl16_t *tl;
57 require_action_quiet((end - ptr) >= (ptrdiff_t)sizeof(*tl), exit, err = kUnderrunErr);
58
59 tl = (const mdns_tl16_t *)ptr;
60 const uint16_t tlv_type = _mdns_tl16_get_type(tl);
61 const uint16_t tlv_length = _mdns_tl16_get_length(tl);
62 const uint8_t * const tlv_value = (const uint8_t *)&tl[1];
63 require_action_quiet((end - tlv_value) >= tlv_length, exit, err = kUnderrunErr);
64
65 ptr = &tlv_value[tlv_length];
66 if (tlv_type == type) {
67 if (out_length) {
68 *out_length = tlv_length;
69 }
70 if (out_value) {
71 *out_value = tlv_value;
72 }
73 if (out_ptr) {
74 *out_ptr = ptr;
75 }
76 return kNoErr;
77 }
78 }
79 err = kNotFoundErr;
80
81 exit:
82 return err;
83 }
84
85 //======================================================================================================================
86
87 OSStatus
88 mdns_tlv16_set(uint8_t * const dst, const uint8_t * const limit, const uint16_t type, const uint16_t length,
89 const uint8_t * const value, uint8_t ** const out_end)
90 {
91 OSStatus err;
92 mdns_tl16_t *tl;
93 require_action_quiet(!limit || ((limit - dst) >= (ptrdiff_t)(sizeof(tl) + length)), exit, err = kUnderrunErr);
94
95 tl = (mdns_tl16_t *)dst;
96 _mdns_tl16_init(tl, type, length);
97 uint8_t * const dst_value = (uint8_t *)&tl[1];
98 if (length > 0) {
99 memcpy(dst_value, value, length);
100 }
101 if (out_end) {
102 *out_end = &dst_value[length];
103 }
104 err = kNoErr;
105
106 exit:
107 return err;
108 }
109
110 //======================================================================================================================
111
112 size_t
113 mdns_tlv16_get_required_length(const uint16_t value_length)
114 {
115 return (sizeof(mdns_tl16_t) + value_length);
116 }
117
118 //======================================================================================================================
119 // MARK: - Private Functions
120
121 static uint16_t
122 _mdns_tl16_get_type(const mdns_tl16_t * const tl)
123 {
124 return ReadBig16(tl->type);
125 }
126
127 //======================================================================================================================
128
129 static uint16_t
130 _mdns_tl16_get_length(const mdns_tl16_t * const tl)
131 {
132 return ReadBig16(tl->length);
133 }
134
135 //======================================================================================================================
136
137 static void
138 _mdns_tl16_init(mdns_tl16_t * const tl, const uint16_t type, const uint16_t length)
139 {
140 WriteBig16(tl->type, type);
141 WriteBig16(tl->length, length);
142 }