1 /*
2 * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <errno.h>
33 #include <inttypes.h>
34
35 #include "MFSCommunication.h"
36
37 #include "sessions.h"
38 #include "bio.h"
39 #include "filesystem.h"
40 #include "openfiles.h"
41 #include "changelog.h"
42 #include "metadata.h"
43 #include "datapack.h"
44 #include "cfg.h"
45 #include "main.h"
46 #include "slogger.h"
47 #include "massert.h"
48
49 #define SESSION_STATS 16
50
51 #define SESSION_HASHSIZE 256
52 #define SESSION_HASH(sessionid) ((sessionid)%(SESSION_HASHSIZE))
53
54 // opened files
55 /*
56 typedef struct filelist {
57 uint32_t inode;
58 struct filelist *next;
59 } filelist;
60 */
61
62 typedef struct session {
63 uint32_t sessionid;
64 uint64_t exportscsum; // session valid for given "exports" file
65 uint8_t *info;
66 uint32_t ileng;
67 uint32_t peerip;
68 uint8_t closed;
69 uint8_t sesflags;
70 uint16_t umaskval;
71 uint8_t mingoal;
72 uint8_t maxgoal;
73 uint32_t mintrashtime;
74 uint32_t maxtrashtime;
75 uint32_t rootuid;
76 uint32_t rootgid;
77 uint32_t mapalluid;
78 uint32_t mapallgid;
79 uint32_t disables;
80 uint32_t rootinode;
81 uint32_t disconnected; // 0 = connected ; other = disconnection timestamp
82 uint32_t nsocks; // >0 - connected (number of active connections) ; 0 - not connected
83 uint32_t infopeerip; // peer ip for info
84 uint32_t infoversion; // version for info
85 uint32_t currentopstats[SESSION_STATS];
86 uint32_t lasthouropstats[SESSION_STATS];
87 // filelist *openedfiles;
88 struct session *next;
89 } session;
90
91 static session *sessionshashtab[SESSION_HASHSIZE];
92 // static session *sessionshead=NULL;
93 static uint32_t nextsessionid;
94
95 static uint32_t SessionSustainTime;
96
97 static uint32_t starttime;
98
sessions_attach_session(void * vsesdata,uint32_t peerip,uint32_t version)99 void sessions_attach_session(void* vsesdata,uint32_t peerip,uint32_t version) {
100 session *sesdata = (session*)vsesdata;
101 sesdata->closed = 0;
102 sesdata->nsocks++;
103 sesdata->infopeerip = peerip;
104 sesdata->infoversion = version;
105 sesdata->disconnected = 0;
106 }
107
sessions_close_session(uint32_t sessionid)108 void sessions_close_session(uint32_t sessionid) {
109 session *asesdata;
110 if (sessionid==0) {
111 return;
112 }
113 for (asesdata = sessionshashtab[SESSION_HASH(sessionid)] ; asesdata ; asesdata=asesdata->next) {
114 if (asesdata->sessionid==sessionid) {
115 if (asesdata->nsocks==1) {
116 asesdata->closed = 1;
117 }
118 }
119 }
120 return;
121 }
122
sessions_disconnection(void * vsesdata)123 void sessions_disconnection(void *vsesdata) {
124 session *sesdata = (session*)vsesdata;
125 if (sesdata) {
126 if (sesdata->nsocks>0) {
127 sesdata->nsocks--;
128 }
129 if (sesdata->nsocks==0) {
130 sesdata->disconnected = main_time();
131 changelog("%"PRIu32"|SESDISCONNECTED(%"PRIu32")",main_time(),sesdata->sessionid);
132 }
133 }
134 }
135
sessions_find_session(uint32_t sessionid)136 void* sessions_find_session(uint32_t sessionid) {
137 session *asesdata;
138 if (sessionid==0) {
139 return NULL;
140 }
141 for (asesdata = sessionshashtab[SESSION_HASH(sessionid)] ; asesdata ; asesdata=asesdata->next) {
142 if (asesdata->sessionid==sessionid) {
143 return asesdata;
144 }
145 }
146 return NULL;
147 }
148
sessions_clean_session(session * sesdata)149 static inline void sessions_clean_session(session *sesdata) {
150 // filelist *fl,*afl;
151 of_session_removed(sesdata->sessionid);
152 // flock_session_removed(sesdata->sessionid);
153 // fl=sesdata->openedfiles;
154 // while (fl) {
155 // afl = fl;
156 // fl=fl->next;
157 // fs_release(afl->inode,sesdata->sessionid);
158 // free(afl);
159 // }
160 // sesdata->openedfiles=NULL;
161 if (sesdata->info) {
162 free(sesdata->info);
163 }
164 }
165
sessions_store(bio * fd)166 uint8_t sessions_store(bio *fd) {
167 session *asesdata;
168 uint8_t fsesrecord[61+SESSION_STATS*8]; // 4+4+4+4+1+1+1+4+4+4+4+4+4+SESSION_STATS*4+SESSION_STATS*4
169 uint8_t *ptr;
170 int i;
171 uint32_t hpos;
172 if (fd==NULL) {
173 return 0x15;
174 }
175 ptr = fsesrecord;
176 put32bit(&ptr,nextsessionid);
177 put16bit(&ptr,SESSION_STATS);
178 if (bio_write(fd,fsesrecord,6)!=6) {
179 return 0xFF;
180 }
181 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
182 for (asesdata = sessionshashtab[hpos] ; asesdata ; asesdata=asesdata->next) {
183 if (asesdata->closed==0) {
184 ptr = fsesrecord;
185 put32bit(&ptr,asesdata->sessionid);
186 put64bit(&ptr,asesdata->exportscsum);
187 put32bit(&ptr,asesdata->ileng);
188 put32bit(&ptr,asesdata->peerip);
189 put32bit(&ptr,asesdata->rootinode);
190 put8bit(&ptr,asesdata->sesflags);
191 put16bit(&ptr,asesdata->umaskval);
192 put8bit(&ptr,asesdata->mingoal);
193 put8bit(&ptr,asesdata->maxgoal);
194 put32bit(&ptr,asesdata->mintrashtime);
195 put32bit(&ptr,asesdata->maxtrashtime);
196 put32bit(&ptr,asesdata->rootuid);
197 put32bit(&ptr,asesdata->rootgid);
198 put32bit(&ptr,asesdata->mapalluid);
199 put32bit(&ptr,asesdata->mapallgid);
200 put32bit(&ptr,asesdata->disables);
201 put32bit(&ptr,asesdata->disconnected);
202 for (i=0 ; i<SESSION_STATS ; i++) {
203 put32bit(&ptr,asesdata->currentopstats[i]);
204 }
205 for (i=0 ; i<SESSION_STATS ; i++) {
206 put32bit(&ptr,asesdata->lasthouropstats[i]);
207 }
208 if (bio_write(fd,fsesrecord,(61+SESSION_STATS*8))!=(61+SESSION_STATS*8)) {
209 return 0xFF;
210 }
211 if (asesdata->ileng>0) {
212 if (bio_write(fd,asesdata->info,asesdata->ileng)!=asesdata->ileng) {
213 return 0xFF;
214 }
215 }
216 }
217 }
218 }
219 memset(fsesrecord,0,(61+SESSION_STATS*8));
220 if (bio_write(fd,fsesrecord,(61+SESSION_STATS*8))!=(61+SESSION_STATS*8)) {
221 return 0xFF;
222 }
223 return 0;
224 }
225
sessions_load(bio * fd,uint8_t mver)226 int sessions_load(bio *fd,uint8_t mver) {
227 session *asesdata;
228 uint8_t hdr[8];
229 uint8_t *fsesrecord;
230 const uint8_t *ptr;
231 uint16_t statsinfile;
232 uint32_t recsize;
233 uint32_t i,sessionid,hpos;
234
235 if (mver<0x12) {
236 if (bio_read(fd,hdr,8)!=8) {
237 return -1;
238 }
239
240 ptr = hdr;
241 switch (get16bit(&ptr)) {
242 case 1:
243 mver = 0x10;
244 break;
245 case 2:
246 mver = 0x11;
247 break;
248 default:
249 return -1;
250 }
251 } else {
252 if (bio_read(fd,hdr,6)!=6) {
253 return -1;
254 }
255
256 ptr = hdr;
257 }
258 nextsessionid = get32bit(&ptr);
259 statsinfile = get16bit(&ptr);
260
261 if (mver<0x11) {
262 recsize = 43+statsinfile*8;
263 } else if (mver<0x13) {
264 recsize = 47+statsinfile*8;
265 } else if (mver<0x14) {
266 recsize = 55+statsinfile*8;
267 } else if (mver<0x15) {
268 recsize = 57+statsinfile*8;
269 } else {
270 recsize = 61+statsinfile*8;
271 }
272 fsesrecord = malloc(recsize);
273 passert(fsesrecord);
274
275 while(1) {
276 if (bio_read(fd,fsesrecord,recsize)==recsize) {
277 ptr = fsesrecord;
278 sessionid = get32bit(&ptr);
279 if (sessionid==0) {
280 free(fsesrecord);
281 return 0;
282 }
283 asesdata = (session*)malloc(sizeof(session));
284 passert(asesdata);
285 asesdata->sessionid = sessionid;
286 if (mver>=0x13) {
287 asesdata->exportscsum = get64bit(&ptr);
288 } else {
289 asesdata->exportscsum = 0;
290 }
291 asesdata->ileng = get32bit(&ptr);
292 asesdata->peerip = get32bit(&ptr);
293 asesdata->rootinode = get32bit(&ptr);
294 asesdata->sesflags = get8bit(&ptr);
295 if (mver>=0x14) {
296 asesdata->umaskval = get16bit(&ptr);
297 } else {
298 asesdata->umaskval = 0;
299 }
300 asesdata->mingoal = get8bit(&ptr);
301 asesdata->maxgoal = get8bit(&ptr);
302 asesdata->mintrashtime = get32bit(&ptr);
303 asesdata->maxtrashtime = get32bit(&ptr);
304 asesdata->rootuid = get32bit(&ptr);
305 asesdata->rootgid = get32bit(&ptr);
306 asesdata->mapalluid = get32bit(&ptr);
307 asesdata->mapallgid = get32bit(&ptr);
308 if (mver>=0x15) {
309 asesdata->disables = get32bit(&ptr);
310 } else {
311 asesdata->disables = 0;
312 }
313 if (mver>=0x11) {
314 asesdata->disconnected = get32bit(&ptr);
315 } else {
316 asesdata->disconnected = main_time();
317 }
318 asesdata->info = NULL;
319 asesdata->closed = 0;
320 // asesdata->openedfiles = NULL;
321 asesdata->nsocks = 0;
322 asesdata->infopeerip = asesdata->peerip;
323 asesdata->infoversion = 0;
324 for (i=0 ; i<SESSION_STATS ; i++) {
325 asesdata->currentopstats[i] = (i<statsinfile)?get32bit(&ptr):0;
326 }
327 if (statsinfile>SESSION_STATS) {
328 ptr+=4*(statsinfile-SESSION_STATS);
329 }
330 for (i=0 ; i<SESSION_STATS ; i++) {
331 asesdata->lasthouropstats[i] = (i<statsinfile)?get32bit(&ptr):0;
332 }
333 if (asesdata->ileng>0) {
334 asesdata->info = malloc(asesdata->ileng+1);
335 passert(asesdata->info);
336 if (bio_read(fd,asesdata->info,asesdata->ileng)!=asesdata->ileng) {
337 free(asesdata->info);
338 free(asesdata);
339 free(fsesrecord);
340 return -1;
341 }
342 asesdata->info[asesdata->ileng]=0;
343 }
344 hpos = SESSION_HASH(sessionid);
345 asesdata->next = sessionshashtab[hpos];
346 sessionshashtab[hpos] = asesdata;
347 } else {
348 free(fsesrecord);
349 return -1;
350 }
351 }
352 }
353
354 /* import from old metadata */
sessions_set_nextsessionid(uint32_t nsi)355 void sessions_set_nextsessionid(uint32_t nsi) {
356 nextsessionid = nsi;
357 }
358 /*
359 uint32_t sessions_getnextsessionid(void) {
360 return nextsessionid;
361 }
362 */
sessions_import_data(void)363 int sessions_import_data(void) {
364 session *asesdata;
365 // uint8_t fsesrecord[33+SESSION_STATS*8]; // 4+4+4+4+1+4+4+4+4+SESSION_STATS*4+SESSION_STATS*4
366 uint8_t hdr[8];
367 uint8_t *fsesrecord;
368 const uint8_t *ptr;
369 uint8_t mapalldata;
370 uint8_t goaltrashdata;
371 uint32_t i,statsinfile;
372 uint32_t hpos;
373 int r;
374 FILE *fd;
375
376 fd = fopen("sessions.mfs","r");
377 if (fd==NULL) {
378 mfs_errlog_silent(LOG_WARNING,"can't load sessions, fopen error");
379 if (errno==ENOENT) { // it's ok if file does not exist
380 nextsessionid = 1;
381 return 0;
382 } else {
383 return -1;
384 }
385 }
386 if (fread(hdr,8,1,fd)!=1) {
387 syslog(LOG_WARNING,"can't load sessions, fread error");
388 fclose(fd);
389 return -1;
390 }
391 if (memcmp(hdr,MFSSIGNATURE "S 1.5",8)==0) {
392 mapalldata = 0;
393 goaltrashdata = 0;
394 statsinfile = 16;
395 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\001",8)==0) {
396 mapalldata = 1;
397 goaltrashdata = 0;
398 statsinfile = 16;
399 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\002",8)==0) {
400 mapalldata = 1;
401 goaltrashdata = 0;
402 statsinfile = 21;
403 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\003",8)==0) {
404 mapalldata = 1;
405 goaltrashdata = 0;
406 if (fread(hdr,2,1,fd)!=1) {
407 syslog(LOG_WARNING,"can't load sessions, fread error");
408 fclose(fd);
409 return -1;
410 }
411 ptr = hdr;
412 statsinfile = get16bit(&ptr);
413 } else if (memcmp(hdr,MFSSIGNATURE "S \001\006\004",8)==0) {
414 mapalldata = 1;
415 goaltrashdata = 1;
416 if (fread(hdr,2,1,fd)!=1) {
417 syslog(LOG_WARNING,"can't load sessions, fread error");
418 fclose(fd);
419 return -1;
420 }
421 ptr = hdr;
422 statsinfile = get16bit(&ptr);
423 } else {
424 syslog(LOG_WARNING,"can't load sessions, bad header");
425 fclose(fd);
426 return -1;
427 }
428
429 if (mapalldata==0) {
430 fsesrecord = malloc(25+statsinfile*8);
431 } else if (goaltrashdata==0) {
432 fsesrecord = malloc(33+statsinfile*8);
433 } else {
434 fsesrecord = malloc(43+statsinfile*8);
435 }
436 passert(fsesrecord);
437
438 while (!feof(fd)) {
439 if (mapalldata==0) {
440 r = fread(fsesrecord,25+statsinfile*8,1,fd);
441 } else if (goaltrashdata==0) {
442 r = fread(fsesrecord,33+statsinfile*8,1,fd);
443 } else {
444 r = fread(fsesrecord,43+statsinfile*8,1,fd);
445 }
446 if (r==1) {
447 ptr = fsesrecord;
448 asesdata = (session*)malloc(sizeof(session));
449 passert(asesdata);
450 asesdata->sessionid = get32bit(&ptr);
451 asesdata->ileng = get32bit(&ptr);
452 asesdata->peerip = get32bit(&ptr);
453 asesdata->rootinode = get32bit(&ptr);
454 asesdata->sesflags = get8bit(&ptr);
455 asesdata->umaskval = 0;
456 if (goaltrashdata) {
457 asesdata->mingoal = get8bit(&ptr);
458 asesdata->maxgoal = get8bit(&ptr);
459 asesdata->mintrashtime = get32bit(&ptr);
460 asesdata->maxtrashtime = get32bit(&ptr);
461 } else { // set defaults (no limits)
462 asesdata->mingoal = 1;
463 asesdata->maxgoal = 9;
464 asesdata->mintrashtime = 0;
465 asesdata->maxtrashtime = UINT32_C(0xFFFFFFFF);
466 }
467 asesdata->rootuid = get32bit(&ptr);
468 asesdata->rootgid = get32bit(&ptr);
469 if (mapalldata) {
470 asesdata->mapalluid = get32bit(&ptr);
471 asesdata->mapallgid = get32bit(&ptr);
472 } else {
473 asesdata->mapalluid = 0;
474 asesdata->mapallgid = 0;
475 }
476 asesdata->disables = 0;
477 asesdata->info = NULL;
478 asesdata->closed = 0;
479 // asesdata->openedfiles = NULL;
480 asesdata->disconnected = main_time();
481 asesdata->nsocks = 0;
482 asesdata->infopeerip = 0;
483 asesdata->infoversion = 0;
484 asesdata->exportscsum = 0;
485 for (i=0 ; i<SESSION_STATS ; i++) {
486 asesdata->currentopstats[i] = (i<statsinfile)?get32bit(&ptr):0;
487 }
488 if (statsinfile>SESSION_STATS) {
489 ptr+=4*(statsinfile-SESSION_STATS);
490 }
491 for (i=0 ; i<SESSION_STATS ; i++) {
492 asesdata->lasthouropstats[i] = (i<statsinfile)?get32bit(&ptr):0;
493 }
494 if (asesdata->ileng>0) {
495 asesdata->info = malloc(asesdata->ileng+1);
496 passert(asesdata->info);
497 if (fread(asesdata->info,asesdata->ileng,1,fd)!=1) {
498 free(asesdata->info);
499 free(asesdata);
500 free(fsesrecord);
501 syslog(LOG_WARNING,"can't load sessions, fread error");
502 fclose(fd);
503 return -1;
504 }
505 asesdata->info[asesdata->ileng]=0;
506 }
507 hpos = SESSION_HASH(asesdata->sessionid);
508 asesdata->next = sessionshashtab[hpos];
509 sessionshashtab[hpos] = asesdata;
510 }
511 if (ferror(fd)) {
512 free(fsesrecord);
513 syslog(LOG_WARNING,"can't load sessions, fread error");
514 fclose(fd);
515 return -1;
516 }
517 }
518 free(fsesrecord);
519 syslog(LOG_NOTICE,"sessions have been loaded");
520 fclose(fd);
521 return 1;
522 }
523
sessions_import(void)524 void sessions_import(void) {
525 fprintf(stderr,"loading sessions ... ");
526 fflush(stderr);
527 switch (sessions_import_data()) {
528 case 0: // no file
529 fprintf(stderr,"file not found\n");
530 fprintf(stderr,"if it is not fresh installation then you have to restart all active mounts !!!\n");
531 break;
532 case 1: // file loaded
533 fprintf(stderr,"ok\n");
534 fprintf(stderr,"sessions file has been loaded\n");
535 break;
536 default:
537 fprintf(stderr,"error\n");
538 fprintf(stderr,"due to missing sessions you have to restart all active mounts !!!\n");
539 break;
540 }
541 }
542
sessions_datasize(uint8_t vmode)543 uint32_t sessions_datasize(uint8_t vmode) {
544 session *sesdata;
545 uint32_t hpos;
546 uint32_t size;
547
548 size = 2;
549 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
550 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
551 if (vmode<2) {
552 if (sesdata->nsocks>0) {
553 size += 37+SESSION_STATS*8+(vmode?10:0);
554 size += sesdata->ileng;
555 if (sesdata->rootinode==0) {
556 size += 1;
557 } else {
558 size += fs_getdirpath_size(sesdata->rootinode);
559 }
560 }
561 } else {
562 if (vmode<3) {
563 size += 56+SESSION_STATS*8;
564 } else if (vmode<4) {
565 size += 58+SESSION_STATS*8;
566 } else {
567 size += 62+SESSION_STATS*8;
568 }
569 size += sesdata->ileng;
570 if (sesdata->rootinode==0) {
571 size += 1;
572 } else {
573 size += fs_getdirpath_size(sesdata->rootinode);
574 }
575 }
576 }
577 }
578 return size;
579 }
580
sessions_datafill(uint8_t * ptr,uint8_t vmode)581 void sessions_datafill(uint8_t *ptr,uint8_t vmode) {
582 session *sesdata;
583 uint32_t now;
584 uint32_t hpos;
585 uint32_t pleng,i;
586
587 put16bit(&ptr,SESSION_STATS);
588 now = main_time();
589 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
590 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
591 if (vmode<2) {
592 if (sesdata->nsocks>0) {
593 put32bit(&ptr,sesdata->sessionid);
594 put32bit(&ptr,sesdata->infopeerip);
595 put32bit(&ptr,sesdata->infoversion);
596 put32bit(&ptr,sesdata->ileng);
597 if (sesdata->ileng>0) {
598 memcpy(ptr,sesdata->info,sesdata->ileng);
599 ptr+=sesdata->ileng;
600 }
601 if (sesdata->rootinode==0) { // meta
602 pleng = 1;
603 put32bit(&ptr,pleng);
604 put8bit(&ptr,'.');
605 } else {
606 pleng = fs_getdirpath_size(sesdata->rootinode);
607 put32bit(&ptr,pleng);
608 if (pleng>0) {
609 fs_getdirpath_data(sesdata->rootinode,ptr,pleng);
610 ptr+=pleng;
611 }
612 }
613 put8bit(&ptr,sesdata->sesflags);
614 put32bit(&ptr,sesdata->rootuid);
615 put32bit(&ptr,sesdata->rootgid);
616 put32bit(&ptr,sesdata->mapalluid);
617 put32bit(&ptr,sesdata->mapallgid);
618 if (vmode) {
619 put8bit(&ptr,sesdata->mingoal);
620 put8bit(&ptr,sesdata->maxgoal);
621 put32bit(&ptr,sesdata->mintrashtime);
622 put32bit(&ptr,sesdata->maxtrashtime);
623 }
624 for (i=0 ; i<SESSION_STATS ; i++) {
625 put32bit(&ptr,sesdata->currentopstats[i]);
626 }
627 for (i=0 ; i<SESSION_STATS ; i++) {
628 put32bit(&ptr,sesdata->lasthouropstats[i]);
629 }
630 }
631 } else {
632 put32bit(&ptr,sesdata->sessionid);
633 if (sesdata->infopeerip==0 && sesdata->peerip!=0) {
634 put32bit(&ptr,sesdata->peerip);
635 } else {
636 put32bit(&ptr,sesdata->infopeerip);
637 }
638 put32bit(&ptr,sesdata->infoversion);
639 put32bit(&ptr,of_noofopenedfiles(sesdata->sessionid));
640 if (sesdata->nsocks>255) {
641 put8bit(&ptr,255);
642 } else {
643 put8bit(&ptr,sesdata->nsocks);
644 }
645 if (sesdata->nsocks>0) {
646 put32bit(&ptr,UINT32_C(0xFFFFFFFF));
647 } else {
648 if (sesdata->closed || sesdata->disconnected+SessionSustainTime<now) {
649 put32bit(&ptr,0);
650 } else {
651 put32bit(&ptr,sesdata->disconnected+SessionSustainTime-now);
652 }
653 }
654 put32bit(&ptr,sesdata->ileng);
655 if (sesdata->ileng>0) {
656 memcpy(ptr,sesdata->info,sesdata->ileng);
657 ptr+=sesdata->ileng;
658 }
659 if (sesdata->rootinode==0) { // meta
660 pleng = 1;
661 put32bit(&ptr,pleng);
662 put8bit(&ptr,'.');
663 } else {
664 pleng = fs_getdirpath_size(sesdata->rootinode);
665 put32bit(&ptr,pleng);
666 if (pleng>0) {
667 fs_getdirpath_data(sesdata->rootinode,ptr,pleng);
668 ptr+=pleng;
669 }
670 }
671 put8bit(&ptr,sesdata->sesflags);
672 if (vmode>=3) {
673 put16bit(&ptr,sesdata->umaskval);
674 }
675 put32bit(&ptr,sesdata->rootuid);
676 put32bit(&ptr,sesdata->rootgid);
677 put32bit(&ptr,sesdata->mapalluid);
678 put32bit(&ptr,sesdata->mapallgid);
679 put8bit(&ptr,sesdata->mingoal);
680 put8bit(&ptr,sesdata->maxgoal);
681 put32bit(&ptr,sesdata->mintrashtime);
682 put32bit(&ptr,sesdata->maxtrashtime);
683 if (vmode>=4) {
684 put32bit(&ptr,sesdata->disables);
685 }
686 for (i=0 ; i<SESSION_STATS ; i++) {
687 put32bit(&ptr,sesdata->currentopstats[i]);
688 }
689 for (i=0 ; i<SESSION_STATS ; i++) {
690 put32bit(&ptr,sesdata->lasthouropstats[i]);
691 }
692 }
693 }
694 }
695 }
696
sessions_create_session(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng)697 static inline void* sessions_create_session(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng) {
698 session *sesdata;
699 uint32_t hpos;
700
701 sesdata = (session*)malloc(sizeof(session));
702 passert(sesdata);
703 sesdata->sessionid = nextsessionid++;
704 sesdata->exportscsum = exportscsum;
705 sesdata->rootinode = rootinode;
706 sesdata->sesflags = (sesflags&(~SESFLAG_METARESTORE));
707 sesdata->umaskval = umaskval;
708 sesdata->rootuid = rootuid;
709 sesdata->rootgid = rootgid;
710 sesdata->mapalluid = mapalluid;
711 sesdata->mapallgid = mapallgid;
712 sesdata->mingoal = mingoal;
713 sesdata->maxgoal = maxgoal;
714 sesdata->mintrashtime = mintrashtime;
715 sesdata->maxtrashtime = maxtrashtime;
716 sesdata->disables = disables;
717 sesdata->peerip = peerip;
718 while (ileng>0 && info[ileng-1]==0) {
719 ileng--;
720 }
721 if (ileng>0) {
722 sesdata->info = malloc(ileng+1);
723 passert(sesdata->info);
724 memcpy(sesdata->info,info,ileng);
725 sesdata->info[ileng]=0;
726 sesdata->ileng = ileng;
727 } else {
728 sesdata->info = NULL;
729 sesdata->ileng = 0;
730 }
731 sesdata->closed = 0;
732 // sesdata->openedfiles = NULL;
733 sesdata->disconnected = 0;
734 sesdata->nsocks = 0;
735 sesdata->infopeerip = 0;
736 sesdata->infoversion = 0;
737 memset(sesdata->currentopstats,0,4*SESSION_STATS);
738 memset(sesdata->lasthouropstats,0,4*SESSION_STATS);
739 hpos = SESSION_HASH(sesdata->sessionid);
740 sesdata->next = sessionshashtab[hpos];
741 sessionshashtab[hpos] = sesdata;
742 if ((sesflags&SESFLAG_METARESTORE)==0) {
743 changelog("%" PRIu32 "|SESADD(#%"PRIu64",%"PRIu32",%"PRIu8",0%03"PRIo16",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu8",%"PRIu8",%"PRIu32",%"PRIu32",0x%08"PRIX32",%"PRIu32",%s):%"PRIu32,main_time(),exportscsum,rootinode,sesflags,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,changelog_escape_name(ileng,(uint8_t*)info),sesdata->sessionid);
744 } else {
745 meta_version_inc();
746 }
747 return sesdata;
748 }
749
sessions_change_session(session * sesdata,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng)750 static inline void sessions_change_session(session *sesdata,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng) {
751 sesdata->rootinode = rootinode;
752 sesdata->exportscsum = exportscsum;
753 sesdata->sesflags = (sesflags&(~SESFLAG_METARESTORE));
754 sesdata->umaskval = umaskval;
755 sesdata->rootuid = rootuid;
756 sesdata->rootgid = rootgid;
757 sesdata->mapalluid = mapalluid;
758 sesdata->mapallgid = mapallgid;
759 sesdata->mingoal = mingoal;
760 sesdata->maxgoal = maxgoal;
761 sesdata->mintrashtime = mintrashtime;
762 sesdata->maxtrashtime = maxtrashtime;
763 sesdata->disables = disables;
764 sesdata->peerip = peerip;
765 if (sesdata->info!=NULL) {
766 free(sesdata->info);
767 }
768 while (ileng>0 && info[ileng-1]==0) {
769 ileng--;
770 }
771 if (ileng>0) {
772 sesdata->info = malloc(ileng+1);
773 passert(sesdata->info);
774 memcpy(sesdata->info,info,ileng);
775 sesdata->info[ileng]=0;
776 sesdata->ileng = ileng;
777 } else {
778 sesdata->info = NULL;
779 sesdata->ileng = 0;
780 }
781
782 if ((sesflags&SESFLAG_METARESTORE)==0) {
783 changelog("%" PRIu32 "|SESCHANGED(%"PRIu32",#%"PRIu64",%"PRIu32",%"PRIu8",0%03"PRIo16",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu8",%"PRIu8",%"PRIu32",%"PRIu32",0x%08"PRIX32",%"PRIu32",%s)",main_time(),sesdata->sessionid,exportscsum,rootinode,sesflags,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,changelog_escape_name(ileng,info));
784 } else {
785 meta_version_inc();
786 }
787 }
788
sessions_new_session(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng)789 void* sessions_new_session(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng) {
790 session *sesdata;
791 sesdata = sessions_create_session(exportscsum,rootinode,sesflags&(~SESFLAG_METARESTORE),umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,info,ileng);
792 return sesdata;
793 }
794
sessions_mr_sesadd(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng,uint32_t sessionid)795 uint8_t sessions_mr_sesadd(uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng,uint32_t sessionid) {
796 session *sesdata;
797 sesdata = sessions_create_session(exportscsum,rootinode,sesflags|SESFLAG_METARESTORE,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,info,ileng);
798 if (sesdata->sessionid!=sessionid) {
799 return MFS_ERROR_MISMATCH;
800 }
801 return MFS_STATUS_OK;
802 }
803
sessions_chg_session(void * vsesdata,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng)804 void sessions_chg_session(void *vsesdata,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng) {
805 session *sesdata = (session*)vsesdata;
806 sessions_change_session(sesdata,exportscsum,rootinode,sesflags&(~SESFLAG_METARESTORE),umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,info,ileng);
807 }
808
sessions_mr_seschanged(uint32_t sessionid,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t * info,uint32_t ileng)809 uint8_t sessions_mr_seschanged(uint32_t sessionid,uint64_t exportscsum,uint32_t rootinode,uint8_t sesflags,uint16_t umaskval,uint32_t rootuid,uint32_t rootgid,uint32_t mapalluid,uint32_t mapallgid,uint8_t mingoal,uint8_t maxgoal,uint32_t mintrashtime,uint32_t maxtrashtime,uint32_t disables,uint32_t peerip,const uint8_t *info,uint32_t ileng) {
810 session *sesdata;
811 sesdata = sessions_find_session(sessionid);
812 if (sesdata==NULL) {
813 return MFS_ERROR_MISMATCH;
814 }
815 sessions_change_session(sesdata,exportscsum,rootinode,sesflags|SESFLAG_METARESTORE,umaskval,rootuid,rootgid,mapalluid,mapallgid,mingoal,maxgoal,mintrashtime,maxtrashtime,disables,peerip,info,ileng);
816 return MFS_STATUS_OK;
817 }
818
sessions_mr_sesdel(uint32_t sessionid)819 uint8_t sessions_mr_sesdel(uint32_t sessionid) {
820 session **sesdata,*asesdata;
821 uint8_t status = MFS_ERROR_BADSESSIONID;
822 uint32_t hpos;
823
824 hpos = SESSION_HASH(sessionid);
825 sesdata = sessionshashtab + hpos;
826 while ((asesdata=*sesdata)) {
827 if (asesdata->sessionid==sessionid) {
828 sessions_clean_session(asesdata);
829 *sesdata = asesdata->next;
830 free(asesdata);
831 status = MFS_STATUS_OK;
832 } else {
833 sesdata = &(asesdata->next);
834 }
835 }
836 if (status==MFS_STATUS_OK) {
837 meta_version_inc();
838 }
839 return status;
840 }
841
sessions_mr_disconnected(uint32_t sessionid,uint32_t disctime)842 uint8_t sessions_mr_disconnected(uint32_t sessionid,uint32_t disctime) {
843 session *sesdata;
844
845 for (sesdata = sessionshashtab[SESSION_HASH(sessionid)] ; sesdata ; sesdata = sesdata->next) {
846 if (sesdata->sessionid == sessionid) {
847 sesdata->disconnected = disctime;
848 meta_version_inc();
849 return MFS_STATUS_OK;
850 }
851 }
852 return MFS_ERROR_NOTFOUND;
853 }
854
sessions_mr_session(uint32_t sessionid)855 uint8_t sessions_mr_session(uint32_t sessionid) {
856 if (sessionid!=nextsessionid) {
857 return MFS_ERROR_MISMATCH;
858 }
859 nextsessionid++;
860 meta_version_inc();
861 return MFS_STATUS_OK;
862 }
863
sessions_new(void)864 void sessions_new(void) {
865 nextsessionid=1;
866 }
867
sessions_get_id(void * vsesdata)868 uint32_t sessions_get_id(void *vsesdata) {
869 session *sesdata = (session*)vsesdata;
870 return sesdata->sessionid;
871 }
872
sessions_get_exportscsum(void * vsesdata)873 uint64_t sessions_get_exportscsum(void *vsesdata) {
874 session *sesdata = (session*)vsesdata;
875 return sesdata->exportscsum;
876 }
877
sessions_get_peerip(void * vsesdata)878 uint32_t sessions_get_peerip(void *vsesdata) {
879 session *sesdata = (session*)vsesdata;
880 return sesdata->peerip;
881 }
882
sessions_get_rootinode(void * vsesdata)883 uint32_t sessions_get_rootinode(void *vsesdata) {
884 session *sesdata = (session*)vsesdata;
885 return sesdata->rootinode;
886 }
887
sessions_get_sesflags(void * vsesdata)888 uint32_t sessions_get_sesflags(void *vsesdata) {
889 session *sesdata = (session*)vsesdata;
890 return sesdata->sesflags | ((sesdata->infoversion>=VERSION2INT(1,7,32))?SESFLAG_ATTRBIT:0);
891 }
892
sessions_get_umask(void * vsesdata)893 uint16_t sessions_get_umask(void *vsesdata) {
894 session *sesdata = (session*)vsesdata;
895 return sesdata->umaskval;
896 }
897
sessions_get_disables(void * vsesdata)898 uint32_t sessions_get_disables(void *vsesdata) {
899 session *sesdata = (session*)vsesdata;
900 return sesdata->disables;
901 }
902
sessions_is_root_remapped(void * vsesdata)903 uint8_t sessions_is_root_remapped(void *vsesdata) {
904 session *sesdata = (session*)vsesdata;
905 return (sesdata->rootuid!=0)?1:0;
906 }
907
sessions_check_goal(void * vsesdata,uint8_t smode,uint8_t goal)908 uint8_t sessions_check_goal(void *vsesdata,uint8_t smode,uint8_t goal) {
909 session *sesdata = (session*)vsesdata;
910 switch (smode) {
911 case SMODE_EXCHANGE:
912 case SMODE_SET:
913 if (goal<sesdata->mingoal || goal>sesdata->maxgoal) {
914 return MFS_ERROR_EPERM;
915 }
916 break;
917 case SMODE_INCREASE:
918 if (goal>sesdata->maxgoal) {
919 return MFS_ERROR_EPERM;
920 }
921 break;
922 case SMODE_DECREASE:
923 if (goal<sesdata->mingoal) {
924 return MFS_ERROR_EPERM;
925 }
926 break;
927 }
928 return MFS_STATUS_OK;
929 }
930
sessions_check_trashtime(void * vsesdata,uint8_t smode,uint32_t trashtime)931 uint8_t sessions_check_trashtime(void *vsesdata,uint8_t smode,uint32_t trashtime) {
932 session *sesdata = (session*)vsesdata;
933 switch (smode) {
934 case SMODE_EXCHANGE:
935 case SMODE_SET:
936 if (trashtime<sesdata->mintrashtime || trashtime>sesdata->maxtrashtime) {
937 return MFS_ERROR_EPERM;
938 }
939 break;
940 case SMODE_INCREASE:
941 if (trashtime>sesdata->maxtrashtime) {
942 return MFS_ERROR_EPERM;
943 }
944 break;
945 case SMODE_DECREASE:
946 if (trashtime<sesdata->mintrashtime) {
947 return MFS_ERROR_EPERM;
948 }
949 break;
950 }
951 return MFS_STATUS_OK;
952 }
953
sessions_inc_stats(void * vsesdata,uint8_t statid)954 void sessions_inc_stats(void *vsesdata,uint8_t statid) {
955 session *sesdata = (session*)vsesdata;
956 if (sesdata && statid<SESSION_STATS) {
957 sesdata->currentopstats[statid]++;
958 }
959 }
960
sessions_ugid_remap(void * vsesdata,uint32_t * auid,uint32_t * agid)961 void sessions_ugid_remap(void *vsesdata,uint32_t *auid,uint32_t *agid) {
962 session *sesdata = (session*)vsesdata;
963 if (*auid==0) {
964 *auid = sesdata->rootuid;
965 if (agid) {
966 *agid = sesdata->rootgid;
967 }
968 } else if (sesdata->sesflags&SESFLAG_MAPALL) {
969 *auid = sesdata->mapalluid;
970 if (agid) {
971 *agid = sesdata->mapallgid;
972 }
973 }
974 }
975
sessions_check(void)976 void sessions_check(void) {
977 session **sesdata,*asesdata;
978 uint32_t now;
979 uint32_t hpos;
980
981 now = main_time();
982 if (starttime+120>now) {
983 return;
984 }
985 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
986 sesdata = sessionshashtab + hpos;
987 while ((asesdata=*sesdata)) {
988 if (asesdata->nsocks==0 && (asesdata->closed || asesdata->disconnected+SessionSustainTime<now)) {
989 syslog(LOG_NOTICE,"remove session: %u",asesdata->sessionid);
990 sessions_clean_session(asesdata);
991 changelog("%"PRIu32"|SESDEL(%"PRIu32")",main_time(),asesdata->sessionid);
992 *sesdata = asesdata->next;
993 free(asesdata);
994 } else {
995 sesdata = &(asesdata->next);
996 }
997 }
998 }
999 }
1000
sessions_force_remove(uint32_t sessionid)1001 uint8_t sessions_force_remove(uint32_t sessionid) {
1002 session **sesdata,*asesdata;
1003 uint32_t hpos;
1004
1005 hpos = SESSION_HASH(sessionid);
1006 sesdata = sessionshashtab + hpos;
1007 while ((asesdata=*sesdata)) {
1008 if (asesdata->sessionid==sessionid) {
1009 if (asesdata->nsocks==0) {
1010 syslog(LOG_NOTICE,"remove session: %u",asesdata->sessionid);
1011 sessions_clean_session(asesdata);
1012 changelog("%"PRIu32"|SESDEL(%"PRIu32")",main_time(),asesdata->sessionid);
1013 *sesdata = asesdata->next;
1014 free(asesdata);
1015 return MFS_STATUS_OK;
1016 } else {
1017 return MFS_ERROR_ACTIVE;
1018 }
1019 } else {
1020 sesdata = &(asesdata->next);
1021 }
1022 }
1023 return MFS_ERROR_NOTFOUND;
1024 }
1025
sessions_statsmove(void)1026 void sessions_statsmove(void) {
1027 session *sesdata;
1028 uint32_t hpos;
1029 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1030 for (sesdata = sessionshashtab[hpos] ; sesdata ; sesdata=sesdata->next) {
1031 memcpy(sesdata->lasthouropstats,sesdata->currentopstats,4*SESSION_STATS);
1032 memset(sesdata->currentopstats,0,4*SESSION_STATS);
1033 }
1034 }
1035 }
1036
sessions_cleanup(void)1037 void sessions_cleanup(void) {
1038 session *ss,*ssn;
1039 uint32_t hpos;
1040 // filelist *of,*ofn;
1041
1042 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1043 for (ss = sessionshashtab[hpos] ; ss ; ss = ssn) {
1044 ssn = ss->next;
1045 // for (of = ss->openedfiles ; of ; of = ofn) {
1046 // ofn = of->next;
1047 // free(of);
1048 // }
1049 if (ss->info) {
1050 free(ss->info);
1051 }
1052 free(ss);
1053 }
1054 sessionshashtab[hpos] = NULL;
1055 }
1056 }
1057
sessions_reload(void)1058 void sessions_reload(void) {
1059 SessionSustainTime = cfg_getuint32("SESSION_SUSTAIN_TIME",86400);
1060 if (SessionSustainTime>7*86400) {
1061 SessionSustainTime=7*86400;
1062 mfs_syslog(LOG_WARNING,"SESSION_SUSTAIN_TIME too big (more than week) - setting this value to one week");
1063 }
1064 if (SessionSustainTime<60) {
1065 SessionSustainTime=60;
1066 mfs_syslog(LOG_WARNING,"SESSION_SUSTAIN_TIME too low (less than minute) - setting this value to one minute");
1067 }
1068 }
1069
sessions_init(void)1070 int sessions_init(void) {
1071 uint32_t hpos;
1072
1073 starttime = main_time();
1074 for (hpos = 0 ; hpos < SESSION_HASHSIZE ; hpos++) {
1075 sessionshashtab[hpos] = NULL;
1076 }
1077 sessions_reload();
1078 main_time_register(10,0,sessions_check);
1079 main_time_register(3600,0,sessions_statsmove);
1080 main_reload_register(sessions_reload);
1081 return 0;
1082 }
1083