Sync usage with man page.
[netbsd-mini2440.git] / dist / smbfs / lib / smb / ctx.c
blob040c89a4f44c2b559355d3c452a1aeb5528aa00a
1 /*
2 * Copyright (c) 2000-2002, Boris Popov
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * from: Id: ctx.c,v 1.24 2002/04/13 14:35:28 bp Exp
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: ctx.c,v 1.14 2009/09/06 18:38:17 pooka Exp $");
38 #include <sys/param.h>
39 #include <sys/sysctl.h>
40 #include <sys/ioctl.h>
41 #include <sys/time.h>
42 #include <sys/mount.h>
43 #include <fcntl.h>
44 #include <ctype.h>
45 #include <errno.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <stdlib.h>
49 #include <pwd.h>
50 #include <grp.h>
51 #include <unistd.h>
52 #include <netsmb/iconv.h>
54 #define NB_NEEDRESOLVER
56 #include <netsmb/smb_lib.h>
57 #include <netsmb/netbios.h>
58 #include <netsmb/nb_lib.h>
59 #include <netsmb/smb_conn.h>
60 #include <cflib.h>
62 #include "smb_kernelops.h"
65 * Prescan command line for [-U user] argument
66 * and fill context with defaults
68 int
69 smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[],
70 int minlevel, int maxlevel, int sharetype)
72 int opt, error = 0;
73 uid_t euid;
74 const char *arg, *cp;
75 struct passwd *pwd;
77 bzero(ctx,sizeof(*ctx));
78 error = nb_ctx_create(&ctx->ct_nb);
79 if (error)
80 return error;
81 ctx->ct_fd = -1;
82 ctx->ct_parsedlevel = SMBL_NONE;
83 ctx->ct_minlevel = minlevel;
84 ctx->ct_maxlevel = maxlevel;
86 ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE;
87 ctx->ct_ssn.ioc_timeout = 15;
88 ctx->ct_ssn.ioc_retrycount = 4;
89 ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER;
90 ctx->ct_ssn.ioc_group = SMBM_ANY_GROUP;
91 ctx->ct_ssn.ioc_mode = SMBM_EXEC;
92 ctx->ct_ssn.ioc_rights = SMBM_DEFAULT;
94 ctx->ct_sh.ioc_opt = SMBVOPT_CREATE;
95 ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
96 ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
97 ctx->ct_sh.ioc_mode = SMBM_EXEC;
98 ctx->ct_sh.ioc_rights = SMBM_DEFAULT;
99 ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
100 ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
102 nb_ctx_setscope(ctx->ct_nb, "");
103 euid = geteuid();
104 if ((pwd = getpwuid(euid)) != NULL) {
105 smb_ctx_setuser(ctx, pwd->pw_name);
106 endpwent();
107 } else if (euid == 0)
108 smb_ctx_setuser(ctx, "root");
109 else
110 return 0;
111 if (argv == NULL)
112 return 0;
113 for (opt = 1; opt < argc; opt++) {
114 cp = argv[opt];
115 if (strncmp(cp, "//", 2) != 0)
116 continue;
117 error = smb_ctx_parseunc(ctx, cp, sharetype, (const char**)&cp);
118 if (error)
119 return error;
120 ctx->ct_uncnext = cp;
121 break;
123 while (error == 0 && (opt = cf_getopt(argc, argv, ":E:L:U:")) != -1) {
124 arg = cf_optarg;
125 switch (opt) {
126 case 'E':
127 error = smb_ctx_setcharset(ctx, arg);
128 if (error)
129 return error;
130 break;
131 case 'L':
132 error = nls_setlocale(optarg);
133 if (error)
134 break;
135 break;
136 case 'U':
137 error = smb_ctx_setuser(ctx, arg);
138 break;
141 cf_optind = cf_optreset = 1;
142 return error;
145 void
146 smb_ctx_done(struct smb_ctx *ctx)
148 if (ctx->ct_ssn.ioc_server)
149 nb_snbfree(ctx->ct_ssn.ioc_server);
150 if (ctx->ct_ssn.ioc_local)
151 nb_snbfree(ctx->ct_ssn.ioc_local);
152 if (ctx->ct_srvaddr)
153 free(ctx->ct_srvaddr);
154 if (ctx->ct_nb)
155 nb_ctx_done(ctx->ct_nb);
158 static int
159 getsubstring(const char *p, u_char sep, char *dest, int maxlen, const char **next)
161 int len;
163 maxlen--;
164 for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) {
165 if (*p == 0)
166 return EINVAL;
167 *dest = *p;
169 *dest = 0;
170 *next = *p ? p + 1 : p;
171 return 0;
175 * Here we expect something like "[proto:]//[user@]host[/share][/path]"
178 smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype,
179 const char **next)
181 const char *p = unc;
182 char *p1;
183 char tmp[1024];
184 int error ;
186 ctx->ct_parsedlevel = SMBL_NONE;
187 if (*p++ != '/' || *p++ != '/') {
188 smb_error("UNC should start with '//'", 0);
189 return EINVAL;
191 p1 = tmp;
192 error = getsubstring(p, '@', p1, sizeof(tmp), &p);
193 if (!error) {
194 if (ctx->ct_maxlevel < SMBL_VC) {
195 smb_error("no user name required", 0);
196 return EINVAL;
198 if (*p1 == 0) {
199 smb_error("empty user name", 0);
200 return EINVAL;
202 error = smb_ctx_setuser(ctx, tmp);
203 if (error)
204 return error;
205 ctx->ct_parsedlevel = SMBL_VC;
207 error = getsubstring(p, '/', p1, sizeof(tmp), &p);
208 if (error) {
209 error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
210 if (error) {
211 smb_error("no server name found", 0);
212 return error;
215 if (*p1 == 0) {
216 smb_error("empty server name", 0);
217 return EINVAL;
219 error = smb_ctx_setserver(ctx, tmp);
220 if (error)
221 return error;
222 if (sharetype == SMB_ST_NONE) {
223 *next = p;
224 return 0;
226 if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
227 smb_error("no share name required", 0);
228 return EINVAL;
230 error = getsubstring(p, '/', p1, sizeof(tmp), &p);
231 if (error) {
232 error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
233 if (error) {
234 smb_error("unexpected end of line", 0);
235 return error;
238 if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) {
239 smb_error("empty share name", 0);
240 return EINVAL;
242 *next = p;
243 if (*p1 == 0)
244 return 0;
245 error = smb_ctx_setshare(ctx, p1, sharetype);
246 return error;
250 smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg)
252 char *cp, *servercs, *localcs;
253 int cslen = sizeof(ctx->ct_ssn.ioc_localcs);
254 int scslen, lcslen, error;
256 cp = strchr(arg, ':');
257 lcslen = cp ? (cp - arg) : 0;
258 if (lcslen == 0 || lcslen >= cslen) {
259 smb_error("invalid local charset specification (%s)", 0, arg);
260 return EINVAL;
262 scslen = (size_t)strlen(++cp);
263 if (scslen == 0 || scslen >= cslen) {
264 smb_error("invalid server charset specification (%s)", 0, arg);
265 return EINVAL;
267 localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen);
268 localcs[lcslen] = 0;
269 servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp);
270 error = nls_setrecode(localcs, servercs);
271 if (error == 0)
272 return 0;
273 smb_error("can't initialize iconv support (%s:%s)",
274 error, localcs, servercs);
275 localcs[0] = 0;
276 servercs[0] = 0;
277 return error;
281 smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
283 char *d;
286 * If the name contains dot, it's likely a IP address
287 * or a name. Update srvaddr in that case, and use
288 * first part of the name (up to the dot) as NetBIOS name.
290 if ((d = strchr(name, '.'))) {
291 static char nm[sizeof(ctx->ct_ssn.ioc_srvname)];
292 int error;
294 error = smb_ctx_setsrvaddr(ctx, name);
295 if (error)
296 return (error);
298 /* cut name to MAXSRVNAMELEN */
299 if (strlen(name) >= sizeof(ctx->ct_ssn.ioc_srvname)) {
300 snprintf(nm, sizeof(nm), "%.*s",
301 (int)(sizeof(ctx->ct_ssn.ioc_srvname) - 1), name);
302 name = nm;
306 if (strlen(name) >= sizeof(ctx->ct_ssn.ioc_srvname)) {
307 smb_error("server name '%s' too long", 0, name);
308 return ENAMETOOLONG;
310 nls_str_upper(ctx->ct_ssn.ioc_srvname, name);
311 return 0;
315 smb_ctx_setuser(struct smb_ctx *ctx, const char *name)
317 if (strlen(name) >= sizeof(ctx->ct_ssn.ioc_user)) {
318 smb_error("user name '%s' too long", 0, name);
319 return ENAMETOOLONG;
321 nls_str_upper(ctx->ct_ssn.ioc_user, name);
322 return 0;
326 smb_ctx_setworkgroup(struct smb_ctx *ctx, const char *name)
328 if (strlen(name) >= SMB_MAXUSERNAMELEN) {
329 smb_error("workgroup name '%s' too long", 0, name);
330 return ENAMETOOLONG;
332 nls_str_upper(ctx->ct_ssn.ioc_workgroup, name);
333 return 0;
337 smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd)
339 if (passwd == NULL)
340 return EINVAL;
341 if (strlen(passwd) >= SMB_MAXPASSWORDLEN) {
342 smb_error("password too long", 0);
343 return ENAMETOOLONG;
345 if (strncmp(passwd, "$$1", 3) == 0)
346 smb_simpledecrypt(ctx->ct_ssn.ioc_password, passwd);
347 else
348 strcpy(ctx->ct_ssn.ioc_password, passwd);
349 strcpy(ctx->ct_sh.ioc_password, ctx->ct_ssn.ioc_password);
350 return 0;
354 smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype)
356 if (strlen(share) >= SMB_MAXSHARENAMELEN) {
357 smb_error("share name '%s' too long", 0, share);
358 return ENAMETOOLONG;
360 nls_str_upper(ctx->ct_sh.ioc_share, share);
361 if (share[0] != 0)
362 ctx->ct_parsedlevel = SMBL_SHARE;
363 ctx->ct_sh.ioc_stype = stype;
364 return 0;
368 smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr)
370 if (addr == NULL || addr[0] == 0)
371 return EINVAL;
372 if (ctx->ct_srvaddr)
373 free(ctx->ct_srvaddr);
374 if ((ctx->ct_srvaddr = strdup(addr)) == NULL)
375 return ENOMEM;
376 return 0;
379 static int
380 smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
382 struct group *gr;
383 struct passwd *pw;
384 char *cp;
386 cp = strchr(pair, ':');
387 if (cp) {
388 *cp++ = '\0';
389 if (*cp) {
390 gr = getgrnam(cp);
391 if (gr) {
392 *gid = gr->gr_gid;
393 } else
394 smb_error("Invalid group name '%s', ignored",
395 0, cp);
398 if (*pair) {
399 pw = getpwnam(pair);
400 if (pw) {
401 *uid = pw->pw_uid;
402 } else
403 smb_error("Invalid user name '%s', ignored", 0, pair);
405 endpwent();
406 return 0;
410 smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg)
412 int error = 0;
413 char *p, *cp;
415 switch(opt) {
416 case 'U':
417 break;
418 case 'I':
419 error = smb_ctx_setsrvaddr(ctx, arg);
420 break;
421 case 'M':
422 ctx->ct_ssn.ioc_rights = strtol(arg, &cp, 8);
423 if (*cp == '/') {
424 ctx->ct_sh.ioc_rights = strtol(cp + 1, &cp, 8);
425 ctx->ct_flags |= SMBCF_SRIGHTS;
427 break;
428 case 'N':
429 ctx->ct_flags |= SMBCF_NOPWD;
430 break;
431 case 'O':
432 p = strdup(arg);
433 cp = strchr(p, '/');
434 if (cp) {
435 *cp++ = '\0';
436 error = smb_parse_owner(cp, &ctx->ct_sh.ioc_owner,
437 &ctx->ct_sh.ioc_group);
439 if (*p && error == 0) {
440 error = smb_parse_owner(p, &ctx->ct_ssn.ioc_owner,
441 &ctx->ct_ssn.ioc_group);
443 free(p);
444 break;
445 case 'P':
446 /* ctx->ct_ssn.ioc_opt |= SMBCOPT_PERMANENT;*/
447 break;
448 case 'R':
449 ctx->ct_ssn.ioc_retrycount = atoi(arg);
450 break;
451 case 'T':
452 ctx->ct_ssn.ioc_timeout = atoi(arg);
453 break;
454 case 'W':
455 error = smb_ctx_setworkgroup(ctx, arg);
456 break;
458 return error;
461 #if 0
462 static void
463 smb_hexdump(const u_char *buf, int len) {
464 int ofs = 0;
466 while (len--) {
467 if (ofs % 16 == 0)
468 printf("\n%02X: ", ofs);
469 printf("%02x ", *buf++);
470 ofs++;
472 printf("\n");
474 #endif
477 static int
478 smb_addiconvtbl(const char *to, const char *from, const u_char *tbl)
480 int error;
482 error = kiconv_add_xlat_table(to, from, tbl);
483 if (error && error != EEXIST) {
484 smb_error("can not setup kernel iconv table (%s:%s)", error,
485 from, to);
486 return error;
488 return 0;
492 * Verify context before connect operation(s),
493 * lookup specified server and try to fill all forgotten fields.
496 smb_ctx_resolve(struct smb_ctx *ctx)
498 struct smbioc_ossn *ssn = &ctx->ct_ssn;
499 struct smbioc_oshare *sh = &ctx->ct_sh;
500 struct nb_name nn;
501 struct sockaddr *sap;
502 struct sockaddr_nb *salocal, *saserver;
503 char *cp;
504 u_char cstbl[256];
505 u_int i;
506 int error = 0;
508 ctx->ct_flags &= ~SMBCF_RESOLVED;
509 if (ssn->ioc_srvname[0] == 0) {
510 smb_error("no server name specified", 0);
511 return EINVAL;
513 if (ssn->ioc_user[0] == 0) {
514 smb_error("no user name specified for server %s",
515 0, ssn->ioc_srvname);
516 return EINVAL;
518 if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) {
519 smb_error("no share name specified for %s@%s",
520 0, ssn->ioc_user, ssn->ioc_srvname);
521 return EINVAL;
523 error = nb_ctx_resolve(ctx->ct_nb);
524 if (error)
525 return error;
526 if (ssn->ioc_localcs[0] == 0)
527 strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */
528 error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower);
529 if (error)
530 return error;
531 error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper);
532 if (error)
533 return error;
534 if (ssn->ioc_servercs[0] != 0) {
535 for(i = 0; i < sizeof(cstbl); i++)
536 cstbl[i] = i;
537 nls_mem_toext(cstbl, cstbl, sizeof(cstbl));
538 error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, cstbl);
539 if (error)
540 return error;
541 for(i = 0; i < sizeof(cstbl); i++)
542 cstbl[i] = i;
543 nls_mem_toloc(cstbl, cstbl, sizeof(cstbl));
544 error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, cstbl);
545 if (error)
546 return error;
548 if (ctx->ct_srvaddr) {
549 error = nb_resolvehost_in(ctx->ct_srvaddr, &sap);
550 } else {
551 error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap);
553 if (error) {
554 smb_error("can't get server address", error);
555 return error;
557 nn.nn_scope = ctx->ct_nb->nb_scope;
558 nn.nn_type = NBT_SERVER;
559 strcpy(nn.nn_name, ssn->ioc_srvname);
560 error = nb_sockaddr(sap, &nn, &saserver);
561 nb_snbfree(sap);
562 if (error) {
563 smb_error("can't allocate server address", error);
564 return error;
566 ssn->ioc_server = (struct sockaddr*)saserver;
567 if (ctx->ct_locname[0] == 0) {
568 error = nb_getlocalname(ctx->ct_locname);
569 if (error) {
570 smb_error("can't get local name", error);
571 return error;
573 nls_str_upper(ctx->ct_locname, ctx->ct_locname);
575 strcpy(nn.nn_name, ctx->ct_locname);
576 nn.nn_type = NBT_WKSTA;
577 nn.nn_scope = ctx->ct_nb->nb_scope;
578 error = nb_sockaddr(NULL, &nn, &salocal);
579 if (error) {
580 nb_snbfree((struct sockaddr*)saserver);
581 smb_error("can't allocate local address", error);
582 return error;
584 ssn->ioc_local = (struct sockaddr*)salocal;
585 ssn->ioc_lolen = salocal->snb_len;
586 ssn->ioc_svlen = saserver->snb_len;
587 if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) {
588 cp = getpass("Password:");
589 error = smb_ctx_setpassword(ctx, cp);
590 if (error)
591 return error;
593 ctx->ct_flags |= SMBCF_RESOLVED;
594 return 0;
597 static int
598 smb_ctx_gethandle(struct smb_ctx *ctx)
600 int fd, i;
601 char buf[20];
604 * First, try to open as cloned device
606 fd = smb_kops.ko_open("/dev/"NSMB_NAME, O_RDWR, 0);
607 if (fd >= 0) {
608 ctx->ct_fd = fd;
609 return 0;
613 * well, no clone capabilities available - we have to scan
614 * all devices in order to get free one
616 for (i = 0; i < 1024; i++) {
617 snprintf(buf, sizeof(buf), "/dev/"NSMB_NAME"%d", i);
618 fd = smb_kops.ko_open(buf, O_RDWR, 0);
619 if (fd >= 0) {
620 ctx->ct_fd = fd;
621 return 0;
623 if (errno == ENOENT)
624 return ENOENT;
627 return ENOENT;
631 smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags)
633 struct smbioc_lookup rq;
634 int error;
636 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
637 smb_error("smb_ctx_lookup() data is not resolved", 0);
638 return EINVAL;
640 if (ctx->ct_fd != -1) {
641 smb_kops.ko_close(ctx->ct_fd);
642 ctx->ct_fd = -1;
644 error = smb_ctx_gethandle(ctx);
645 if (error) {
646 smb_error("can't get handle to requester (no /dev/"NSMB_NAME"* device available)", 0);
647 return EINVAL;
649 bzero(&rq, sizeof(rq));
650 bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn));
651 bcopy(&ctx->ct_sh, &rq.ioc_sh, sizeof(struct smbioc_oshare));
652 rq.ioc_flags = flags;
653 rq.ioc_level = level;
654 if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) {
655 error = errno;
657 smb_kops.ko_close(ctx->ct_fd);
658 ctx->ct_fd = -1;
661 * Fallback to *SMBSERVER as NetBIOS name. At least
662 * Windows NT and Windows XP require this (or valid
663 * NetBIOS server name), otherwise they refuse connection.
665 if (smb_ctx_setserver(ctx, "*SMBSERVER") != 0)
666 goto fail;
668 error = smb_ctx_resolve(ctx);
669 if (error)
670 goto fail;
672 error = smb_ctx_gethandle(ctx);
673 if (error)
674 goto fail;
676 bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn));
678 if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) != -1)
679 goto success;
680 error = errno;
682 fail:
683 if (flags & SMBLK_CREATE)
684 smb_error("unable to open connection", error);
685 return error;
688 success:
689 return 0;
693 smb_ctx_login(struct smb_ctx *ctx)
695 struct smbioc_ossn *ssn = &ctx->ct_ssn;
696 struct smbioc_oshare *sh = &ctx->ct_sh;
697 int error;
699 if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
700 smb_error("smb_ctx_resolve() should be called first", 0);
701 return EINVAL;
703 if (ctx->ct_fd != -1) {
704 smb_kops.ko_close(ctx->ct_fd);
705 ctx->ct_fd = -1;
707 error = smb_ctx_gethandle(ctx);
708 if (error) {
709 smb_error("can't get handle to requester", 0);
710 return EINVAL;
712 if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_OPENSESSION, ssn) == -1) {
713 error = errno;
714 smb_error("can't open session to server %s", error, ssn->ioc_srvname);
715 return error;
717 if (sh->ioc_share[0] == 0)
718 return 0;
719 if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_OPENSHARE, sh) == -1) {
720 error = errno;
721 smb_error("can't connect to share //%s/%s", error,
722 ssn->ioc_srvname, sh->ioc_share);
723 return error;
725 return 0;
729 smb_ctx_setflags(struct smb_ctx *ctx, int level, int mask, int flags)
731 struct smbioc_flags fl;
733 if (ctx->ct_fd == -1)
734 return EINVAL;
735 fl.ioc_level = level;
736 fl.ioc_mask = mask;
737 fl.ioc_flags = flags;
738 if (smb_kops.ko_ioctl(ctx->ct_fd, SMBIOC_SETFLAGS, &fl) == -1)
739 return errno;
740 return 0;
744 * level values:
745 * 0 - default
746 * 1 - server
747 * 2 - server:user
748 * 3 - server:user:share
750 static int
751 smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
753 char *p;
754 int error;
756 if (level >= 0) {
757 rc_getstringptr(smb_rc, sname, "charsets", &p);
758 if (p) {
759 error = smb_ctx_setcharset(ctx, p);
760 if (error)
761 smb_error("charset specification in the section '%s' ignored", error, sname);
764 if (level <= 1) {
765 rc_getint(smb_rc, sname, "timeout", &ctx->ct_ssn.ioc_timeout);
766 rc_getint(smb_rc, sname, "retry_count", &ctx->ct_ssn.ioc_retrycount);
768 if (level == 1) {
769 rc_getstringptr(smb_rc, sname, "addr", &p);
770 if (p) {
771 error = smb_ctx_setsrvaddr(ctx, p);
772 if (error) {
773 smb_error("invalid address specified in the section %s", 0, sname);
774 return error;
778 if (level >= 2) {
779 rc_getstringptr(smb_rc, sname, "password", &p);
780 if (p)
781 smb_ctx_setpassword(ctx, p);
783 rc_getstringptr(smb_rc, sname, "workgroup", &p);
784 if (p)
785 smb_ctx_setworkgroup(ctx, p);
786 return 0;
790 * read rc file as follows:
791 * 1. read [default] section
792 * 2. override with [server] section
793 * 3. override with [server:user:share] section
794 * Since abcence of rcfile is not fatal, silently ignore this fact.
795 * smb_rc file should be closed by caller.
798 smb_ctx_readrc(struct smb_ctx *ctx)
800 char sname[SMB_MAXSRVNAMELEN + SMB_MAXUSERNAMELEN + SMB_MAXSHARENAMELEN + 4];
801 /* char *p;*/
803 if (smb_open_rcfile() != 0)
804 return 0;
806 if (ctx->ct_ssn.ioc_user[0] == 0 || ctx->ct_ssn.ioc_srvname[0] == 0)
807 return 0;
809 smb_ctx_readrcsection(ctx, "default", 0);
810 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0);
811 smb_ctx_readrcsection(ctx, ctx->ct_ssn.ioc_srvname, 1);
812 nb_ctx_readrcsection(smb_rc, ctx->ct_nb, ctx->ct_ssn.ioc_srvname, 1);
814 * SERVER:USER parameters
816 snprintf(sname, sizeof(sname), "%s:%s", ctx->ct_ssn.ioc_srvname,
817 ctx->ct_ssn.ioc_user);
818 smb_ctx_readrcsection(ctx, sname, 2);
820 if (ctx->ct_sh.ioc_share[0] != 0) {
822 * SERVER:USER:SHARE parameters
824 snprintf(sname, sizeof(sname), "%s:%s:%s", ctx->ct_ssn.ioc_srvname,
825 ctx->ct_ssn.ioc_user, ctx->ct_sh.ioc_share);
826 smb_ctx_readrcsection(ctx, sname, 3);
828 return 0;