📄 proc.c
字号:
lastname_len = 0; if (ff_lastname > 0) { switch (info_level) { case 260: lastname = p + ff_lastname; lastname_len = resp_data_len - ff_lastname; ff_resume_key = 0; break; case 1: lastname = p + ff_lastname + 1; lastname_len = BVAL(p, ff_lastname); ff_resume_key = 0; break; } } lastname_len = min(lastname_len, 256); strncpy(mask, lastname, lastname_len); mask[lastname_len] = '\0'; /* Now we are ready to parse smb directory entries. */ for (i = 0; i < ff_searchcount; i++) { struct smb_dirent *entry = &(cache[entries]); p = smb_decode_long_dirent(server, p, entry, info_level); DDPRINTK("smb_readdir_long: got %s\n", entry->name); if ((entry->name[0] == '.') && ((entry->name[1] == '\0') || ((entry->name[1] == '.') && (entry->name[2] == '\0')))) { /* ignore . and .. from the server */ continue; } if (entries_seen >= fpos) { entry->f_pos = entries_seen; entries += 1; } if (entries >= cache_size) { goto finished; } entries_seen += 1; } DPRINTK("received %d entries (eos=%d resume=%d)\n", ff_searchcount, ff_eos, ff_resume_key); first = 0; } finished: smb_unlock_server(server); return entries;}intsmb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos, int cache_size, struct smb_dirent *entry){ if (server->protocol >= PROTOCOL_LANMAN2) return smb_proc_readdir_long(server, dir, fpos, cache_size, entry); else return smb_proc_readdir_short(server, dir, fpos, cache_size, entry);}/* * This version uses the core protocol to get the attribute info. * It works OK with Win 3.11, 95 and NT 3.51, but NOT with NT 4 (bad mtime). */static intsmb_proc_getattr_core(struct inode *dir, const char *name, int len, struct smb_dirent *entry){ int result; char *p; struct smb_server *server = SMB_SERVER(dir); char *buf; smb_lock_server(server); DDPRINTK("smb_proc_getattr_core: %s\n", name); retry: buf = server->packet; p = smb_setup_header(server, SMBgetatr, 0, 0); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(dir), name, len); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) { if (smb_retry(server)) { goto retry; } smb_unlock_server(server); return result; } /* N.B. Packet may change after request */ buf = server->packet; entry->attr = WVAL(buf, smb_vwv0); entry->f_ctime = entry->f_atime = entry->f_mtime = local2utc(DVAL(buf, smb_vwv1)); DDPRINTK("smb_proc_getattr_core: mtime=%ld\n", entry->f_mtime); entry->f_size = DVAL(buf, smb_vwv3); smb_unlock_server(server); return 0;}/* * This version uses the trans2 findfirst to get the attribute info. * It works fine with NT 3.51 and NT 4 (any SP), but not with Win95 (ERRerror). */static intsmb_proc_getattr_ff(struct inode *dir, const char *name, int len, struct smb_dirent *entry){ unsigned char *resp_data = NULL; unsigned char *resp_param = NULL; int resp_data_len = 0; int resp_param_len = 0; char param[SMB_MAXPATHLEN + 1 + 12]; int mask_len; unsigned char *mask = &(param[12]); int result; char *p; struct smb_server *server = SMB_SERVER(dir); mask_len = smb_encode_path(server, mask, SMB_INOP(dir), name, len) - mask; mask[mask_len] = 0; DDPRINTK("smb_proc_getattr_ff: mask=%s\n", mask); smb_lock_server(server); retry: WSET(param, 0, aSYSTEM | aHIDDEN | aDIR); WSET(param, 2, 1); /* max count */ WSET(param, 4, 2 + 1); /* close on end + close after this call */ WSET(param, 6, 1); /* info level */ DSET(param, 8, 0); result = smb_trans2_request(server, TRANSACT2_FINDFIRST, 0, NULL, 12 + mask_len + 1, param, &resp_data_len, &resp_data, &resp_param_len, &resp_param); if (result < 0) { if (smb_retry(server)) { DPRINTK("smb_proc_getattr_ff: error=%d, retrying\n", result); goto retry; } goto out; } if (server->rcls != 0) { result = -smb_errno(server->rcls, server->err); if (result != -ENOENT) DPRINTK("smb_proc_getattr_ff: rcls=%d, err=%d\n", server->rcls, server->err); goto out; } /* Make sure we got enough data ... */ result = -EINVAL; /* WVAL(resp_param, 2) is ff_searchcount */ if (resp_data_len < 22 || WVAL(resp_param, 2) != 1) { DPRINTK("smb_proc_getattr_ff: bad result, len=%d, count=%d\n", resp_data_len, WVAL(resp_param, 2)); goto out; } /* Decode the response (info level 1, as in smb_decode_long_dirent) */ p = resp_data; entry->f_ctime = date_dos2unix(WVAL(p, 2), WVAL(p, 0)); entry->f_atime = date_dos2unix(WVAL(p, 6), WVAL(p, 4)); entry->f_mtime = date_dos2unix(WVAL(p, 10), WVAL(p, 8)); entry->f_size = DVAL(p, 12); entry->attr = WVAL(p, 20); DDPRINTK("smb_proc_getattr_ff: attr=%x\n", entry->attr); result = 0;out: smb_unlock_server(server); return result;}intsmb_proc_getattr(struct inode *dir, const char *name, int len, struct smb_dirent *entry){ struct smb_server *server = SMB_SERVER(dir); int result; smb_init_dirent(server, entry); /* Use trans2 for NT, use core protocol for others (Win95/3.11/...). * We distinguish NT from Win95 by looking at the capabilities, * in the same way as in Samba 1.9.18p2's reply.c. */ if ((server->protocol >= PROTOCOL_LANMAN2) && (server->blkmode & (CAP_NT_SMBS | CAP_STATUS32))) result = smb_proc_getattr_ff(dir, name, len, entry); else result = smb_proc_getattr_core(dir, name, len, entry); smb_finish_dirent(server, entry); entry->len = len; memcpy(entry->name, name, len); /* entry->name is null terminated from smb_init_dirent */ return result;}intsmb_proc_setattr(struct smb_server *server, struct inode *i, struct smb_dirent *new_finfo){ char *p; char *buf; int result; smb_lock_server(server); retry: buf = server->packet; p = smb_setup_header(server, SMBsetatr, 8, 0); WSET(buf, smb_vwv0, new_finfo->attr); DSET(buf, smb_vwv1, 0); DSET(buf, smb_vwv3, 0); DSET(buf, smb_vwv5, 0); WSET(buf, smb_vwv7, 0); *p++ = 4; p = smb_encode_path(server, p, SMB_INOP(i)->dir, SMB_INOP(i)->finfo.name, SMB_INOP(i)->finfo.len); smb_setup_bcc(server, p); if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) { if (smb_retry(server)) { goto retry; } } smb_unlock_server(server); return result;}intsmb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr){ int error; char *p; struct smb_server *server = &(SMB_SBP(super)->s_server); smb_lock_server(server); retry: smb_setup_header(server, SMBdskattr, 0, 0); if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) { if (smb_retry(server)) { goto retry; } smb_unlock_server(server); return error; } p = SMB_VWV(server->packet); p = smb_decode_word(p, &attr->total); p = smb_decode_word(p, &attr->allocblocks); p = smb_decode_word(p, &attr->blocksize); p = smb_decode_word(p, &attr->free); smb_unlock_server(server); return 0;}/*****************************************************************************//* *//* Mount/umount operations. *//* *//*****************************************************************************/struct smb_prots{ enum smb_protocol prot; const char *name;};/* smb_proc_reconnect: We expect the server to be locked, so that you can call the routine from within smb_retry. The socket must be created, like after a user-level socket()-call. It may not be connected. */intsmb_proc_reconnect(struct smb_server *server){ struct smb_prots prots[] = { {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"}, {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"},#ifdef LANMAN1 {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"}, {PROTOCOL_LANMAN1, "LANMAN1.0"},#endif#ifdef LANMAN2 {PROTOCOL_LANMAN2, "LM1.2X002"},#endif#ifdef NT1 {PROTOCOL_NT1, "NT LM 0.12"}, {PROTOCOL_NT1, "NT LANMAN 1.0"},#endif {-1, NULL}}; char dev[] = "A:"; int i, plength; int max_xmit = 1024; /* Space needed for first request. */ int given_max_xmit = server->m.max_xmit; int result; byte *p; if ((result = smb_connect(server)) < 0) { DPRINTK("smb_proc_reconnect: could not smb_connect\n"); goto fail; } /* Here we assume that the connection is valid */ server->state = CONN_VALID; if (server->packet != NULL) { smb_vfree(server->packet); server->packet = NULL; server->packet_size = 0; } server->packet = smb_vmalloc(max_xmit); if (server->packet == NULL) { printk("smb_proc_connect: No memory! Bailing out.\n"); result = -ENOMEM; goto fail; } server->packet_size = server->max_xmit = max_xmit; /* * Start with an RFC1002 session request packet. */ p = server->packet + 4; p = smb_name_mangle(p, server->m.server_name); p = smb_name_mangle(p, server->m.client_name); smb_encode_smb_length(server->packet, (void *) p - (void *) (server->packet)); server->packet[0] = 0x81; /* SESSION REQUEST */ if (smb_catch_keepalive(server) < 0) { printk("smb_proc_connect: could not catch_keepalives\n"); } if ((result = smb_request(server)) < 0) { DPRINTK("smb_proc_connect: Failed to send SESSION REQUEST.\n"); smb_dont_catch_keepalive(server); goto fail; } if (server->packet[0] != 0x82) { printk("smb_proc_connect: Did not receive positive response " "(err = %x)\n", server->packet[0]); smb_dont_catch_keepalive(server); result = -EIO; goto fail; } DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n"); /* Now we are ready to send a SMB Negotiate Protocol packet. */ memset(server->packet, 0, SMB_HEADER_LEN); plength = 0; for (i = 0; prots[i].name != NULL; i++) { plength += strlen(prots[i].name) + 2; } smb_setup_header(server, SMBnegprot, 0, plength); p = SMB_BUF(server->packet); for (i = 0; prots[i].name != NULL; i++) { *p++ = 2; strcpy(p, prots[i].name); p += strlen(prots[i].name) + 1; } if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) { DPRINTK("smb_proc_connect: Failure requesting SMBnegprot\n"); smb_dont_catch_keepalive(server); goto fail; } else { DDPRINTK("smb_proc_connect: Request SMBnegprot.."); } DDPRINTK("Verified!\n"); p = SMB_VWV(server->packet); p = smb_decode_word(p, (word *) & i); server->protocol = prots[i].prot; DPRINTK("smb_proc_connect: Server wants %s protocol.\n", prots[i].name); if (server->protocol >= PROTOCOL_LANMAN1) { word passlen = strlen(server->m.password); word userlen = strlen(server->m.username);#ifdef DEBUG_SMB_PASSWORD DPRINTK("smb_proc_connect: password = %s\n", server->m.password);#endif DPRINTK("smb_proc_connect: usernam = %s\n", server->m.username); if (server->protocol >= PROTOCOL_NT1) { server->max_xmit = DVAL(server->packet, smb_vwv3 + 1); server->maxmux = WVAL(server->packet, smb_vwv1 + 1); server->maxvcs = WVAL(server->packet, smb_vwv2 + 1); server->blkmode = DVAL(server->packet, smb_vwv9 + 1); server->sesskey = DVAL(server->packet, smb_vwv7 + 1); } else { server->max_xmit = WVAL(server->packet, smb_vwv2); server->maxmux = WVAL(server->packet, smb_vwv3); server->maxvcs = WVAL(server->packet, smb_vwv4); server->blkmode = WVAL(server->packet, smb_vwv5); server->sesskey = DVAL(server->packet, smb_vwv6); } DPRINTK("smb_proc_connect: blkmode (capabilities) = %x\n", server->blkmode); if (server->max_xmit < given_max_xmit) { /* We do not distinguish between the client requests and the server response. */ given_max_xmit = server->max_xmit; } if (server->protocol >= PROTOCOL_NT1) { char *workgroup = server->m.domain; char *OS_id = "Unix"; char *client_id = "ksmbfs"; smb_setup_header(server, SMBsesssetupX, 13, 5 + userlen + passlen + strlen(workgroup) + strlen(OS_id) + strlen(client_id)); WSET(server->packet, smb_vwv0, 0x00ff); WSET(server->packet, smb_vwv1, 0); WSET(server->packet, smb_vwv2, given_max_xmit); WSET(server->packet, smb_vwv3, 2); WSET(server->packet, smb_vwv4, server->pid); DSET(server->packet, smb_vwv5, server->sesskey); WSET(server->packet, smb_vwv7, passlen + 1); WSET(server->packet, smb_vwv8, 0); WSET(server->packet, smb_vwv9, 0); p = SMB_BUF(server->packet); strcpy(p, server->m.password); p += passlen + 1; strcpy(p, server->m.username); p += userlen + 1; strcpy(p, workgroup); p += strlen(p) + 1; strcpy(p, OS_id); p += strlen(p) + 1; strcpy(p, client_id); } else { smb_setup_header(server, SMBsesssetupX, 10, 2 + userlen + passlen); WSET(server->packet, smb_vwv0, 0x00ff); WSET(server->packet, smb_vwv1, 0); WSET(server->packet, smb_vwv2, given_max_xmit); WSET(server->packet, smb_vwv3, 2); WSET(server->packet, smb_vwv4, server->pid); DSET(server->packet, smb_vwv5, server->sesskey); WSET(server->packet, smb_vwv7, passlen + 1); WSET(server->packet, smb_vwv8, 0); WSET(server->packet, smb_vwv9, 0); p = SMB_BUF(server->packet); strcpy(p, server->m.password); p += passlen + 1; strcpy(p, server->m.username); } if ((result = smb_request_ok(server, SMBsesssetupX, 3, 0)) < 0) { DPRINTK("smb_proc_connect: SMBsessetupX failed\n"); smb_dont_catch_keepalive(server); goto fail; } smb_decode_word(server->packet + 32, &(server->server_uid)); } else { server->max_xmit = 0; server->maxmux = 0; server->maxvcs = 0; server->blkmode = 0; server->sesskey = 0; } /* Fine! We have a connection, send a tcon message. */ smb_setup_header(server, SMBtcon, 0, 6 + strlen(server->m.service) + strlen(server->m.password) + strlen(dev)); p = SMB_BUF(server->packet); p = smb_encode_ascii(p, server->m.service, strlen(server->m.service)); p = smb_encode_ascii(p, server->m.password, strlen(server->m.password)); p = smb_encode_ascii(p, dev, strlen(dev)); if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) { DPRINTK("smb_proc_connect: SMBtcon not verified.\n"); smb_dont_catch_keepalive(server); goto fail; } DDPRINTK("OK! Managed to set up SMBtcon!\n"); p = SMB_VWV(server->packet); if (server->protocol <= PROTOCOL_COREPLUS) { word max_xmit; p = smb_decode_word(p, &max_xmit); server->max_xmit = max_xmit; if (server->max_xmit > given_max_xmit) { server->max_xmit = given_max_xmit; } } else { p += 2; } p = smb_decode_word(p, &server->tid); /* Ok, everything is fine. max_xmit does not include */ /* the TCP-SMB header of 4 bytes. */ server->max_xmit += 4; DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid); /* Now make a new packet with the correct size. */ smb_vfree(server->packet); server->packet = NULL; server->packet = smb_vmalloc(server->max_xmit); if (server->packet == NULL) { printk("smb_proc_connect: No memory left in end of " "connection phase :-(\n"); smb_dont_catch_keepalive(server); goto fail; } server->packet_size = server->max_xmit; DPRINTK("smb_proc_connect: Normal exit\n"); return 0; fail: server->state = CONN_INVALID; return result;}/* smb_proc_reconnect: server->packet is allocated with server->max_xmit bytes if and only if we return >= 0 */intsmb_proc_connect(struct smb_server *server){ int result; smb_lock_server(server); result = smb_proc_reconnect(server); if ((result < 0) && (server->packet != NULL)) { smb_vfree(server->packet); server->packet = NULL; } smb_unlock_server(server); return result;}intsmb_proc_disconnect(struct smb_server *server){ smb_setup_header_exclusive(server, SMBtdis, 0, 0); return smb_request_ok_unlock(server, SMBtdis, 0, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -