9
#include <sys/utsname.h>
10
#include <sys/socket.h>
11
#include <arpa/inet.h>
18
#define MOUNT_CIFS_VERSION "1"
20
extern char *getusername(void);
24
static int got_password = 0;
25
static int got_user = 0;
26
static int got_domain = 0;
27
static int got_ip = 0;
28
static int got_unc = 0;
29
static int got_uid = 0;
30
static int got_gid = 0;
31
static char * user_name = NULL;
32
char * mountpassword = NULL;
35
void mount_cifs_usage()
37
printf("\nUsage: %s remotetarget dir\n", thisprogram);
38
printf("\nMount the remotetarget, specified as either a UNC name or ");
39
printf(" CIFS URL, to the local directory, dir.\n");
44
/* caller frees username if necessary */
45
char * getusername() {
46
char *username = NULL;
47
struct passwd *password = getpwuid(getuid());
50
username = password->pw_name;
55
char * parse_cifs_url(unc_name)
57
printf("\ncifs url %s\n",unc_name);
60
int parse_options(char * options)
68
while ((data = strsep(&options, ",")) != NULL) {
71
if ((value = strchr(data, '=')) != NULL) {
74
if (strncmp(data, "user", 4) == 0) {
75
if (!value || !*value) {
76
printf("invalid or missing username\n");
77
return 1; /* needs_arg; */
79
if (strnlen(value, 260) < 260) {
81
/* BB add check for format user%pass */
82
/* if(strchr(username%passw) got_password = 1) */
84
printf("username too long\n");
87
} else if (strncmp(data, "pass", 4) == 0) {
88
if (!value || !*value) {
90
printf("password specified twice, ignoring second\n");
93
} else if (strnlen(value, 17) < 17) {
96
printf("password too long\n");
99
} else if (strncmp(data, "ip", 2) == 0) {
100
if (!value || !*value) {
101
printf("target ip address argument missing");
102
} else if (strnlen(value, 35) < 35) {
105
printf("ip address too long\n");
108
} else if ((strncmp(data, "unc", 3) == 0)
109
|| (strncmp(data, "target", 6) == 0)
110
|| (strncmp(data, "path", 4) == 0)) {
111
if (!value || !*value) {
112
printf("invalid path to network resource\n");
113
return 1; /* needs_arg; */
114
} else if(strnlen(value,5) < 5) {
115
printf("UNC name too short");
118
if (strnlen(value, 300) < 300) {
120
if (strncmp(value, "//", 2) == 0) {
122
printf("unc name specified twice, ignoring second\n");
125
} else if (strncmp(value, "\\\\", 2) != 0) {
126
printf("UNC Path does not begin with // or \\\\ \n");
130
printf("unc name specified twice, ignoring second\n");
135
printf("CIFS: UNC name too long\n");
138
} else if ((strncmp(data, "domain", 3) == 0)
139
|| (strncmp(data, "workgroup", 5) == 0)) {
140
if (!value || !*value) {
141
printf("CIFS: invalid domain name\n");
142
return 1; /* needs_arg; */
144
if (strnlen(value, 65) < 65) {
147
printf("domain name too long\n");
150
} else if (strncmp(data, "uid", 3) == 0) {
151
if (value && *value) {
154
} else if (strncmp(data, "gid", 3) == 0) {
155
if (value && *value) {
158
} /* else if (strnicmp(data, "file_mode", 4) == 0) {
159
if (value && *value) {
161
simple_strtoul(value, &value, 0);
163
} else if (strnicmp(data, "dir_mode", 3) == 0) {
164
if (value && *value) {
166
simple_strtoul(value, &value, 0);
168
} else if (strnicmp(data, "port", 4) == 0) {
169
if (value && *value) {
171
simple_strtoul(value, &value, 0);
173
} else if (strnicmp(data, "rsize", 5) == 0) {
174
if (value && *value) {
176
simple_strtoul(value, &value, 0);
178
} else if (strnicmp(data, "wsize", 5) == 0) {
179
if (value && *value) {
181
simple_strtoul(value, &value, 0);
183
} else if (strnicmp(data, "version", 3) == 0) {
185
} else if (strnicmp(data, "rw", 2) == 0) {
188
printf("CIFS: Unknown mount option %s\n",data); */
193
/* Note that caller frees the returned buffer if necessary */
194
char * parse_server(char * unc_name)
196
int length = strnlen(unc_name,1024);
198
char * ipaddress_string = NULL;
199
struct hostent * host_entry;
200
struct in_addr server_ipaddr;
205
printf("mount error: UNC name too long");
208
if (strncasecmp("cifs://",unc_name,7) == 0)
209
return parse_cifs_url(unc_name+7);
210
if (strncasecmp("smb://",unc_name,6) == 0) {
211
return parse_cifs_url(unc_name+6);
215
/* BB add code to find DFS root here */
216
printf("\nMounting the DFS root for domain not implemented yet");
219
/* BB add support for \\\\ not just // */
220
if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
221
printf("mount error: improperly formatted UNC name.");
222
printf(" %s does not begin with \\\\ or //\n",unc_name);
228
if ((share = strchr(unc_name, '/')) ||
229
(share = strchr(unc_name,'\\'))) {
230
*share = 0; /* temporarily terminate the string */
232
host_entry = gethostbyname(unc_name);
233
*(share - 1) = '\\'; /* put the slash back */
234
/* rc = getipnodebyname(unc_name, AF_INET, AT_ADDRCONFIG ,&rc);*/
235
if(host_entry == NULL) {
236
printf("mount error: could not find target server. TCP name %s not found ", unc_name);
237
printf(" rc = %d\n",rc);
241
/* BB should we pass an alternate version of the share name as Unicode */
242
/* BB what about ipv6? BB */
243
/* BB add retries with alternate servers in list */
245
memcpy(&server_ipaddr.s_addr, host_entry->h_addr, 4);
247
ipaddress_string = inet_ntoa(server_ipaddr);
248
if(ipaddress_string == NULL) {
249
printf("mount error: could not get valid ip address for target server\n");
252
return ipaddress_string;
255
/* BB add code to find DFS root (send null path on get DFS Referral to specified server here */
256
printf("Mounting the DFS root for a particular server not implemented yet\n");
263
static struct option longopts[] = {
264
{ "all", 0, 0, 'a' },
265
{ "help", 0, 0, 'h' },
266
{ "read-only", 0, 0, 'r' },
268
{ "verbose", 0, 0, 'v' },
269
{ "version", 0, 0, 'V' },
270
{ "read-write", 0, 0, 'w' },
272
{ "options", 1, 0, 'o' },
273
{ "types", 1, 0, 't' },
274
{ "replace", 0, 0, 129 },
275
{ "after", 0, 0, 130 },
276
{ "before", 0, 0, 131 },
277
{ "over", 0, 0, 132 },
278
{ "move", 0, 0, 133 },
279
{ "rsize",1, 0, 136 },
280
{ "wsize",1, 0, 137 },
285
{ "username",1,0,140},
288
{ "password",1,0,142},
292
int main(int argc, char ** argv)
295
int flags = MS_MANDLOCK | MS_MGC_VAL;
296
char * orgoptions = NULL;
297
char * share_name = NULL;
298
char * domain_name = NULL;
299
char * ipaddr = NULL;
311
struct utsname sysinfo;
312
struct mntent mountent;
315
/* setlocale(LC_ALL, "");
316
#if defined(LOCALEDIR)
317
bindtextdomain(PACKAGE, LOCALEDIR);
318
textdomain(PACKAGE); */
322
thisprogram = argv[0];
324
if(thisprogram == NULL)
325
thisprogram = "mount.cifs";
328
/* BB add workstation name and domain and pass down */
330
printf(" node: %s machine: %s\n", sysinfo.nodename,sysinfo.machine);
334
share_name = argv[1];
335
mountpoint = argv[2];
336
/* add sharename in opts string as unc= parm */
338
while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
339
longopts, NULL)) != -1) {
354
external_allowed = 0;
357
list_with_volumelabel = 1;
360
volumelabel = optarg;
367
orgoptions = strcat(orgoptions, ",");
368
orgoptions = strcat(orgoptions,optarg);
370
orgoptions = strdup(optarg);
375
test_opts = xstrconcat3(test_opts, ",", optarg);
377
test_opts = xstrdup(optarg);
379
case 'r': /* mount readonly */
389
printf ("mount: %s\n", version);
392
flags &= ~MS_RDONLY;;
401
mounttype = MS_REPLACE;
404
mounttype = MS_AFTER;
407
mounttype = MS_BEFORE;
416
mounttype = (MS_BIND | MS_REC);
419
rsize = atoi(optarg) ;
422
wsize = atoi(optarg);
435
domain_name = optarg;
439
mountpassword = optarg;
447
/* canonicalize the path in argv[1]? */
449
if(stat (mountpoint, &statbuf)) {
450
printf("mount error: mount point %s does not exist\n",mountpoint);
453
if (S_ISDIR(statbuf.st_mode) == 0) {
454
printf("mount error: mount point %s is not a directory\n",mountpoint);
459
printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n");
463
ipaddr = parse_server(share_name);
464
/* if(share_name == NULL)
466
if (parse_options(strdup(orgoptions)))
470
user_name = getusername();
472
/* check username for user%password format */
474
if(got_password == 0) {
475
if (getenv("PASSWD")) {
476
mountpassword = malloc(33);
478
strncpy(mountpassword,getenv("PASSWD"),32);
481
/* } else if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
483
got_password = 1;*/ /* BB add missing function */
485
mountpassword = getpass("Password: "); /* BB obsolete */
489
/* FIXME launch daemon (handles dfs name resolution and credential change)
490
remember to clear parms and overwrite password field before launching */
492
optlen = strlen(orgoptions);
496
optlen += strlen(share_name) + 4;
498
optlen += strlen(user_name) + 6;
500
optlen += strlen(ipaddr) + 4;
502
optlen += strlen(mountpassword) + 6;
503
options = malloc(optlen + 10);
506
strncat(options,"unc=",4);
507
strcat(options,share_name);
509
strncat(options,",ip=",4);
510
strcat(options,ipaddr);
513
strncat(options,",user=",6);
514
strcat(options,user_name);
517
strncat(options,",pass=",6);
518
strcat(options,mountpassword);
520
strncat(options,",ver=",5);
521
strcat(options,MOUNT_CIFS_VERSION);
525
strcat(options,orgoptions);
527
/* printf("\noptions %s \n",options);*/
528
if(mount(share_name, mountpoint, "cifs", flags, options)) {
529
/* remember to kill daemon on error */
532
printf("mount failed but no error number set\n");
535
printf("mount error: cifs filesystem not supported by the system\n");
538
printf("mount error %d = %s",errno,strerror(errno));
540
printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
543
pmntfile = setmntent(MOUNTED, "a+");
545
mountent.mnt_fsname = share_name;
546
mountent.mnt_dir = mountpoint;
547
mountent.mnt_type = "cifs";
548
mountent.mnt_opts = "";
549
mountent.mnt_freq = 0;
550
mountent.mnt_passno = 0;
551
rc = addmntent(pmntfile,&mountent);
554
printf("could not update mount table\n");