MSWSP: add ids for another unknown Property Set
[wireshark-wip.git] / epan / dissectors / packet-smb-common.c
blob0d77f6b98724b6046f5d7312c5af0a03a53ada17
1 /* packet-smb-common.c
2 * Common routines for smb packet dissection
3 * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-pop.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/wmem/wmem.h>
34 #include <epan/strutil.h>
35 #include "packet-smb-common.h"
37 #include "packet-dns.h"
40 * Share type values - used in LANMAN and in SRVSVC.
42 * XXX - should we dissect share type values, at least in SRVSVC, as
43 * a subtree with bitfields, as the 0x80000000 bit appears to be a
44 * hidden bit, with some number of bits at the bottom being the share
45 * type?
47 * Does LANMAN use that bit?
49 const value_string share_type_vals[] = {
50 {0, "Directory tree"},
51 {1, "Printer queue"},
52 {2, "Communications device"},
53 {3, "IPC"},
54 {0x80000000, "Hidden Directory tree"},
55 {0x80000001, "Hidden Printer queue"},
56 {0x80000002, "Hidden Communications device"},
57 {0x80000003, "Hidden IPC"},
58 {0, NULL}
61 int display_ms_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
63 char *str;
64 gint len;
66 /* display a string from the tree and return the new offset */
68 str = tvb_get_stringz(wmem_packet_scope(), tvb, offset, &len);
69 proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
71 /* Return a copy of the string if requested */
73 if (data)
74 *data = str;
76 return offset+len;
80 int display_unicode_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index, char **data)
82 char *str, *p;
83 int len;
84 int charoffset;
85 guint16 character;
87 /* display a unicode string from the tree and return new offset */
90 * Get the length of the string.
91 * XXX - is it a bug or a feature that this will throw an exception
92 * if we don't find the '\0'? I think it's a feature.
94 len = 0;
95 while (tvb_get_letohs(tvb, offset + len) != '\0')
96 len += 2;
97 len += 2; /* count the '\0' too */
100 * Allocate a buffer for the string; "len" is the length in
101 * bytes, not the length in characters.
103 str = (char *)wmem_alloc(wmem_packet_scope(), len/2);
106 * XXX - this assumes the string is just ISO 8859-1; we need
107 * to better handle multiple character sets in Wireshark,
108 * including Unicode/ISO 10646, and multiple encodings of
109 * that character set (UCS-2, UTF-8, etc.).
111 charoffset = offset;
112 p = str;
113 while ((character = tvb_get_letohs(tvb, charoffset)) != '\0') {
114 *p++ = (char) character;
115 charoffset += 2;
117 *p = '\0';
119 proto_tree_add_string(tree, hf_index, tvb, offset, len, str);
121 if (data)
122 *data = str;
124 return offset+len;
127 /* Max string length for displaying Unicode strings. */
128 #define MAX_UNICODE_STR_LEN 256
130 int dissect_ms_compressed_string(tvbuff_t *tvb, proto_tree *tree, int offset, int hf_index,
131 char **data)
133 int compr_len;
134 const guchar *str = NULL;
136 /* The name data MUST start at offset 0 of the tvb */
137 compr_len = expand_dns_name(tvb, offset, MAX_UNICODE_STR_LEN+3+1, 0, &str);
138 proto_tree_add_string(tree, hf_index, tvb, offset, compr_len, str);
140 if (data)
141 *data = (char*) str;
143 return offset + compr_len;
146 /* Turn a little-endian Unicode '\0'-terminated string into a string we
147 can display.
148 XXX - for now, we just handle the ISO 8859-1 characters.
149 If exactlen==TRUE then us_lenp contains the exact len of the string in
150 bytes. It might not be null terminated !
151 bc specifies the number of bytes in the byte parameters; Windows 2000,
152 at least, appears, in some cases, to put only 1 byte of 0 at the end
153 of a Unicode string if the byte count
155 static gchar *
156 unicode_to_str(tvbuff_t *tvb, int offset, int *us_lenp, gboolean exactlen,
157 guint16 bc)
159 gchar *cur;
160 gchar *p;
161 guint16 uchar;
162 int len;
163 int us_len;
164 gboolean overflow = FALSE;
166 cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1);
167 p = cur;
168 len = MAX_UNICODE_STR_LEN;
169 us_len = 0;
170 for (;;) {
171 if (bc == 0)
172 break;
174 if (bc == 1) {
175 /* XXX - explain this */
176 if (!exactlen)
177 us_len += 1; /* this is a one-byte null terminator */
178 break;
181 uchar = tvb_get_letohs(tvb, offset);
182 if (uchar == 0) {
183 us_len += 2; /* this is a two-byte null terminator */
184 break;
187 if (len > 0) {
188 if ((uchar & 0xFF00) == 0)
189 *p++ = (gchar) uchar; /* ISO 8859-1 */
190 else
191 *p++ = '?'; /* not 8859-1 */
192 len--;
193 } else
194 overflow = TRUE;
196 offset += 2;
197 bc -= 2;
198 us_len += 2;
200 if(exactlen){
201 if(us_len>= *us_lenp){
202 break;
206 if (overflow) {
207 /* Note that we're not showing the full string. */
208 *p++ = '.';
209 *p++ = '.';
210 *p++ = '.';
213 *p = '\0';
214 *us_lenp = us_len;
216 return cur;
219 /* nopad == TRUE : Do not add any padding before this string
220 * exactlen == TRUE : len contains the exact len of the string in bytes.
221 * bc: pointer to variable with amount of data left in the byte parameters
222 * region
224 const gchar *
225 get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
226 gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
227 guint16 *bcp)
229 gchar *cur;
230 const gchar *string;
231 int string_len = 0;
232 int copylen;
233 gboolean overflow = FALSE;
235 if (*bcp == 0) {
236 /* Not enough data in buffer */
237 return NULL;
240 if (useunicode) {
241 if ((!nopad) && (*bcp % 2)) {
242 (*offsetp)++; /* Looks like a pad byte there sometimes */
243 (*bcp)--;
245 if (*bcp == 0) {
246 /* Not enough data in buffer */
247 return NULL;
251 if(exactlen){
252 string_len = *len;
253 if (string_len < 0) {
254 /* This probably means it's a very large unsigned number; just set
255 it to the largest signed number, so that we throw the appropriate
256 exception. */
257 string_len = INT_MAX;
261 string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp);
263 } else {
264 if(exactlen){
266 * The string we return must be null-terminated.
268 cur=(gchar *)wmem_alloc(wmem_packet_scope(), MAX_UNICODE_STR_LEN+3+1);
269 copylen = *len;
271 if (copylen < 0) {
272 /* This probably means it's a very large unsigned number; just set
273 it to the largest signed number, so that we throw the appropriate
274 exception. */
275 copylen = INT_MAX;
278 tvb_ensure_bytes_exist(tvb, *offsetp, copylen);
280 if (copylen > MAX_UNICODE_STR_LEN) {
281 copylen = MAX_UNICODE_STR_LEN;
282 overflow = TRUE;
285 tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
286 cur[copylen] = '\0';
288 if (overflow)
289 g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1);
291 string_len = *len;
292 string = cur;
293 } else {
294 string = tvb_get_const_stringz(tvb, *offsetp, &string_len);
298 *len = string_len;
299 return string;