~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/protocol/smb/smb.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Gervai
  • Date: 2004-01-21 22:13:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040121221345-ju33hai1yhhqt6kn
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Internal SMB protocol implementation */
 
2
/* $Id: smb.c,v 1.32 2004/01/01 16:15:16 pasky Exp $ */
 
3
 
 
4
#ifndef _GNU_SOURCE
 
5
#define _GNU_SOURCE /* Needed for asprintf() */
 
6
#endif
 
7
 
 
8
#ifdef HAVE_CONFIG_H
 
9
#include "config.h"
 
10
#endif
 
11
 
 
12
#ifdef CONFIG_SMB
 
13
 
 
14
#include <errno.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#ifdef HAVE_SYS_TIME_H
 
19
#include <sys/time.h> /* FreeBSD needs this before resource.h */
 
20
#endif
 
21
#include <sys/types.h> /* FreeBSD needs this before resource.h */
 
22
#ifdef HAVE_SYS_RESOURCE_H
 
23
#include <sys/resource.h>
 
24
#endif
 
25
#ifdef HAVE_FCNTL_H
 
26
#include <fcntl.h> /* OS/2 needs this after sys/types.h */
 
27
#endif
 
28
#ifdef HAVE_UNISTD_H
 
29
#include <unistd.h>
 
30
#endif
 
31
 
 
32
#include "elinks.h"
 
33
 
 
34
#include "lowlevel/connect.h"
 
35
#include "lowlevel/select.h"
 
36
#include "osdep/osdep.h"
 
37
#include "protocol/protocol.h"
 
38
#include "sched/connection.h"
 
39
#include "util/memory.h"
 
40
#include "util/snprintf.h"
 
41
#include "util/string.h"
 
42
 
 
43
/* XXX: Nice cleanup target --pasky */
 
44
/* FIXME: we rely on smbclient output which may change in future,
 
45
 * so i think we should use libsmbclient instead (or better in addition)
 
46
 * This stuff is a quick hack, but it works ;). --Zas */
 
47
 
 
48
enum smb_list_type {
 
49
        SMB_LIST_NONE,
 
50
        SMB_LIST_SHARES,
 
51
        SMB_LIST_DIR,
 
52
};
 
53
 
 
54
struct smb_connection_info {
 
55
        enum smb_list_type list_type;
 
56
 
 
57
        /* If this is 1, it means one socket is already off. The second one
 
58
         * should call end_smb_connection() when it goes off as well. */
 
59
        int closing;
 
60
 
 
61
        int textlen;
 
62
        unsigned char text[1];
 
63
};
 
64
 
 
65
static void end_smb_connection(struct connection *conn);
 
66
 
 
67
 
 
68
/* Return 0 if @conn->cache was set. */
 
69
static int
 
70
smb_get_cache(struct connection *conn)
 
71
{
 
72
        if (conn->cache) return 0;
 
73
 
 
74
        conn->cache = get_cache_entry(struri(conn->uri));
 
75
        if (conn->cache) return 0;
 
76
 
 
77
        abort_conn_with_state(conn, S_OUT_OF_MEM);
 
78
        return -1;
 
79
}
 
80
 
 
81
 
 
82
#define READ_SIZE       4096
 
83
 
 
84
static int
 
85
smb_read_data(struct connection *conn, int sock, unsigned char *dst)
 
86
{
 
87
        int r;
 
88
        struct smb_connection_info *si = conn->info;
 
89
 
 
90
        r = read(sock, dst, READ_SIZE);
 
91
        if (r == -1) {
 
92
                retry_conn_with_state(conn, -errno);
 
93
                return -1;
 
94
        }
 
95
        if (r == 0) {
 
96
                if (!si->closing) {
 
97
                        si->closing = 1;
 
98
                        set_handlers(conn->socket, NULL, NULL, NULL, NULL);
 
99
                        return 0;
 
100
                }
 
101
                end_smb_connection(conn);
 
102
                return 0;
 
103
        }
 
104
 
 
105
        return r;
 
106
}
 
107
 
 
108
static void
 
109
smb_read_text(struct connection *conn, int sock)
 
110
{
 
111
        int r;
 
112
        struct smb_connection_info *si = conn->info;
 
113
 
 
114
        si = mem_realloc(si, sizeof(struct smb_connection_info) + si->textlen
 
115
                             + READ_SIZE + 2); /* XXX: why +2 ? --Zas */
 
116
        if (!si) {
 
117
                abort_conn_with_state(conn, S_OUT_OF_MEM);
 
118
                return;
 
119
        }
 
120
        conn->info = si;
 
121
 
 
122
        r = smb_read_data(conn, sock, si->text + si->textlen);
 
123
        if (r <= 0) return;
 
124
 
 
125
        if (!conn->from) set_connection_state(conn, S_GETH);
 
126
        si->textlen += r;
 
127
}
 
128
 
 
129
static void
 
130
smb_got_data(struct connection *conn)
 
131
{
 
132
        struct smb_connection_info *si = conn->info;
 
133
        unsigned char buffer[READ_SIZE];
 
134
        int r;
 
135
 
 
136
        if (si->list_type != SMB_LIST_NONE) {
 
137
                smb_read_text(conn, conn->data_socket);
 
138
                return;
 
139
        }
 
140
 
 
141
        r = smb_read_data(conn, conn->data_socket, buffer);
 
142
        if (r <= 0) return;
 
143
 
 
144
        set_connection_state(conn, S_TRANS);
 
145
 
 
146
        if (smb_get_cache(conn)) return;
 
147
 
 
148
        conn->received += r;
 
149
        if (add_fragment(conn->cache, conn->from, buffer, r) == 1)
 
150
                conn->tries = 0;
 
151
        conn->from += r;
 
152
}
 
153
 
 
154
#undef READ_SIZE
 
155
 
 
156
static void
 
157
smb_got_text(struct connection *conn)
 
158
{
 
159
        smb_read_text(conn, conn->socket);
 
160
}
 
161
 
 
162
 
 
163
/* FIXME: split it. --Zas */
 
164
static void
 
165
end_smb_connection(struct connection *conn)
 
166
{
 
167
        struct smb_connection_info *si = conn->info;
 
168
 
 
169
        if (smb_get_cache(conn)) return;
 
170
 
 
171
        if (conn->from) {
 
172
                truncate_entry(conn->cache, conn->from, 1);
 
173
                conn->cache->incomplete = 0;
 
174
                goto bye;
 
175
        }
 
176
 
 
177
        if (si->textlen && si->text[si->textlen - 1] != '\n')
 
178
                si->text[si->textlen++] = '\n';
 
179
        si->text[si->textlen] = '\0';
 
180
 
 
181
        if ((strstr(si->text, "NT_STATUS_FILE_IS_A_DIRECTORY")
 
182
             || strstr(si->text, "NT_STATUS_ACCESS_DENIED")
 
183
             || strstr(si->text, "ERRbadfile"))
 
184
            && conn->uri.datalen
 
185
            && conn->uri.data[conn->uri.datalen - 1] != '/'
 
186
            && conn->uri.data[conn->uri.datalen - 1] != '\\') {
 
187
                if (conn->cache->redirect) mem_free(conn->cache->redirect);
 
188
                conn->cache->redirect = stracpy(struri(conn->uri));
 
189
                conn->cache->redirect_get = 1;
 
190
                add_to_strn(&conn->cache->redirect, "/");
 
191
                conn->cache->incomplete = 0;
 
192
 
 
193
        } else {
 
194
                unsigned char *line_start, *line_end, *line_end2;
 
195
                struct string page;
 
196
                int type = 0;
 
197
                int pos = 0;
 
198
 
 
199
                if (!init_string(&page)) {
 
200
                        abort_conn_with_state(conn, S_OUT_OF_MEM);
 
201
                        return;
 
202
                }
 
203
 
 
204
                add_to_string(&page, "<html><head><title>/");
 
205
                add_bytes_to_string(&page, conn->uri.data, conn->uri.datalen);
 
206
                add_to_string(&page, "</title></head><body><pre>");
 
207
 
 
208
                line_start = si->text;
 
209
                while ((line_end = strchr(line_start, '\n'))) {
 
210
                        unsigned char *line;
 
211
 
 
212
                        /* FIXME: Just look if '\r' is right in front of '\n'?
 
213
                         * --pasky */
 
214
                        line_end2 = strchr(line_start, '\r');
 
215
                        if (!line_end2 || line_end2 > line_end)
 
216
                                line_end2 = line_end;
 
217
                        line = memacpy(line_start, line_end2 - line_start);
 
218
 
 
219
                        /* And I got bored here with cleaning it up. --pasky */
 
220
 
 
221
                        if (si->list_type == SMB_LIST_SHARES) {
 
222
                                unsigned char *ll, *lll;
 
223
 
 
224
                                if (!*line) type = 0;
 
225
                                if (strstr(line, "Sharename")
 
226
                                    && strstr(line, "Type")) {
 
227
                                        if (strstr(line, "Type")) {
 
228
                                                pos = (unsigned char *)
 
229
                                                        strstr(line, "Type") - line;
 
230
                                        } else {
 
231
                                                pos = 0;
 
232
                                        }
 
233
                                        type = 1;
 
234
                                        goto print_as_is;
 
235
                                }
 
236
                                if (strstr(line, "Server")
 
237
                                    && strstr(line, "Comment")) {
 
238
                                        type = 2;
 
239
                                        goto print_as_is;
 
240
                                }
 
241
                                if (strstr(line, "Workgroup")
 
242
                                    && strstr(line, "Master")) {
 
243
                                        pos = (unsigned char *) strstr(line, "Master") - line;
 
244
                                        type = 3;
 
245
                                        goto print_as_is;
 
246
                                }
 
247
 
 
248
                                if (!type) goto print_as_is;
 
249
                                for (ll = line; *ll; ll++)
 
250
                                        if (!WHITECHAR(*ll) && *ll != '-')
 
251
                                                goto np;
 
252
                                goto print_as_is;
 
253
np:
 
254
 
 
255
                                for (ll = line; *ll; ll++)
 
256
                                        if (!WHITECHAR(*ll))
 
257
                                                break;
 
258
 
 
259
                                for (lll = ll; *lll/* && lll[1]*/; lll++)
 
260
                                        if (WHITECHAR(*lll)/* && WHITECHAR(lll[1])*/)
 
261
                                                break;
 
262
 
 
263
                                switch (type) {
 
264
                                case 1:
 
265
                                {
 
266
                                        unsigned char *llll;
 
267
 
 
268
                                        if (!strstr(lll, "Disk"))
 
269
                                                goto print_as_is;
 
270
 
 
271
                                        if (pos && pos < strlen(line)
 
272
                                            && WHITECHAR(*(llll = line + pos - 1))
 
273
                                            && llll > ll) {
 
274
                                                while (llll > ll && WHITECHAR(*llll))
 
275
                                                        llll--;
 
276
                                                if (!WHITECHAR(*llll))
 
277
                                                        lll = llll + 1;
 
278
                                        }
 
279
 
 
280
                                        add_bytes_to_string(&page, line, ll - line);
 
281
                                        add_to_string(&page, "<a href=\"");
 
282
                                        add_bytes_to_string(&page, ll, lll - ll);
 
283
                                        add_to_string(&page, "/\">");
 
284
                                        add_bytes_to_string(&page, ll, lll - ll);
 
285
                                        add_to_string(&page, "</a>");
 
286
                                        add_to_string(&page, lll);
 
287
                                        break;
 
288
                                }
 
289
 
 
290
                                case 3:
 
291
                                        if (pos < strlen(line) && pos
 
292
                                            && WHITECHAR(line[pos - 1])
 
293
                                            && !WHITECHAR(line[pos])) {
 
294
                                                ll = line + pos;
 
295
                                        } else {
 
296
                                                for (ll = lll; *ll; ll++)
 
297
                                                        if (!WHITECHAR(*ll))
 
298
                                                                break;
 
299
                                        }
 
300
                                        for (lll = ll; *lll; lll++)
 
301
                                                if (WHITECHAR(*lll))
 
302
                                                        break;
 
303
                                        /* Fall-through */
 
304
 
 
305
                                case 2:
 
306
                                        add_bytes_to_string(&page, line, ll - line);
 
307
                                        add_to_string(&page, "<a href=\"smb://");
 
308
                                        add_bytes_to_string(&page, ll, lll - ll);
 
309
                                        add_to_string(&page, "/\">");
 
310
                                        add_bytes_to_string(&page, ll, lll - ll);
 
311
                                        add_to_string(&page, "</a>");
 
312
                                        add_to_string(&page, lll);
 
313
                                        break;
 
314
 
 
315
                                default:
 
316
                                        goto print_as_is;
 
317
                                }
 
318
 
 
319
                        } else if (si->list_type == SMB_LIST_DIR) {
 
320
                                if (strstr(line, "NT_STATUS")) {
 
321
                                        line_end[1] = '\0';
 
322
                                        goto print_as_is;
 
323
                                }
 
324
 
 
325
                                if (line_end2 - line_start >= 5
 
326
                                    && line_start[0] == ' '
 
327
                                    && line_start[1] == ' '
 
328
                                    && line_start[2] != ' ') {
 
329
                                        int dir = 0;
 
330
                                        unsigned char *pp;
 
331
                                        unsigned char *p = line_start + 3;
 
332
                                        unsigned char *url = p - 1;
 
333
 
 
334
                                        while (p + 2 <= line_end2) {
 
335
                                                if (p[0] == ' ' && p[1] == ' ')
 
336
                                                        goto is_a_file_entry;
 
337
                                                p++;
 
338
                                        }
 
339
                                        goto print_as_is;
 
340
 
 
341
is_a_file_entry:
 
342
                                        pp = p;
 
343
                                        while (pp < line_end2 && *pp == ' ')
 
344
                                                pp++;
 
345
                                        while (pp < line_end2 && *pp != ' ') {
 
346
                                                if (*pp == 'D') {
 
347
                                                        dir = 1;
 
348
                                                        break;
 
349
                                                }
 
350
                                                pp++;
 
351
                                        }
 
352
 
 
353
                                        if (*url == '.' && p - url == 1) goto ignored;
 
354
 
 
355
                                        add_to_string(&page, "  <a href=\"");
 
356
                                        add_bytes_to_string(&page, url, p - url);
 
357
                                        if (dir) add_char_to_string(&page, '/');
 
358
                                        add_to_string(&page, "\">");
 
359
                                        add_bytes_to_string(&page, url, p - url);
 
360
                                        add_to_string(&page, "</a>");
 
361
                                        add_bytes_to_string(&page, p, line_end - p);
 
362
 
 
363
                                } else {
 
364
                                        goto print_as_is;
 
365
                                }
 
366
 
 
367
                        } else {
 
368
print_as_is:
 
369
                                add_bytes_to_string(&page, line_start, line_end2 - line_start);
 
370
                        }
 
371
 
 
372
                        add_char_to_string(&page, '\n');
 
373
ignored:
 
374
                        line_start = line_end + 1;
 
375
                        mem_free(line);
 
376
                }
 
377
 
 
378
                add_to_string(&page, "</pre></body></html>");
 
379
 
 
380
                add_fragment(conn->cache, 0, page.source, page.length);
 
381
                conn->from += page.length;
 
382
                truncate_entry(conn->cache, page.length, 1);
 
383
                conn->cache->incomplete = 0;
 
384
                done_string(&page);
 
385
 
 
386
                if (!conn->cache->head)
 
387
                        conn->cache->head = stracpy("\r\n");
 
388
                add_to_strn(&conn->cache->head, "Content-Type: text/html\r\n");
 
389
        }
 
390
 
 
391
bye:
 
392
        close_socket(conn, &conn->socket);
 
393
        close_socket(conn, &conn->data_socket);
 
394
        abort_conn_with_state(conn, S_OK);
 
395
}
 
396
 
 
397
 
 
398
/* Close all non-terminal file descriptors. */
 
399
static void
 
400
close_all_non_term_fd(void)
 
401
{
 
402
        int n;
 
403
        int max = 1024;
 
404
#ifdef RLIMIT_NOFILE
 
405
        struct rlimit lim;
 
406
 
 
407
        if (!getrlimit(RLIMIT_NOFILE, &lim))
 
408
                max = lim.rlim_max;
 
409
#endif
 
410
        for (n = 3; n < max; n++)
 
411
                close(n);
 
412
}
 
413
 
 
414
static void
 
415
smb_func(struct connection *conn)
 
416
{
 
417
        int out_pipe[2] = { -1, -1 };
 
418
        int err_pipe[2] = { -1, -1 };
 
419
        unsigned char *share, *dir;
 
420
        unsigned char *p;
 
421
        int cpid, dirlen;
 
422
        struct smb_connection_info *si;
 
423
 
 
424
        si = mem_calloc(1, sizeof(struct smb_connection_info) + 2);
 
425
        if (!si) {
 
426
                abort_conn_with_state(conn, S_OUT_OF_MEM);
 
427
                return;
 
428
        }
 
429
        conn->info = si;
 
430
 
 
431
        p = strchr(conn->uri.data, '/');
 
432
        if (p && p - conn->uri.data < conn->uri.datalen) {
 
433
                share = memacpy(conn->uri.data, p - conn->uri.data);
 
434
                dir = p + 1;
 
435
                /* FIXME: ensure @dir do not contain dangerous chars. --Zas */
 
436
 
 
437
        } else if (conn->uri.datalen) {
 
438
                if (smb_get_cache(conn)) return;
 
439
 
 
440
                if (conn->cache->redirect) mem_free(conn->cache->redirect);
 
441
                conn->cache->redirect = stracpy(struri(conn->uri));
 
442
                conn->cache->redirect_get = 1;
 
443
                add_to_strn(&conn->cache->redirect, "/");
 
444
 
 
445
                conn->cache->incomplete = 0;
 
446
                abort_conn_with_state(conn, S_OK);
 
447
                return;
 
448
 
 
449
        } else {
 
450
                share = stracpy("");
 
451
                dir = "";
 
452
        }
 
453
 
 
454
        if (!share) {
 
455
                abort_conn_with_state(conn, S_OUT_OF_MEM);
 
456
                return;
 
457
        }
 
458
 
 
459
        dirlen = strlen(dir);
 
460
        if (!*share) {
 
461
                si->list_type = SMB_LIST_SHARES;
 
462
        } else if (!dirlen || dir[dirlen - 1] == '/'
 
463
                   || dir[dirlen - 1] == '\\') {
 
464
                si->list_type = SMB_LIST_DIR;
 
465
        }
 
466
 
 
467
        if (c_pipe(out_pipe) || c_pipe(err_pipe)) {
 
468
                int s_errno = errno;
 
469
 
 
470
                if (out_pipe[0] >= 0) close(out_pipe[0]);
 
471
                if (out_pipe[1] >= 0) close(out_pipe[1]);
 
472
                mem_free(share);
 
473
                abort_conn_with_state(conn, -s_errno);
 
474
                return;
 
475
        }
 
476
 
 
477
        conn->from = 0;
 
478
 
 
479
        cpid = fork();
 
480
        if (cpid == -1) {
 
481
                int s_errno = errno;
 
482
 
 
483
                close(out_pipe[0]);
 
484
                close(out_pipe[1]);
 
485
                close(err_pipe[0]);
 
486
                close(err_pipe[1]);
 
487
                mem_free(share);
 
488
                retry_conn_with_state(conn, -s_errno);
 
489
                return;
 
490
        }
 
491
 
 
492
        if (!cpid) {
 
493
#define MAX_SMBCLIENT_ARGS 32
 
494
                int n = 0;
 
495
                unsigned char *v[MAX_SMBCLIENT_ARGS];
 
496
 
 
497
                close(1);
 
498
                dup2(out_pipe[1], 1);
 
499
                close(2);
 
500
                dup2(err_pipe[1], 2);
 
501
                close(0);
 
502
                dup2(open("/dev/null", O_RDONLY), 0);
 
503
 
 
504
                close_all_non_term_fd();
 
505
                close(out_pipe[0]);
 
506
                close(err_pipe[0]);
 
507
 
 
508
                v[n++] = "smbclient";
 
509
 
 
510
                /* FIXME: handle alloc failures. */
 
511
                /* At this point, we are the child process.
 
512
                 * Maybe we just don't care if the child kills itself
 
513
                 * dereferencing a NULL pointer... -- Miciah */
 
514
                /* Leaving random core files after itself is not what a nice
 
515
                 * program does. Also, the user might also want to know, why
 
516
                 * the hell does he see nothing on the screen. --pasky */
 
517
 
 
518
                if (!*share) {
 
519
                        v[n++] = "-L";  /* get a list of shares available on a host */
 
520
                        v[n++] = memacpy(conn->uri.host, conn->uri.hostlen);
 
521
 
 
522
                } else {
 
523
                        /* Construct path. */
 
524
                        asprintf((char **) &v[n++], "//%.*s/%s",
 
525
                                 conn->uri.hostlen, conn->uri.host, share);
 
526
                        /* XXX: add password to argument if any. TODO: Recheck
 
527
                         * if correct. --Zas. */
 
528
                        if (conn->uri.passwordlen && !conn->uri.userlen) {
 
529
                                v[n++] = memacpy(conn->uri.password, conn->uri.passwordlen);
 
530
                        }
 
531
                }
 
532
 
 
533
                v[n++] = "-N";          /* don't ask for a password */
 
534
                v[n++] = "-E";          /* write messages to stderr instead of stdout */
 
535
                v[n++] = "-d 0";        /* disable debug mode. */
 
536
 
 
537
                if (conn->uri.portlen) {
 
538
                        v[n++] = "-p";  /* connect to the specified port */
 
539
                        v[n++] = memacpy(conn->uri.port, conn->uri.portlen);
 
540
                }
 
541
 
 
542
                if (conn->uri.userlen) {
 
543
                        v[n++] = "-U";  /* set the network username */
 
544
                        if (!conn->uri.passwordlen) {
 
545
                                /* No password. */
 
546
                                v[n++] = memacpy(conn->uri.user, conn->uri.userlen);
 
547
                        } else {
 
548
                                /* With password. */
 
549
                                asprintf((char **) &v[n++], "%.*s%%%.*s",
 
550
                                         conn->uri.userlen, conn->uri.user,
 
551
                                         conn->uri.passwordlen, conn->uri.password);
 
552
                        }
 
553
                }
 
554
 
 
555
                if (*share) {
 
556
                        /* FIXME: use si->list_type here ?? --Zas */
 
557
                        if (!dirlen || dir[dirlen - 1] == '/' || dir[dirlen - 1] == '\\') {
 
558
                                if (dirlen) {
 
559
                                        v[n++] = "-D";  /* start from directory */
 
560
                                        v[n++] = dir;
 
561
                                }
 
562
                                v[n++] = "-c"; /* execute semicolon separated commands */
 
563
                                v[n++] = "ls";
 
564
 
 
565
                        } else {
 
566
                                unsigned char *s = straconcat("get \"", dir, "\" -", NULL);
 
567
                                unsigned char *ss = s;
 
568
 
 
569
                                v[n++] = "-c"; /* execute semicolon separated commands */
 
570
                                while ((ss = strchr(ss, '/'))) *ss = '\\';
 
571
                                v[n++] = s;
 
572
                        }
 
573
                }
 
574
 
 
575
                v[n++] = NULL;
 
576
                assert(n < MAX_SMBCLIENT_ARGS);
 
577
 
 
578
                execvp("smbclient", (char **) v);
 
579
 
 
580
                fprintf(stderr, "smbclient not found in $PATH");
 
581
                _exit(1);
 
582
#undef MAX_SMBCLIENT_ARGS
 
583
        }
 
584
 
 
585
        mem_free(share);
 
586
 
 
587
        conn->data_socket = out_pipe[0];
 
588
        conn->socket = err_pipe[0];
 
589
 
 
590
        close(out_pipe[1]);
 
591
        close(err_pipe[1]);
 
592
 
 
593
        set_handlers(out_pipe[0], (void (*)(void *)) smb_got_data, NULL, NULL, conn);
 
594
        set_handlers(err_pipe[0], (void (*)(void *)) smb_got_text, NULL, NULL, conn);
 
595
        set_connection_state(conn, S_CONN);
 
596
}
 
597
 
 
598
 
 
599
struct protocol_backend smb_protocol_backend = {
 
600
        /* name: */                     "smb",
 
601
        /* port: */                     139,
 
602
        /* handler: */                  smb_func,
 
603
        /* external_handler: */         NULL,
 
604
        /* free_syntax: */              0,
 
605
        /* need_slashes: */             1,
 
606
        /* need_slash_after_host: */    1,
 
607
};
 
608
 
 
609
#endif /* CONFIG_SMB */