Skip to main content

c/
ns_parse.rs

1// Parsing of DNS messages for the ns_* API from <arpa/nameser.h>.
2
3pub const NS_MAXDNAME_V: usize = 1025;
4const NS_INT16SZ_V: usize = 2;
5const NS_INT32SZ_V: usize = 4;
6const NS_S_MAX_V: usize = 4;
7
8#[repr(C)]
9pub struct NsMsg {
10    pub _msg: *const u8,
11    pub _eom: *const u8,
12    pub _id: u16,
13    pub _flags: u16,
14    pub _counts: [u16; NS_S_MAX_V],
15    pub _sections: [*const u8; NS_S_MAX_V],
16    pub _sect: c_int,
17    pub _rrnum: c_int,
18    pub _msg_ptr: *const u8,
19}
20
21#[repr(C)]
22pub struct NsRr {
23    pub name: [c_char; NS_MAXDNAME_V],
24    pub type_: u16,
25    pub rr_class: u16,
26    pub ttl: u32,
27    pub rdlength: u16,
28    __pad: u16,
29    pub rdata: *const u8,
30}
31
32#[no_mangle]
33pub static _ns_flagdata: [[c_int; 2]; 16] = [
34    [0x8000, 15],
35    [0x7800, 11],
36    [0x0400, 10],
37    [0x0200, 9],
38    [0x0100, 8],
39    [0x0080, 7],
40    [0x0040, 6],
41    [0x0020, 5],
42    [0x0010, 4],
43    [0x000f, 0],
44    [0x0000, 0],
45    [0x0000, 0],
46    [0x0000, 0],
47    [0x0000, 0],
48    [0x0000, 0],
49    [0x0000, 0],
50];
51
52unsafe fn ns_skiprr_inner(ptr: *const u8, eom: *const u8, section: c_int, mut count: c_int) -> c_int {
53    let mut p = ptr;
54    while count > 0 {
55        count -= 1;
56        let r = dn_skipname(p, eom);
57        if r < 0 { return -1; }
58        if r as usize + 2 * NS_INT16SZ_V > eom as usize - p as usize { return -1; }
59        p = p.add(r as usize + 2 * NS_INT16SZ_V);
60        if section != 0 {
61            if NS_INT32SZ_V + NS_INT16SZ_V > eom as usize - p as usize { return -1; }
62            p = p.add(NS_INT32SZ_V);
63            let rdlen = ns_get16(p) as usize;
64            p = p.add(NS_INT16SZ_V);
65            if rdlen > eom as usize - p as usize { return -1; }
66            p = p.add(rdlen);
67        }
68    }
69    (p as usize - ptr as usize) as c_int
70}
71
72#[no_mangle]
73pub unsafe extern "C" fn ns_skiprr(ptr: *const u8, eom: *const u8, section: c_int, count: c_int) -> c_int {
74    let r = ns_skiprr_inner(ptr, eom, section, count);
75    if r < 0 { ERRNO = 90; } // EMSGSIZE
76    r
77}
78
79#[no_mangle]
80pub unsafe extern "C" fn ns_initparse(msg: *const u8, msglen: c_int, handle: *mut NsMsg) -> c_int {
81    if msg.is_null() || handle.is_null() || msglen < 0 {
82        ERRNO = 90;
83        return -1;
84    }
85    (*handle)._msg = msg;
86    (*handle)._eom = msg.add(msglen as usize);
87    if (msglen as usize) < (2 + NS_S_MAX_V) * NS_INT16SZ_V {
88        ERRNO = 90;
89        return -1;
90    }
91    let mut p = msg;
92    (*handle)._id = ns_get16(p) as u16;
93    p = p.add(2);
94    (*handle)._flags = ns_get16(p) as u16;
95    p = p.add(2);
96    for i in 0..NS_S_MAX_V {
97        (*handle)._counts[i] = ns_get16(p) as u16;
98        p = p.add(2);
99    }
100    for i in 0..NS_S_MAX_V {
101        if (*handle)._counts[i] != 0 {
102            (*handle)._sections[i] = p;
103            let r = ns_skiprr_inner(p, (*handle)._eom, i as c_int, (*handle)._counts[i] as c_int);
104            if r < 0 {
105                ERRNO = 90;
106                return -1;
107            }
108            p = p.add(r as usize);
109        } else {
110            (*handle)._sections[i] = core::ptr::null();
111        }
112    }
113    if p != (*handle)._eom {
114        ERRNO = 90;
115        return -1;
116    }
117    (*handle)._sect = NS_S_MAX_V as c_int;
118    (*handle)._rrnum = -1;
119    (*handle)._msg_ptr = core::ptr::null();
120    0
121}
122
123#[no_mangle]
124pub unsafe extern "C" fn ns_name_uncompress(
125    msg: *const u8,
126    eom: *const u8,
127    src: *const u8,
128    dst: *mut c_char,
129    dstsiz: usize,
130) -> c_int {
131    let r = crate::dn_expand(msg, eom, src, dst, dstsiz as c_int);
132    if r < 0 { ERRNO = 90; }
133    r
134}
135
136#[no_mangle]
137pub unsafe extern "C" fn ns_parserr(handle: *mut NsMsg, section: c_int, rrnum_in: c_int, rr: *mut NsRr) -> c_int {
138    if handle.is_null() || rr.is_null() || section < 0 || section >= NS_S_MAX_V as c_int {
139        ERRNO = 19; // ENODEV
140        return -1;
141    }
142    let sec = section as usize;
143    if section != (*handle)._sect {
144        (*handle)._sect = section;
145        (*handle)._rrnum = 0;
146        (*handle)._msg_ptr = (*handle)._sections[sec];
147    }
148    let mut rrnum = rrnum_in;
149    if rrnum == -1 { rrnum = (*handle)._rrnum; }
150    if rrnum < 0 || rrnum >= (*handle)._counts[sec] as c_int {
151        ERRNO = 19;
152        return -1;
153    }
154    if rrnum < (*handle)._rrnum {
155        (*handle)._rrnum = 0;
156        (*handle)._msg_ptr = (*handle)._sections[sec];
157    }
158    if rrnum > (*handle)._rrnum {
159        let r = ns_skiprr_inner(
160            (*handle)._msg_ptr,
161            (*handle)._eom,
162            section,
163            rrnum - (*handle)._rrnum,
164        );
165        if r < 0 {
166            ERRNO = 90;
167            return -1;
168        }
169        (*handle)._msg_ptr = (*handle)._msg_ptr.add(r as usize);
170        (*handle)._rrnum = rrnum;
171    }
172    let r = ns_name_uncompress(
173        (*handle)._msg,
174        (*handle)._eom,
175        (*handle)._msg_ptr,
176        (*rr).name.as_mut_ptr(),
177        NS_MAXDNAME_V,
178    );
179    if r < 0 { return -1; }
180    (*handle)._msg_ptr = (*handle)._msg_ptr.add(r as usize);
181    if 2 * NS_INT16SZ_V > (*handle)._eom as usize - (*handle)._msg_ptr as usize {
182        ERRNO = 90;
183        return -1;
184    }
185    (*rr).type_ = ns_get16((*handle)._msg_ptr) as u16;
186    (*handle)._msg_ptr = (*handle)._msg_ptr.add(2);
187    (*rr).rr_class = ns_get16((*handle)._msg_ptr) as u16;
188    (*handle)._msg_ptr = (*handle)._msg_ptr.add(2);
189    if section != 0 {
190        if NS_INT32SZ_V + NS_INT16SZ_V > (*handle)._eom as usize - (*handle)._msg_ptr as usize {
191            ERRNO = 90;
192            return -1;
193        }
194        (*rr).ttl = ns_get32((*handle)._msg_ptr) as u32;
195        (*handle)._msg_ptr = (*handle)._msg_ptr.add(4);
196        (*rr).rdlength = ns_get16((*handle)._msg_ptr) as u16;
197        (*handle)._msg_ptr = (*handle)._msg_ptr.add(2);
198        if (*rr).rdlength as usize > (*handle)._eom as usize - (*handle)._msg_ptr as usize {
199            ERRNO = 90;
200            return -1;
201        }
202        (*rr).rdata = (*handle)._msg_ptr;
203        (*handle)._msg_ptr = (*handle)._msg_ptr.add((*rr).rdlength as usize);
204    } else {
205        (*rr).ttl = 0;
206        (*rr).rdlength = 0;
207        (*rr).rdata = core::ptr::null();
208    }
209    (*handle)._rrnum += 1;
210    if (*handle)._rrnum > (*handle)._counts[sec] as c_int {
211        (*handle)._sect = section + 1;
212        if (*handle)._sect == NS_S_MAX_V as c_int {
213            (*handle)._rrnum = -1;
214            (*handle)._msg_ptr = core::ptr::null();
215        } else {
216            (*handle)._rrnum = 0;
217        }
218    }
219    0
220}