1
/* Copyright (c) 2007-2010 Sam Trenholme
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
15
* This software is provided 'as is' with no guarantees of correctness or
16
* fitness for purpose.
19
/* Make sure a dw_str object is sane.
20
* Input: Pointer to dw_str
21
* Output: 0 if sane; -1 if not */
22
int dw_assert_sanity(dw_str *object);
24
/* Create a new dw_str object.
25
* Input: Maximum length allowed for the string
26
* Output: Pointer to newly created string
28
dw_str *dw_create(uint32_t size);
30
/* Destroy a dw_str object.
31
* Input: Pointer to string to destroy
32
* Output: 0 on success; -1 on failure
34
int dw_destroy(dw_str *object);
36
/* Add a single character to the DwStr */
37
int dw_addchar(uint8_t add, dw_str *object);
39
/* Add a C-string (which may have NULL characters) to a DwStr object.
40
* Input: Pointer to string; number of characters we will add to DwStr
41
* object; pointer to dw_str object. Output: -1 on error; 0 on success */
42
int dw_cstr_append(uint8_t *add, int32_t len, dw_str *obj);
44
/* Add a null-terminated string to a DwStr; should the null-terminated string
45
* have the character specified in 'nope', don't append that character and
46
* stop appending to the string. Input: String to append; DwStr to append
47
* to; 'nope' character we're not allowed to add (make this 0 if you want
48
* to allow all non-NULL characters) */
49
int dw_qrappend(uint8_t *add, dw_str *object, char nope);
51
/* Add an arbitrary binary string of length "len" to a DwStr object */
52
int dw_bin_append(uint8_t *add, int len, dw_str *object);
54
/* Add a null-terminated string to a DwStr; if the DwStr is non-0 length,
55
* first add a comma. If the null-terminated string has a comma, stop
56
* appending the string.
57
* Input: C string to add; DwStr to add string to
58
* Output: 0 on success; -1 on failure */
59
int dw_qspush(uint8_t *add, dw_str *object);
61
/* For debug purposes: Output a dw_str object on the standard output. */
62
void dw_stdout(dw_str *object);
64
/* Take some of, or all, of a dw_str, and copy it in to a new dw_str object.
65
* return 0 (NULL) if there is an error copying the string. The parameters
67
* 1) The dw_string we want to copy
68
* 2) The first character we starting copying from. If this value has
69
* a value of 0, then we start copying from the start of the
70
* string. If this has a value of -1, then we start copying at
71
* the end of the string (meaning, we can only copy the very last
72
* character). -2 is the second-to-last character in the string; 1 is
73
* the second character in the string (c indexes, ugh)
74
* 3) The number of characters we copy. 0 means no characters (making
75
* a zero-length string); 1 means 1 character, etc. If this is negative
76
* then we copy relative to the end of the string. In other words, if
77
* the length has a value of -1, we copy until the end of the string;
78
* if length has a value of -2, we copy until the second to last character
80
* 4) The maximum allowed length for the string. Should this have a positive
81
* value or 0, the string is allowed to add that many characters to the end
82
* of the string (0: The string can not grow; 1: the string can grow by
83
* one character, etc). If it has a value of -1, then the string has the
84
* same maximum permitted size as the string we are copying. Otherwise,
87
* Output: We create a new dw_str object, which has the copied substr.
89
* Some common parameters: dw_substr(str,0,-1,-1): Copies the entire string
92
dw_str *dw_substr(dw_str *obj, int32_t begin, int32_t amount, int32_t max);
94
/* Read a 16-bit big-endian string that is in a dw_str as a number. DNS
95
* commonly has these kinds of numbers (can you say 1983?)
96
* Input: Pointer to dw_str object; offset where we will look for number
97
* (0 is top of string; -1 is last two bytes of string)
98
* Output: The number; -1 on error */
99
int32_t dw_fetch_u16(dw_str *object, int32_t offset);
101
/* Read a 16-bit big-endian number at the end of a dw_str object, and
102
* remove the string from the string object. -1 on error */
103
int32_t dw_pop_u16(dw_str *object);
105
/* Read an 8-bit number at the end of a dw_str object, and
106
* remove the string from the string object. -1 on error */
107
int32_t dw_pop_u8(dw_str *object);
109
/* Read an 8-bit big-endian string that is in a dw_str as a number.
110
* Input: Pointer to dw_str object; offset where we will look for number
111
* (0 is top of string)
112
* Output: The number; -1 on error */
113
int32_t dw_fetch_u8(dw_str *object, int32_t offset);
115
/* Put a 16-bit big-endian number (the argument "value") in a dw_str object.
116
* Offset can be either a positive or negative number; should offset be
117
* a positive number, then we put that byte in that many bytes from
118
* the beginning of the string. Should offset be a negative number, then
119
* we put the number that many bytes from the end of the string. This
120
* function will, in certain cases make the string one or two bytes longer.
121
* If offset is -1, then the number is added to the end of the string.
122
* If offset is -2, then the number replaces the last byte of the string,
123
* and adds a byte the the end of the string. Should offset be 0, the
124
* number replaces the first two numbers in the string (adding numbers
127
* Should this function succeed, it will return a 0. Otherwise, it
128
* will return a -1 */
129
int dw_put_u16(dw_str *obj, uint16_t value, int32_t offset);
131
/* Put an 8-bit (the argument "value") in a dw_str object.
132
* Offset can be either a positive or negative number; should offset be
133
* a positive number, then we put that byte in that many bytes from
134
* the beginning of the string. Should offset be a negative number, then
135
* we put the number that many bytes from the end of the string. This
136
* function will, in certain cases make the string one byte longer.
137
* If offset is -1, then the number is added to the end of the string.
139
* Should offset be 0, the number replaces the first number in the string
140
* (adding numbers if needed)
142
* Should this function succeed, it will return a 0. Otherwise, it
145
int dw_put_u8(dw_str *obj, uint8_t value, int32_t offset);
148
/* Read a single bit from a dw_str object. The way we choose the bit is
149
* to first choose the byte with the desired bit, then to choose the
150
* bit in that byte. 0 is the least significant (rightmost) bit; 7 is the
151
* most significant bit.
152
* We return -1 on error, 0 if the bit is 0, and 1 if the bit is 1 */
153
int dw_get_bit(dw_str *obj, int32_t byte, int8_t bit);
154
#endif /* OTHER_STUFF */
156
/* Compare two dw_string objects to see if they are the same (different max
157
* lengths are allowed). -1 on error, 0 if not the same, and 1 if they are
159
int dw_issame(dw_str *a, dw_str *b);
161
/* Append one dw_string object to another dw_string.
162
* Input: The two dw_string objects
163
* Output: 0 on success, -1 on error */
164
int dw_append(dw_str *toappend, dw_str *target);
166
/* Append a substring of one dw_string object to another dw_string.
167
* Input: String we splice from, where we start cutting from that string,
168
* how many bytes to cut from said string, the string to append to
169
* Output: 0 on success, -1 on error
171
int dw_substr_append(dw_str *splice, int32_t begin, int32_t amount,
174
/* Copy a dw_string object in to a null-terminated C-string.
175
* Input: The string to convert
176
* Output: A pointer to a newly created C-string; 0 on error */
178
uint8_t *dw_to_cstr(dw_str *obj);
180
/* Find the last instance of a given character in a DwStr object.
181
* Input: The dw_str object, the character we are seeking
182
* Output: The index in the string with the character in question
183
* -1 on error; -2 on "not found"
186
int32_t dw_rfind(dw_str *obj, unsigned char rx);
188
/* Take the last element of a comma-separated DwStr object, remove it
189
* from said string, and create a new string with the popped comma-separated
190
* object. Should the source string not have a comma in it, then we take
191
* the entire source string, blank it (make it 0-length) and copy it over
192
* to the newly created string. The final comma is removed from the
193
* source string, but is *not* included in the destination string.
194
* Input: The source string
195
* Output: A newly created string with the last comma separated object */
197
dw_str *dw_qspop(dw_str *in);
199
/* Create a copy of a dw_str object with any leading whitespace in the
200
* original object removed in the copy. If the original is nothing
201
* but whitespace, the copy will be a 0-length string.
202
* Input: dw_str object we want to remove leading whitespace from
203
* Output: Newly created dw_str object without the leading whitespace */
205
dw_str *dw_zap_lws(dw_str *obj);
207
/* Convert a dw_str object with a number in to an integer. Leading
208
* whitespace is ignored; anything that is not a number or letter stops
211
* obj: The dw_str object we convert in to a number
212
* index: How far in to the string we begin conversion (0 is
213
* beginning of string)
214
* base: The base we work in (2 is binary, 10 is decimal, 16 is
215
* hex; this can be up to 36)
217
* The number the string represents; -1 on error
220
int32_t dw_atoi(dw_str *obj, int32_t index, int base);
222
/* This extracts just a DNS DNAME (without TYPE) from a raw c-string (with
223
* ASCII nulls, since DNS packets have those) and puts it in a newly
225
* Input: Pointer to raw string; offset where we look for DNS DNAME,
226
* maximum length of raw string
227
* Output: A pointer to a new dw_str with NAME
229
dw_str *dw_get_dname(uint8_t *raw, int offset, int max);
231
/* This extracts a DNS DNAME, followed by a two-byte TYPE (the type of RR)
232
* from a raw c-string (with ASCII nulls, since DNS packets have those)
233
* and puts it in a newly created offset.
234
* Input: Pointer to raw string; offset where we look for DNS DNAME + CLASS,
235
* maximum length of raw string
236
* Output: A pointer to a new dw_str with NAME + CLASS
238
dw_str *dw_get_dname_type(uint8_t *raw, int offset, int max);
240
/* Given a raw pointer to a c-string (which can have NULLs), and a length
241
* for that string, extract a dw_str object that is a cachable form of
242
* the packet. Basically:
243
* * Everything after the question is put at the beginning
245
* * This is followed by, in order, ancount, nscount, then
249
dw_str *dw_packet_to_cache(uint8_t *raw, int len, uint8_t type);
251
/* Get a TTL that is buried in a DNS string. We start at the beginning of
252
* the DNS name, figure out how long the name is (ugh), then skip past
253
* type and class to get the TTL; return -1 on error. We don't support
254
* TTLs longer than 31,536,000: One year (0x01E13380)
256
* Input: String we will get TTL from; offset from where we will get TTL,
257
* maximum allowed TTL (which should be 31536000 when called from
258
* another part of Deadwood), recursion depth (to stop infinite loops)
259
* Note that depth is a positive number that decrements.
261
int32_t dw_get_a_dnsttl(dw_str *in, int offset, int32_t max, int depth);
263
/* Make sure a filename is sanitized; only lowercase letters, the '_',
264
* the '-', and the '/' are allowed in file names; anything else becomes
266
int dw_filename_sanitize(dw_str *obj);
268
/* Given a packet in the form put in the DNS cache (with things like type,
269
* ancount, nscount, and arcount at the end of the string), tell the user how
270
* many answers are in the packet. */
271
int32_t dw_cachepacket_to_ancount(dw_str *packet);
273
/* See if a given ASCII name ends in a '.'; if it doesn't return -1, if
274
* there is an unexpected error, return 0, and if it does end with '.', return
276
int dw_ends_in_dot(dw_str *in);
278
/* Convert an ASCII name, like "www.samiam.org." in to the DNS form of the
279
* same name (\003www\006samiam\003org\000). Output, as a new string, the
280
* newly created DNS string; 0 if there is any error */
281
dw_str *dw_dnsname_convert(dw_str *in);
283
/* Chop off the first label of a DNS name; for example, the raw DNS form
284
* of www.example.com. (\003www\007example\003com\000) becomes example.com
285
* (\007example\003com\000). This will also work with strings having data
286
* after the end of the DNS name.
288
* This function creates a new string which needs to be freed by its caller
290
dw_str *dw_dnslabel_chop(dw_str *in);
292
/* Determine where the end of a <domain-name> at offset in the string
293
* is (ugh, DNS is ugly); -1 on error */
294
int32_t dw_get_dn_end(dw_str *in, int offset);
296
/* Rotate data in a string: Given a start point and a pivot point, take all of
297
* the string between the pivot point to the end, and put it where the start
298
* point is. Take all the data from the start point to the pivot point, and
299
* put it at the end of the string.
301
* For example, if we have the string "0123456789", and the start is 3, and
302
* the pivot 5, we would have the string "0125678934" after running
305
int dw_rotate(dw_str *in, int32_t start, int32_t pivot, int32_t end);