1 #include "headers.h"
2
3 static SmbProcessResult
query(SmbSession * s,char * cmdname,char * filename,ushort infolevel,vlong cbo,Dir * d)4 query(SmbSession *s, char *cmdname, char *filename, ushort infolevel, vlong cbo, Dir *d)
5 {
6 vlong ntatime, ntmtime;
7 ushort dosmode;
8 ulong fnlfixupoffset;
9 vlong allocsize;
10
11 if (d == nil) {
12 smbseterror(s, ERRDOS, ERRbadfile);
13 return SmbProcessResultError;
14 }
15
16 switch (infolevel) {
17 case SMB_QUERY_FILE_BASIC_INFO:
18 ntatime = smbplan9time2time(d->atime);
19 ntmtime = smbplan9time2time(d->mtime);
20 dosmode = smbplan9mode2dosattr(d->mode);
21
22 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_BASIC_INFO\n");
23 translogprint(s->transaction.in.setup[0], "REPLY:\n");
24 translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
25 translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
26 translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
27
28 if (!smbbufferputv(s->transaction.out.data, ntmtime)
29 || !smbbufferputv(s->transaction.out.data, ntatime)
30 || !smbbufferputv(s->transaction.out.data, ntmtime)
31 || !smbbufferputv(s->transaction.out.data, ntmtime)
32 || !smbbufferputl(s->transaction.out.data, dosmode))
33 return SmbProcessResultMisc;
34 break;
35 case SMB_QUERY_FILE_ALL_INFO:
36 ntatime = smbplan9time2time(d->atime);
37 ntmtime = smbplan9time2time(d->mtime);
38 dosmode = smbplan9mode2dosattr(d->mode);
39 allocsize = (d->length + (1 << smbglobals.l2allocationsize) - 1) & ~((1 << smbglobals.l2allocationsize) - 1);
40
41 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_ALL_INFO\n");
42 translogprint(s->transaction.in.setup[0], "REPLY:\n");
43 translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->atime));
44 translogprint(s->transaction.in.setup[0], "atime=%s", ctime(d->mtime));
45 translogprint(s->transaction.in.setup[0], "mode=0%o -> dosmode=0x%x\n", d->mode, dosmode);
46 translogprint(s->transaction.in.setup[0], "allocsize=%d\n", allocsize);
47 translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->mode & DMDIR) != 0);
48
49 if (!smbbufferputv(s->transaction.out.data, ntmtime)
50 || !smbbufferputv(s->transaction.out.data, ntatime)
51 || !smbbufferputv(s->transaction.out.data, ntmtime)
52 || !smbbufferputv(s->transaction.out.data, ntmtime)
53 || !smbbufferputs(s->transaction.out.data, dosmode)
54 || !smbbufferputbytes(s->transaction.out.data, nil, 6)
55 || !smbbufferputv(s->transaction.out.data, allocsize)
56 || !smbbufferputv(s->transaction.out.data, d->length)
57 || !smbbufferputl(s->transaction.out.data, 0) // hard links - ha
58 || !smbbufferputb(s->transaction.out.data, 0) // TODO delete pending
59 || !smbbufferputb(s->transaction.out.data, (d->mode & DMDIR) != 0)
60 || !smbbufferputv(s->transaction.out.data, d->qid.path)
61 || !smbbufferputl(s->transaction.out.data, 0) // EA size
62 || !smbbufferputl(s->transaction.out.data, (dosmode & SMB_ATTR_READ_ONLY) ? 0xa1 : 0x1a7)
63 || !smbbufferputv(s->transaction.out.data, cbo)
64 || !smbbufferputs(s->transaction.out.data, dosmode)
65 || !smbbufferputl(s->transaction.out.data, 0)) // alignment
66 return SmbProcessResultMisc;
67 fnlfixupoffset = smbbufferwriteoffset(s->transaction.out.data);
68 if (!smbbufferputl(s->transaction.out.data, 0)
69 || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_REVPATH, filename)
70 || !smbbufferfixuprelativel(s->transaction.out.data, fnlfixupoffset))
71 return SmbProcessResultMisc;
72 break;
73 case SMB_QUERY_FILE_STANDARD_INFO:
74 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STANDARD_INFO\n");
75 translogprint(s->transaction.in.setup[0], "REPLY:\n");
76 translogprint(s->transaction.in.setup[0], "length=%lld", d->length);
77 translogprint(s->transaction.in.setup[0], "isdir=%d\n", (d->qid.type & QTDIR) != 0);
78
79 if (!smbbufferputv(s->transaction.out.data, smbl2roundupvlong(d->length, smbglobals.l2allocationsize))
80 || !smbbufferputv(s->transaction.out.data, d->length)
81 || !smbbufferputl(s->transaction.out.data, 1)
82 || !smbbufferputb(s->transaction.out.data, 0)
83 || !smbbufferputb(s->transaction.out.data, (d->qid.type & QTDIR) != 0))
84 return SmbProcessResultMisc;
85 break;
86 case SMB_QUERY_FILE_EA_INFO:
87 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_EA_INFO\n");
88 translogprint(s->transaction.in.setup[0], "REPLY:\n");
89 translogprint(s->transaction.in.setup[0], "ea_len=0\n");
90 if (!smbbufferputl(s->transaction.out.data, 0))
91 return SmbProcessResultMisc;
92 break;
93 case SMB_QUERY_FILE_STREAM_INFO:
94 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FILE_STREAM_INFO\n");
95 translogprint(s->transaction.in.setup[0], "REPLY: failed\n");
96 /* don't do it, never will */
97 goto unknownlevel;
98 default:
99 smblogprint(-1, "smbtrans2query%sinformation: infolevel 0x%.4ux not implemented\n", cmdname, infolevel);
100 unknownlevel:
101 translogprint(s->transaction.in.setup[0], "[not supported]\n");
102 smbseterror(s, ERRDOS, ERRunknownlevel);
103 return SmbProcessResultError;
104 }
105 return SmbProcessResultReply;
106 }
107
108 SmbProcessResult
smbtrans2querypathinformation(SmbSession * s,SmbHeader * h)109 smbtrans2querypathinformation(SmbSession *s, SmbHeader *h)
110 {
111 SmbTree *t;
112 SmbBuffer *b = nil;
113 SmbProcessResult pr;
114 ushort infolevel;
115 Dir *d;
116 char *path = nil;
117 char *fullpath;
118
119 t = smbidmapfind(s->tidmap, h->tid);
120 if (t == nil) {
121 smbseterror(s, ERRSRV, ERRinvtid);
122 pr = SmbProcessResultError;
123 goto done;
124 }
125 b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
126 if (!smbbuffergets(b, &infolevel) || !smbbuffergetbytes(b, nil, 4)
127 || !smbbuffergetstring(b, h, SMB_STRING_PATH, &path)) {
128 pr = SmbProcessResultMisc;
129 goto done;
130 }
131 translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
132 translogprint(s->transaction.in.setup[0], "path %s\n", path);
133 fullpath = nil;
134 smbstringprint(&fullpath, "%s%s", t->serv->path, path);
135 translogprint(s->transaction.in.setup[0], "fullpath %s\n", fullpath);
136 d = dirstat(fullpath);
137 pr = query(s, "path", path, infolevel, 0, d);
138 free(d);
139 free(fullpath);
140 done:
141 free(path);
142 smbbufferfree(&b);
143 return pr;
144 }
145
146 SmbProcessResult
smbtrans2queryfileinformation(SmbSession * s,SmbHeader * h)147 smbtrans2queryfileinformation(SmbSession *s, SmbHeader *h)
148 {
149 SmbTree *t;
150 SmbFile *f;
151 SmbBuffer *b = nil;
152 SmbProcessResult pr;
153 ushort fid;
154 ushort infolevel;
155 vlong o;
156 Dir *d;
157
158 t = smbidmapfind(s->tidmap, h->tid);
159 if (t == nil) {
160 smbseterror(s, ERRSRV, ERRinvtid);
161 pr = SmbProcessResultError;
162 goto done;
163 }
164 b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
165 if (!smbbuffergets(b, &fid) || !smbbuffergets(b, &infolevel)) {
166 pr = SmbProcessResultMisc;
167 goto done;
168 }
169 translogprint(s->transaction.in.setup[0], "fid 0x%.4ux\n", fid);
170 translogprint(s->transaction.in.setup[0], "infolevel 0x%.4ux\n", infolevel);
171 f = smbidmapfind(s->fidmap, fid);
172 if (f == nil) {
173 smbseterror(s, ERRDOS, ERRbadfid);
174 pr = SmbProcessResultError;
175 goto done;
176 }
177 if(f->fd >= 0){
178 o = seek(f->fd, 0, 1);
179 d = dirfstat(f->fd);
180 } else {
181 char *fullpath = nil;
182
183 o = 0;
184 smbstringprint(&fullpath, "%s%s", f->t->serv->path, f->name);
185 d = dirstat(fullpath);
186 free(fullpath);
187 }
188 pr = query(s, "file", f->name, infolevel, o, d);
189 free(d);
190 done:
191 smbbufferfree(&b);
192 return pr;
193 }
194
195 SmbProcessResult
smbtrans2queryfsinformation(SmbSession * s,SmbHeader * h)196 smbtrans2queryfsinformation(SmbSession *s, SmbHeader *h)
197 {
198 SmbTree *t;
199 ushort infolevel;
200 SmbBuffer *b;
201 SmbProcessResult pr;
202 ulong fixup;
203 ulong vnbase;
204
205 t = smbidmapfind(s->tidmap, h->tid);
206 if (t == nil) {
207 smbseterror(s, ERRSRV, ERRinvtid);
208 pr = SmbProcessResultError;
209 goto done;
210 }
211 b = smbbufferinit(s->transaction.in.parameters, s->transaction.in.parameters, s->transaction.in.tpcount);
212 if (!smbbuffergets(b, &infolevel)) {
213 misc:
214 pr = SmbProcessResultMisc;
215 goto done;
216 }
217 pr = SmbProcessResultReply;
218 switch (infolevel) {
219 case SMB_INFO_ALLOCATION:
220 translogprint(s->transaction.in.setup[0], "SMB_INFO_ALLOCATION\n");
221 if (!smbbufferputl(s->transaction.out.data, 0)
222 || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
223 || !smbbufferputl(s->transaction.out.data, 0xffffffff)
224 || !smbbufferputl(s->transaction.out.data, 0xffffffff)
225 || !smbbufferputs(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
226 goto misc;
227 break;
228 case SMB_INFO_VOLUME:
229 translogprint(s->transaction.in.setup[0], "SMB_INFO_VOLUME\n");
230 if (!smbbufferputl(s->transaction.out.data, 0xdeadbeef)
231 || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name))
232 goto misc;
233 break;
234 case SMB_QUERY_FS_VOLUME_INFO:
235 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_VOLUME_INFO\n");
236 if (!smbbufferputv(s->transaction.out.data, 0)
237 || !smbbufferputl(s->transaction.out.data, 0xdeadbeef))
238 goto misc;
239 fixup = smbbufferwriteoffset(s->transaction.out.data);
240 if (!smbbufferputl(s->transaction.out.data, 0)
241 || !smbbufferputs(s->transaction.out.data, 0))
242 goto misc;
243 vnbase = smbbufferwriteoffset(s->transaction.out.data);
244 if (!smbbufferputstring(s->transaction.out.data, &s->peerinfo, 0, t->serv->name)
245 || !smbbufferfixupl(s->transaction.out.data, fixup,
246 smbbufferwriteoffset(s->transaction.out.data) - vnbase))
247 goto misc;
248 break;
249 case SMB_QUERY_FS_SIZE_INFO:
250 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_SIZE_INFO\n");
251 if (!smbbufferputv(s->transaction.out.data, 0LL)
252 || !smbbufferputv(s->transaction.out.data, 0LL)
253 || !smbbufferputl(s->transaction.out.data, 1 << (smbglobals.l2allocationsize - smbglobals.l2sectorsize))
254 || !smbbufferputl(s->transaction.out.data, 1 << smbglobals.l2sectorsize))
255 goto misc;
256 break;
257 case SMB_QUERY_FS_ATTRIBUTE_INFO:
258 translogprint(s->transaction.in.setup[0], "SMB_QUERY_FS_ATTRIBUTE_INFO\n");
259 if (!smbbufferputl(s->transaction.out.data, 3)
260 || !smbbufferputl(s->transaction.out.data, 255))
261 goto misc;
262 fixup = smbbufferwriteoffset(s->transaction.out.data);
263 if (!smbbufferputl(s->transaction.out.data, 0)
264 || !smbbufferputstring(s->transaction.out.data, &s->peerinfo, SMB_STRING_UNTERMINATED, smbglobals.serverinfo.nativelanman)
265 || !smbbufferfixuprelativel(s->transaction.out.data, fixup))
266 goto misc;
267 break;
268 default:
269 smblogprint(-1, "smbtrans2queryfsinformation: infolevel 0x%.4ux not implemented\n", infolevel);
270 smbseterror(s, ERRDOS, ERRunknownlevel);
271 pr = SmbProcessResultError;
272 }
273 done:
274 smbbufferfree(&b);
275 return pr;
276 }
277