~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to libcli/nbt/nbtname.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   manipulate nbt name structures
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2005
 
7
 
 
8
   This program is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 3 of the License, or
 
11
   (at your option) any later version.
 
12
 
 
13
   This program is distributed in the hope that it will be useful,
 
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
   GNU General Public License for more details.
 
17
 
 
18
   You should have received a copy of the GNU General Public License
 
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
/*
 
23
  see rfc1002 for the detailed format of compressed names
 
24
*/
 
25
 
 
26
#include "includes.h"
 
27
#include "librpc/gen_ndr/ndr_nbt.h"
 
28
#include "librpc/gen_ndr/ndr_misc.h"
 
29
#include "system/locale.h"
 
30
 
 
31
/* don't allow an unlimited number of name components */
 
32
#define MAX_COMPONENTS 10
 
33
 
 
34
/**
 
35
  print a nbt string
 
36
*/
 
37
_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s)
 
38
{
 
39
        ndr_print_string(ndr, name, s);
 
40
}
 
41
 
 
42
/*
 
43
  pull one component of a nbt_string
 
44
*/
 
45
static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr,
 
46
                                            uint8_t **component,
 
47
                                            uint32_t *offset,
 
48
                                            uint32_t *max_offset)
 
49
{
 
50
        uint8_t len;
 
51
        uint_t loops = 0;
 
52
        while (loops < 5) {
 
53
                if (*offset >= ndr->data_size) {
 
54
                        return ndr_pull_error(ndr, NDR_ERR_STRING,
 
55
                                              "BAD NBT NAME component");
 
56
                }
 
57
                len = ndr->data[*offset];
 
58
                if (len == 0) {
 
59
                        *offset += 1;
 
60
                        *max_offset = MAX(*max_offset, *offset);
 
61
                        *component = NULL;
 
62
                        return NDR_ERR_SUCCESS;
 
63
                }
 
64
                if ((len & 0xC0) == 0xC0) {
 
65
                        /* its a label pointer */
 
66
                        if (1 + *offset >= ndr->data_size) {
 
67
                                return ndr_pull_error(ndr, NDR_ERR_STRING,
 
68
                                                      "BAD NBT NAME component");
 
69
                        }
 
70
                        *max_offset = MAX(*max_offset, *offset + 2);
 
71
                        *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset];
 
72
                        *max_offset = MAX(*max_offset, *offset);
 
73
                        loops++;
 
74
                        continue;
 
75
                }
 
76
                if ((len & 0xC0) != 0) {
 
77
                        /* its a reserved length field */
 
78
                        return ndr_pull_error(ndr, NDR_ERR_STRING,
 
79
                                              "BAD NBT NAME component");
 
80
                }
 
81
                if (*offset + len + 2 > ndr->data_size) {
 
82
                        return ndr_pull_error(ndr, NDR_ERR_STRING,
 
83
                                              "BAD NBT NAME component");
 
84
                }
 
85
                *component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len);
 
86
                NDR_ERR_HAVE_NO_MEMORY(*component);
 
87
                *offset += len + 1;
 
88
                *max_offset = MAX(*max_offset, *offset);
 
89
                return NDR_ERR_SUCCESS;
 
90
        }
 
91
 
 
92
        /* too many pointers */
 
93
        return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD NBT NAME component");
 
94
}
 
95
 
 
96
/**
 
97
  pull a nbt_string from the wire
 
98
*/
 
99
_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
 
100
{
 
101
        uint32_t offset = ndr->offset;
 
102
        uint32_t max_offset = offset;
 
103
        unsigned num_components;
 
104
        char *name;
 
105
 
 
106
        if (!(ndr_flags & NDR_SCALARS)) {
 
107
                return NDR_ERR_SUCCESS;
 
108
        }
 
109
 
 
110
        name = NULL;
 
111
 
 
112
        /* break up name into a list of components */
 
113
        for (num_components=0;num_components<MAX_COMPONENTS;num_components++) {
 
114
                uint8_t *component = NULL;
 
115
                NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset));
 
116
                if (component == NULL) break;
 
117
                if (name) {
 
118
                        name = talloc_asprintf_append_buffer(name, ".%s", component);
 
119
                        NDR_ERR_HAVE_NO_MEMORY(name);
 
120
                } else {
 
121
                        name = (char *)component;
 
122
                }
 
123
        }
 
124
        if (num_components == MAX_COMPONENTS) {
 
125
                return ndr_pull_error(ndr, NDR_ERR_STRING,
 
126
                                      "BAD NBT NAME too many components");
 
127
        }
 
128
        if (num_components == 0) {
 
129
                name = talloc_strdup(ndr, "");
 
130
                NDR_ERR_HAVE_NO_MEMORY(name);
 
131
        }
 
132
 
 
133
        (*s) = name;
 
134
        ndr->offset = max_offset;
 
135
 
 
136
        return NDR_ERR_SUCCESS;
 
137
}
 
138
 
 
139
/**
 
140
  push a nbt string to the wire
 
141
*/
 
142
_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s)
 
143
{
 
144
        if (!(ndr_flags & NDR_SCALARS)) {
 
145
                return NDR_ERR_SUCCESS;
 
146
        }
 
147
 
 
148
        while (s && *s) {
 
149
                enum ndr_err_code ndr_err;
 
150
                char *compname;
 
151
                size_t complen;
 
152
                uint32_t offset;
 
153
 
 
154
                /* see if we have pushed the remaing string allready,
 
155
                 * if so we use a label pointer to this string
 
156
                 */
 
157
                ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false);
 
158
                if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
159
                        uint8_t b[2];
 
160
 
 
161
                        if (offset > 0x3FFF) {
 
162
                                return ndr_push_error(ndr, NDR_ERR_STRING,
 
163
                                                      "offset for nbt string label pointer %u[%08X] > 0x00003FFF",
 
164
                                                      offset, offset);
 
165
                        }
 
166
 
 
167
                        b[0] = 0xC0 | (offset>>8);
 
168
                        b[1] = (offset & 0xFF);
 
169
 
 
170
                        return ndr_push_bytes(ndr, b, 2);
 
171
                }
 
172
 
 
173
                complen = strcspn(s, ".");
 
174
 
 
175
                /* we need to make sure the length fits into 6 bytes */
 
176
                if (complen >= 0x3F) {
 
177
                        return ndr_push_error(ndr, NDR_ERR_STRING,
 
178
                                              "component length %u[%08X] > 0x00003F",
 
179
                                              (unsigned)complen, (unsigned)complen);
 
180
                }
 
181
 
 
182
                compname = talloc_asprintf(ndr, "%c%*.*s",
 
183
                                                (unsigned char)complen,
 
184
                                                (unsigned char)complen,
 
185
                                                (unsigned char)complen, s);
 
186
                NDR_ERR_HAVE_NO_MEMORY(compname);
 
187
 
 
188
                /* remember the current componemt + the rest of the string
 
189
                 * so it can be reused later
 
190
                 */
 
191
                NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset));
 
192
 
 
193
                /* push just this component into the blob */
 
194
                NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1));
 
195
                talloc_free(compname);
 
196
 
 
197
                s += complen;
 
198
                if (*s == '.') s++;
 
199
        }
 
200
 
 
201
        /* if we reach the end of the string and have pushed the last component
 
202
         * without using a label pointer, we need to terminate the string
 
203
         */
 
204
        return ndr_push_bytes(ndr, (const uint8_t *)"", 1);
 
205
}
 
206
 
 
207
 
 
208
/*
 
209
  decompress a 'compressed' name component
 
210
 */
 
211
static bool decompress_name(char *name, enum nbt_name_type *type)
 
212
{
 
213
        int i;
 
214
        for (i=0;name[2*i];i++) {
 
215
                uint8_t c1 = name[2*i];
 
216
                uint8_t c2 = name[1+(2*i)];
 
217
                if (c1 < 'A' || c1 > 'P' ||
 
218
                    c2 < 'A' || c2 > 'P') {
 
219
                        return false;
 
220
                }
 
221
                name[i] = ((c1-'A')<<4) | (c2-'A');
 
222
        }
 
223
        name[i] = 0;
 
224
        if (i == 16) {
 
225
                *type = (enum nbt_name_type)(name[15]);
 
226
                name[15] = 0;
 
227
                i--;
 
228
        } else {
 
229
                *type = NBT_NAME_CLIENT;
 
230
        }
 
231
 
 
232
        /* trim trailing spaces */
 
233
        for (;i>0 && name[i-1]==' ';i--) {
 
234
                name[i-1] = 0;
 
235
        }
 
236
 
 
237
        return true;
 
238
}
 
239
 
 
240
 
 
241
/*
 
242
  compress a name component
 
243
 */
 
244
static uint8_t *compress_name(TALLOC_CTX *mem_ctx,
 
245
                              const uint8_t *name, enum nbt_name_type type)
 
246
{
 
247
        uint8_t *cname;
 
248
        int i;
 
249
        uint8_t pad_char;
 
250
 
 
251
        if (strlen((const char *)name) > 15) {
 
252
                return NULL;
 
253
        }
 
254
 
 
255
        cname = talloc_array(mem_ctx, uint8_t, 33);
 
256
        if (cname == NULL) return NULL;
 
257
 
 
258
        for (i=0;name[i];i++) {
 
259
                cname[2*i]   = 'A' + (name[i]>>4);
 
260
                cname[1+2*i] = 'A' + (name[i]&0xF);
 
261
        }
 
262
        if (strcmp((const char *)name, "*") == 0) {
 
263
                pad_char = 0;
 
264
        } else {
 
265
                pad_char = ' ';
 
266
        }
 
267
        for (;i<15;i++) {
 
268
                cname[2*i]   = 'A' + (pad_char>>4);
 
269
                cname[1+2*i] = 'A' + (pad_char&0xF);
 
270
        }
 
271
 
 
272
        pad_char = type;
 
273
        cname[2*i]   = 'A' + (pad_char>>4);
 
274
        cname[1+2*i] = 'A' + (pad_char&0xF);
 
275
 
 
276
        cname[32] = 0;
 
277
        return cname;
 
278
}
 
279
 
 
280
 
 
281
/**
 
282
  pull a nbt name from the wire
 
283
*/
 
284
_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r)
 
285
{
 
286
        uint8_t *scope;
 
287
        char *cname;
 
288
        const char *s;
 
289
        bool ok;
 
290
 
 
291
        if (!(ndr_flags & NDR_SCALARS)) {
 
292
                return NDR_ERR_SUCCESS;
 
293
        }
 
294
 
 
295
        NDR_CHECK(ndr_pull_nbt_string(ndr, ndr_flags, &s));
 
296
 
 
297
        scope = (uint8_t *)strchr(s, '.');
 
298
        if (scope) {
 
299
                *scope = 0;
 
300
                r->scope = talloc_strdup(ndr->current_mem_ctx, (const char *)&scope[1]);
 
301
                NDR_ERR_HAVE_NO_MEMORY(r->scope);
 
302
        } else {
 
303
                r->scope = NULL;
 
304
        }
 
305
 
 
306
        cname = discard_const_p(char, s);
 
307
 
 
308
        /* the first component is limited to 16 bytes in the DOS charset,
 
309
           which is 32 in the 'compressed' form */
 
310
        if (strlen(cname) > 32) {
 
311
                return ndr_pull_error(ndr, NDR_ERR_STRING,
 
312
                                      "NBT NAME cname > 32");
 
313
        }
 
314
 
 
315
        /* decompress the first component */
 
316
        ok = decompress_name(cname, &r->type);
 
317
        if (!ok) {
 
318
                return ndr_pull_error(ndr, NDR_ERR_STRING,
 
319
                                      "NBT NAME failed to decompress");
 
320
        }
 
321
 
 
322
        r->name = talloc_strdup(ndr->current_mem_ctx, cname);
 
323
        NDR_ERR_HAVE_NO_MEMORY(r->name);
 
324
 
 
325
        talloc_free(cname);
 
326
 
 
327
        return NDR_ERR_SUCCESS;
 
328
}
 
329
 
 
330
/**
 
331
  push a nbt name to the wire
 
332
*/
 
333
_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r)
 
334
{
 
335
        uint8_t *cname, *fullname;
 
336
        enum ndr_err_code ndr_err;
 
337
 
 
338
        if (!(ndr_flags & NDR_SCALARS)) {
 
339
                return NDR_ERR_SUCCESS;
 
340
        }
 
341
 
 
342
        if (strlen(r->name) > 15) {
 
343
                return ndr_push_error(ndr, NDR_ERR_STRING,
 
344
                                      "nbt_name longer as 15 chars: %s",
 
345
                                      r->name);
 
346
        }
 
347
 
 
348
        cname = compress_name(ndr, (const uint8_t *)r->name, r->type);
 
349
        NDR_ERR_HAVE_NO_MEMORY(cname);
 
350
 
 
351
        if (r->scope) {
 
352
                fullname = (uint8_t *)talloc_asprintf(ndr, "%s.%s", cname, r->scope);
 
353
                NDR_ERR_HAVE_NO_MEMORY(fullname);
 
354
                talloc_free(cname);
 
355
        } else {
 
356
                fullname = cname;
 
357
        }
 
358
 
 
359
        ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname);
 
360
 
 
361
        return ndr_err;
 
362
}
 
363
 
 
364
 
 
365
/**
 
366
  copy a nbt name structure
 
367
*/
 
368
_PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname)
 
369
{
 
370
        *newname = *name;
 
371
        newname->name = talloc_strdup(mem_ctx, newname->name);
 
372
        NT_STATUS_HAVE_NO_MEMORY(newname->name);
 
373
        newname->scope = talloc_strdup(mem_ctx, newname->scope);
 
374
        if (name->scope) {
 
375
                NT_STATUS_HAVE_NO_MEMORY(newname->scope);
 
376
        }
 
377
        return NT_STATUS_OK;
 
378
}
 
379
 
 
380
/**
 
381
  push a nbt name into a blob
 
382
*/
 
383
_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, DATA_BLOB *blob, struct nbt_name *name)
 
384
{
 
385
        enum ndr_err_code ndr_err;
 
386
 
 
387
        ndr_err = ndr_push_struct_blob(blob, mem_ctx, iconv_convenience, name, (ndr_push_flags_fn_t)ndr_push_nbt_name);
 
388
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
389
                return ndr_map_error2ntstatus(ndr_err);
 
390
        }
 
391
 
 
392
        return NT_STATUS_OK;
 
393
}
 
394
 
 
395
/**
 
396
  pull a nbt name from a blob
 
397
*/
 
398
_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name)
 
399
{
 
400
        enum ndr_err_code ndr_err;
 
401
 
 
402
        ndr_err = ndr_pull_struct_blob(blob, mem_ctx, NULL, name,
 
403
                                       (ndr_pull_flags_fn_t)ndr_pull_nbt_name);
 
404
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 
405
                return ndr_map_error2ntstatus(ndr_err);
 
406
        }
 
407
 
 
408
        return NT_STATUS_OK;
 
409
}
 
410
 
 
411
 
 
412
/**
 
413
  choose a name to use when calling a server in a NBT session request.
 
414
  we use heuristics to see if the name we have been given is a IP
 
415
  address, or a too-long name. If it is then use *SMBSERVER, or a
 
416
  truncated name
 
417
*/
 
418
_PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx,
 
419
                            struct nbt_name *n, const char *name, int type)
 
420
{
 
421
        n->scope = NULL;
 
422
        n->type = type;
 
423
 
 
424
        if ((name == NULL) || is_ipaddress(name)) {
 
425
                n->name = "*SMBSERVER";
 
426
                return;
 
427
        }
 
428
        if (strlen(name) > 15) {
 
429
                const char *p = strchr(name, '.');
 
430
                char *s;
 
431
                if (p - name > 15) {
 
432
                        n->name = "*SMBSERVER";
 
433
                        return;
 
434
                }
 
435
                s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name));
 
436
                n->name = talloc_strdup_upper(mem_ctx, s);
 
437
                return;
 
438
        }
 
439
 
 
440
        n->name = talloc_strdup_upper(mem_ctx, name);
 
441
}
 
442
 
 
443
 
 
444
/*
 
445
  escape a string into a form containing only a small set of characters,
 
446
  the rest is hex encoded. This is similar to URL encoding
 
447
*/
 
448
static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s)
 
449
{
 
450
        int i, len;
 
451
        char *ret;
 
452
        const char *valid_chars = "_-.$@ ";
 
453
#define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c))
 
454
 
 
455
        for (len=i=0;s[i];i++,len++) {
 
456
                if (!NBT_CHAR_ALLOW(s[i])) {
 
457
                        len += 2;
 
458
                }
 
459
        }
 
460
 
 
461
        ret = talloc_array(mem_ctx, char, len+1);
 
462
        if (ret == NULL) return NULL;
 
463
 
 
464
        for (len=i=0;s[i];i++) {
 
465
                if (NBT_CHAR_ALLOW(s[i])) {
 
466
                        ret[len++] = s[i];
 
467
                } else {
 
468
                        snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]);
 
469
                        len += 3;
 
470
                }
 
471
        }
 
472
        ret[len] = 0;
 
473
 
 
474
        return ret;
 
475
}
 
476
 
 
477
 
 
478
/**
 
479
  form a string for a NBT name
 
480
*/
 
481
_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name)
 
482
{
 
483
        TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
 
484
        char *ret;
 
485
        if (name->scope) {
 
486
                ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s",
 
487
                                      nbt_hex_encode(tmp_ctx, name->name),
 
488
                                      name->type,
 
489
                                      nbt_hex_encode(tmp_ctx, name->scope));
 
490
        } else {
 
491
                ret = talloc_asprintf(mem_ctx, "%s<%02x>",
 
492
                                      nbt_hex_encode(tmp_ctx, name->name),
 
493
                                      name->type);
 
494
        }
 
495
        talloc_free(tmp_ctx);
 
496
        return ret;
 
497
}
 
498
 
 
499
/**
 
500
  pull a nbt name, WINS Replication uses another on wire format for nbt name
 
501
*/
 
502
_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r)
 
503
{
 
504
        struct nbt_name *r;
 
505
        uint8_t *namebuf;
 
506
        uint32_t namebuf_len;
 
507
 
 
508
        if (!(ndr_flags & NDR_SCALARS)) {
 
509
                return NDR_ERR_SUCCESS;
 
510
        }
 
511
 
 
512
        NDR_CHECK(ndr_pull_align(ndr, 4));
 
513
        NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len));
 
514
        if (namebuf_len < 1 || namebuf_len > 255) {
 
515
                return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value out of range");
 
516
        }
 
517
        NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len);
 
518
        NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
 
519
 
 
520
        NDR_PULL_ALLOC(ndr, r);
 
521
 
 
522
        /* oh wow, what a nasty bug in windows ... */
 
523
        if (namebuf[0] == 0x1b && namebuf_len >= 16) {
 
524
                namebuf[0] = namebuf[15];
 
525
                namebuf[15] = 0x1b;
 
526
        }
 
527
 
 
528
        if (namebuf_len < 17) {
 
529
                r->type = 0x00;
 
530
 
 
531
                r->name = talloc_strndup(r, (char *)namebuf, namebuf_len);
 
532
                if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
 
533
 
 
534
                r->scope= NULL;
 
535
 
 
536
                talloc_free(namebuf);
 
537
                *_r = r;
 
538
                return NDR_ERR_SUCCESS;
 
539
        }
 
540
 
 
541
        r->type = namebuf[15];
 
542
 
 
543
        namebuf[15] = '\0';
 
544
        trim_string((char *)namebuf, NULL, " ");
 
545
        r->name = talloc_strdup(r, (char *)namebuf);
 
546
        if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
 
547
 
 
548
        if (namebuf_len > 18) {
 
549
                r->scope = talloc_strndup(r, (char *)(namebuf+17), namebuf_len-17);
 
550
                if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory");
 
551
        } else {
 
552
                r->scope = NULL;
 
553
        }
 
554
 
 
555
        talloc_free(namebuf);
 
556
        *_r = r;
 
557
        return NDR_ERR_SUCCESS;
 
558
}
 
559
 
 
560
/**
 
561
  push a nbt name, WINS Replication uses another on wire format for nbt name
 
562
*/
 
563
_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r)
 
564
{
 
565
        uint8_t *namebuf;
 
566
        uint32_t namebuf_len;
 
567
        uint32_t _name_len;
 
568
        uint32_t scope_len = 0;
 
569
 
 
570
        if (r == NULL) {
 
571
                return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER,
 
572
                                      "wrepl_nbt_name NULL pointer");
 
573
        }
 
574
 
 
575
        if (!(ndr_flags & NDR_SCALARS)) {
 
576
                return NDR_ERR_SUCCESS;
 
577
        }
 
578
 
 
579
        _name_len = strlen(r->name);
 
580
        if (_name_len > 15) {
 
581
                return ndr_push_error(ndr, NDR_ERR_STRING,
 
582
                                      "wrepl_nbt_name longer as 15 chars: %s",
 
583
                                      r->name);
 
584
        }
 
585
 
 
586
        if (r->scope) {
 
587
                scope_len = strlen(r->scope);
 
588
        }
 
589
        if (scope_len > 238) {
 
590
                return ndr_push_error(ndr, NDR_ERR_STRING,
 
591
                                      "wrepl_nbt_name scope longer as 238 chars: %s",
 
592
                                      r->scope);
 
593
        }
 
594
 
 
595
        namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s",
 
596
                                             r->name, 'X',
 
597
                                             (r->scope?r->scope:""));
 
598
        if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory");
 
599
 
 
600
        namebuf_len = strlen((char *)namebuf) + 1;
 
601
 
 
602
        /*
 
603
         * we need to set the type here, and use a place-holder in the talloc_asprintf()
 
604
         * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results
 
605
         */
 
606
        namebuf[15] = r->type;
 
607
 
 
608
        /* oh wow, what a nasty bug in windows ... */
 
609
        if (r->type == 0x1b) {
 
610
                namebuf[15] = namebuf[0];
 
611
                namebuf[0] = 0x1b;
 
612
        }
 
613
 
 
614
        NDR_CHECK(ndr_push_align(ndr, 4));
 
615
        NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len));
 
616
        NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len));
 
617
 
 
618
        talloc_free(namebuf);
 
619
        return NDR_ERR_SUCCESS;
 
620
}
 
621
 
 
622
_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r)
 
623
{
 
624
        char *s = nbt_name_string(ndr, r);
 
625
        ndr_print_string(ndr, name, s);
 
626
        talloc_free(s);
 
627
}
 
628
 
 
629
_PUBLIC_ enum ndr_err_code ndr_push_nbt_res_rec(struct ndr_push *ndr, int ndr_flags, const struct nbt_res_rec *r)
 
630
{
 
631
        {
 
632
                uint32_t _flags_save_STRUCT = ndr->flags;
 
633
                ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX);
 
634
                if (ndr_flags & NDR_SCALARS) {
 
635
                        NDR_CHECK(ndr_push_align(ndr, 4));
 
636
                        NDR_CHECK(ndr_push_nbt_name(ndr, NDR_SCALARS, &r->name));
 
637
                        NDR_CHECK(ndr_push_nbt_qtype(ndr, NDR_SCALARS, r->rr_type));
 
638
                        NDR_CHECK(ndr_push_nbt_qclass(ndr, NDR_SCALARS, r->rr_class));
 
639
                        NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ttl));
 
640
                        NDR_CHECK(ndr_push_set_switch_value(ndr, &r->rdata, ((((r->rr_type) == NBT_QTYPE_NETBIOS) && ((r->rdata).data.length == 2))?0:r->rr_type)));
 
641
                        NDR_CHECK(ndr_push_nbt_rdata(ndr, NDR_SCALARS, &r->rdata));
 
642
                }
 
643
                if (ndr_flags & NDR_BUFFERS) {
 
644
                }
 
645
                ndr->flags = _flags_save_STRUCT;
 
646
        }
 
647
        return NDR_ERR_SUCCESS;
 
648
}