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