This source file includes following definitions.
- smb_data_callback
- smb_catch_keepalive
- smb_dont_catch_keepalive
- smb_receive
- smb_receive_trans2
- server_sock
- smb_release
- smb_connect
- smb_request
- smb_trans2_request
1
2
3
4
5
6
7
8 #include <linux/config.h>
9 #ifdef MODULE
10 #include <linux/module.h>
11 #include <linux/version.h>
12 #endif
13
14 #include <linux/sched.h>
15 #include <linux/smb_fs.h>
16 #include <linux/errno.h>
17 #include <linux/socket.h>
18 #include <linux/fcntl.h>
19 #include <linux/stat.h>
20 #include <asm/segment.h>
21 #include <linux/in.h>
22 #include <linux/net.h>
23 #include <linux/mm.h>
24 #include <linux/netdevice.h>
25 #include <net/ip.h>
26
27 #include <linux/smb.h>
28 #include <linux/smbno.h>
29
30
31 #define _S(nr) (1<<((nr)-1))
32
33 static void
34 smb_data_callback(struct sock *sk,int len)
35 {
36 struct socket *sock = sk->socket;
37
38 if(!sk->dead)
39 {
40 unsigned char peek_buf[4];
41 int result;
42 unsigned short fs;
43
44 fs = get_fs();
45 set_fs(get_ds());
46
47 result = sock->ops->recvfrom(sock, (void *)peek_buf, 1, 1,
48 MSG_PEEK, NULL, NULL);
49
50 while ((result != -EAGAIN) && (peek_buf[0] == 0x85)) {
51
52
53 result = sock->ops->recvfrom(sock, (void *)peek_buf,
54 4, 1, 0, NULL, NULL);
55
56 DDPRINTK("smb_data_callback:"
57 " got SESSION KEEP ALIVE\n");
58
59 if (result == -EAGAIN)
60 break;
61
62 result = sock->ops->recvfrom(sock, (void *)peek_buf,
63 1, 1, MSG_PEEK,
64 NULL, NULL);
65
66 }
67
68 set_fs(fs);
69
70 if (result != -EAGAIN) {
71 wake_up_interruptible(sk->sleep);
72 }
73 }
74 }
75
76 int
77 smb_catch_keepalive(struct smb_server *server)
78 {
79 struct file *file;
80 struct inode *inode;
81 struct socket *sock;
82 struct sock *sk;
83
84 if ( (server == NULL)
85 || ((file = server->sock_file) == NULL)
86 || ((inode = file->f_inode) == NULL)
87 || (!S_ISSOCK(inode->i_mode))) {
88
89 printk("smb_catch_keepalive: did not get valid server!\n");
90 server->data_ready = NULL;
91 return -EINVAL;
92 }
93
94 sock = &(inode->u.socket_i);
95
96 if (sock->type != SOCK_STREAM) {
97 printk("smb_catch_keepalive: did not get SOCK_STREAM\n");
98 server->data_ready = NULL;
99 return -EINVAL;
100 }
101
102 sk = (struct sock *)(sock->data);
103
104 if (sk == NULL) {
105 printk("smb_catch_keepalive: sk == NULL");
106 server->data_ready = NULL;
107 return -EINVAL;
108 }
109
110 DDPRINTK("smb_catch_keepalive.: sk->d_r = %x, server->d_r = %x\n",
111 (unsigned int)(sk->data_ready),
112 (unsigned int)(server->data_ready));
113
114 if (sk->data_ready == smb_data_callback) {
115 printk("smb_catch_keepalive: already done\n");
116 return -EINVAL;
117 }
118
119 server->data_ready = sk->data_ready;
120 sk->data_ready = smb_data_callback;
121 return 0;
122 }
123
124 int
125 smb_dont_catch_keepalive(struct smb_server *server)
126 {
127 struct file *file;
128 struct inode *inode;
129 struct socket *sock;
130 struct sock *sk;
131
132 if ( (server == NULL)
133 || ((file = server->sock_file) == NULL)
134 || ((inode = file->f_inode) == NULL)
135 || (!S_ISSOCK(inode->i_mode))) {
136
137 printk("smb_dont_catch_keepalive: "
138 "did not get valid server!\n");
139 return -EINVAL;
140 }
141
142 sock = &(inode->u.socket_i);
143
144 if (sock->type != SOCK_STREAM) {
145 printk("smb_dont_catch_keepalive: did not get SOCK_STREAM\n");
146 return -EINVAL;
147 }
148
149 sk = (struct sock *)(sock->data);
150
151 if (sk == NULL) {
152 printk("smb_dont_catch_keepalive: sk == NULL");
153 return -EINVAL;
154 }
155
156 if (server->data_ready == NULL) {
157 printk("smb_dont_catch_keepalive: "
158 "server->data_ready == NULL\n");
159 return -EINVAL;
160 }
161
162 if (sk->data_ready != smb_data_callback) {
163 printk("smb_dont_catch_keepalive: "
164 "sk->data_callback != smb_data_callback\n");
165 return -EINVAL;
166 }
167
168 DDPRINTK("smb_dont_catch_keepalive: sk->d_r = %x, server->d_r = %x\n",
169 (unsigned int)(sk->data_ready),
170 (unsigned int)(server->data_ready));
171
172 sk->data_ready = server->data_ready;
173 server->data_ready = NULL;
174 return 0;
175 }
176
177
178
179
180
181 static int
182 smb_receive(struct smb_server *server, struct socket *sock)
183 {
184 int len, result;
185 unsigned char peek_buf[4];
186
187 re_recv:
188
189 result = sock->ops->recvfrom(sock, (void *)peek_buf, 4, 0,
190 MSG_PEEK, NULL, NULL);
191
192 if (result < 0) {
193 DPRINTK("smb_receive: recv error = %d\n", -result);
194 return result;
195 }
196
197 if (result == 0) {
198 DPRINTK("smb_receive: got 0 bytes\n");
199 return -EIO;
200 }
201
202 switch (peek_buf[0]) {
203
204 case 0x00:
205 case 0x82:
206 break;
207
208 case 0x85:
209 DPRINTK("smb_receive: Got SESSION KEEP ALIVE\n");
210 sock->ops->recvfrom(sock, (void *)peek_buf, 4, 1,
211 0, NULL, NULL);
212 goto re_recv;
213
214 default:
215 printk("smb_receive: Invalid packet\n");
216 return -EIO;
217 }
218
219
220 len = smb_len(peek_buf) + 4;
221 if (len > server->max_xmit) {
222 printk("smb_receive: Received length (%d) > max_xmit (%d)!\n",
223 len, server->max_xmit);
224 return -EIO;
225 }
226 else
227 {
228 int already_read = 0;
229
230 while (already_read < len) {
231
232 result = sock->ops->
233 recvfrom(sock,
234 (void *)(server->packet+already_read),
235 len - already_read, 0, 0,
236 NULL, NULL);
237
238 if (result < 0) {
239 printk("SMB: notice message: error = %d\n",
240 -result);
241 return result;
242 }
243
244 already_read += result;
245 }
246 result = already_read;
247 }
248
249 server->rcls = *((unsigned char *)(server->packet+9));
250 server->err = *((unsigned short *)(server->packet+11));
251
252 if (server->rcls != 0) {
253 DPRINTK("smb_response: rcls=%d, err=%d\n",
254 server->rcls, server->err);
255 }
256
257 return result;
258 }
259
260
261
262
263
264 static int
265 smb_receive_trans2(struct smb_server *server, struct socket *sock,
266 int *data_len, int *param_len,
267 char **data, char **param)
268 {
269 int total_data=0;
270 int total_param=0;
271 int result;
272 unsigned char *inbuf = server->packet;
273
274 *data_len = *param_len = 0;
275
276 DDPRINTK("smb_receive_trans2: enter\n");
277
278 if ((result = smb_receive(server, sock)) < 0) {
279 return result;
280 }
281
282 if (server->rcls != 0) {
283 return result;
284 }
285
286
287 total_data = WVAL(inbuf,smb_tdrcnt);
288 total_param = WVAL(inbuf,smb_tprcnt);
289
290 if ( (total_data > TRANS2_MAX_TRANSFER)
291 || (total_param > TRANS2_MAX_TRANSFER)) {
292 printk("smb_receive_trans2: data/param too long\n");
293 return -EIO;
294 }
295
296
297 if ((*data = smb_kmalloc(total_data, GFP_KERNEL)) == NULL) {
298 printk("smb_receive_trans2: could not alloc data area\n");
299 return -ENOMEM;
300 }
301
302 if ((*param = smb_kmalloc(total_param, GFP_KERNEL)) == NULL) {
303 printk("smb_receive_trans2: could not alloc param area\n");
304 smb_kfree_s(*data, total_data);
305 return -ENOMEM;
306 }
307
308 DDPRINTK("smb_rec_trans2: total_data/param: %d/%d\n",
309 total_data, total_param);
310
311 while (1)
312 {
313 if (WVAL(inbuf,smb_prdisp)+WVAL(inbuf, smb_prcnt)
314 > total_param) {
315 printk("smb_receive_trans2: invalid parameters\n");
316 result = -EIO;
317 goto fail;
318 }
319 memcpy(*param + WVAL(inbuf,smb_prdisp),
320 smb_base(inbuf) + WVAL(inbuf,smb_proff),
321 WVAL(inbuf,smb_prcnt));
322 *param_len += WVAL(inbuf,smb_prcnt);
323
324
325 if (WVAL(inbuf,smb_drdisp)+WVAL(inbuf, smb_drcnt)>total_data) {
326 printk("smb_receive_trans2: invalid data block\n");
327 result = -EIO;
328 goto fail;
329 }
330 memcpy(*data + WVAL(inbuf,smb_drdisp),
331 smb_base(inbuf) + WVAL(inbuf,smb_droff),
332 WVAL(inbuf,smb_drcnt));
333 *data_len += WVAL(inbuf,smb_drcnt);
334
335 DDPRINTK("smb_rec_trans2: drcnt/prcnt: %d/%d\n",
336 WVAL(inbuf, smb_drcnt), WVAL(inbuf, smb_prcnt));
337
338
339
340 if ( (WVAL(inbuf,smb_tdrcnt) > total_data)
341 || (WVAL(inbuf,smb_tprcnt) > total_param)) {
342 printk("smb_receive_trans2: data/params grew!\n");
343 result = -EIO;
344 goto fail;
345 }
346
347 total_data = WVAL(inbuf,smb_tdrcnt);
348 total_param = WVAL(inbuf,smb_tprcnt);
349
350 if (total_data <= *data_len && total_param <= *param_len)
351 break;
352
353 if ((result = smb_receive(server, sock)) < 0) {
354 goto fail;
355 }
356 if (server->rcls != 0) {
357 result = -EIO;
358 goto fail;
359 }
360 }
361
362 DDPRINTK("smb_receive_trans2: normal exit\n");
363
364 return 0;
365
366 fail:
367 DPRINTK("smb_receive_trans2: failed exit\n");
368
369 smb_kfree_s(*param, 0); *param = NULL;
370 smb_kfree_s(*data, 0); *data = NULL;
371 return result;
372 }
373
374 static inline struct socket *
375 server_sock(struct smb_server *server)
376 {
377 struct file *file;
378 struct inode *inode;
379
380 if (server == NULL)
381 return NULL;
382 if ((file = server->sock_file) == NULL)
383 return NULL;
384 if ((inode = file->f_inode) == NULL)
385 return NULL;
386 return &(inode->u.socket_i);
387 }
388
389 int
390 smb_release(struct smb_server *server)
391 {
392 struct socket *sock = server_sock(server);
393 int result;
394
395 if (sock == NULL)
396 return -EINVAL;
397
398 result = sock->ops->release(sock, NULL);
399 DPRINTK("smb_release: sock->ops->release = %d\n", result);
400
401
402
403
404 sock->state = SS_UNCONNECTED;
405
406 result = sock->ops->create(sock, 0);
407 DPRINTK("smb_release: sock->ops->create = %d\n", result);
408 return result;
409 }
410
411 int
412 smb_connect(struct smb_server *server)
413 {
414 struct socket *sock = server_sock(server);
415 if (sock == NULL)
416 return -EINVAL;
417 if (sock->state != SS_UNCONNECTED) {
418 DPRINTK("smb_connect: socket is not unconnected: %d\n",
419 sock->state);
420 }
421 return sock->ops->connect(sock, (struct sockaddr *)&(server->m.addr),
422 sizeof(struct sockaddr_in), 0);
423 }
424
425
426
427
428
429
430
431 int
432 smb_request(struct smb_server *server)
433 {
434 unsigned long old_mask;
435 unsigned short fs;
436
437 int len, result, result2;
438
439 struct socket *sock = server_sock(server);
440 unsigned char *buffer = (server == NULL) ? NULL : server->packet;
441
442 if ((sock == NULL) || (buffer == NULL)) {
443 printk("smb_request: Bad server!\n");
444 return -EBADF;
445 }
446
447 if (server->state != CONN_VALID)
448 return -EIO;
449
450 #if 0
451 while (server->lock)
452 sleep_on(&server->wait);
453 server->lock = 1;
454 #endif
455
456 if ((result = smb_dont_catch_keepalive(server)) != 0) {
457 server->state = CONN_INVALID;
458 smb_invalidate_all_inodes(server);
459 return result;
460 }
461
462 len = smb_len(buffer) + 4;
463
464 DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
465
466 old_mask = current->blocked;
467 current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
468 fs = get_fs();
469 set_fs(get_ds());
470
471 result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
472 if (result < 0) {
473 printk("smb_request: send error = %d\n", result);
474 }
475 else {
476 result = smb_receive(server, sock);
477 }
478
479
480 current->signal &= ~_S(SIGPIPE);
481
482 current->blocked = old_mask;
483 set_fs(fs);
484
485 if ((result2 = smb_catch_keepalive(server)) < 0) {
486 result = result2;
487 }
488
489 #if 0
490 server->lock = 0;
491 wake_up(&server->wait);
492 #endif
493
494 if (result < 0) {
495 server->state = CONN_INVALID;
496 smb_invalidate_all_inodes(server);
497 }
498
499 DDPRINTK("smb_request: result = %d\n", result);
500
501 return result;
502 }
503
504
505
506
507
508 int
509 smb_trans2_request(struct smb_server *server,
510 int *data_len, int *param_len,
511 char **data, char **param)
512 {
513 unsigned long old_mask;
514 unsigned short fs;
515
516 int len, result, result2;
517
518 struct socket *sock = server_sock(server);
519 unsigned char *buffer = (server == NULL) ? NULL : server->packet;
520
521 if ((sock == NULL) || (buffer == NULL)) {
522 printk("smb_trans2_request: Bad server!\n");
523 return -EBADF;
524 }
525
526 if (server->state != CONN_VALID)
527 return -EIO;
528
529 #if 0
530 while (server->lock)
531 sleep_on(&server->wait);
532 server->lock = 1;
533 #endif
534
535 if ((result = smb_dont_catch_keepalive(server)) != 0) {
536 server->state = CONN_INVALID;
537 smb_invalidate_all_inodes(server);
538 return result;
539 }
540
541 len = smb_len(buffer) + 4;
542
543 DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
544
545 old_mask = current->blocked;
546 current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
547 fs = get_fs();
548 set_fs(get_ds());
549
550 result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
551 if (result < 0) {
552 printk("smb_trans2_request: send error = %d\n", result);
553 }
554 else {
555 result = smb_receive_trans2(server, sock,
556 data_len, param_len,
557 data, param);
558 }
559
560
561 current->signal &= ~_S(SIGPIPE);
562
563 current->blocked = old_mask;
564 set_fs(fs);
565
566 if ((result2 = smb_catch_keepalive(server)) < 0) {
567 result = result2;
568 }
569
570 #if 0
571 server->lock = 0;
572 wake_up(&server->wait);
573 #endif
574
575 if (result < 0) {
576 server->state = CONN_INVALID;
577 smb_invalidate_all_inodes(server);
578 }
579
580 DDPRINTK("smb_trans2_request: result = %d\n", result);
581
582 return result;
583 }
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600