Initial revision
This commit is contained in:
parent
6102cd8aa6
commit
2a963be06d
89
include/s_extern.h
Normal file
89
include/s_extern.h
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#ifndef _FSP_S_EXTERN_H_
|
||||||
|
#define _FSP_S_EXTERN_H_ 1
|
||||||
|
|
||||||
|
/* conf.c, read and check configuration */
|
||||||
|
extern int daemonize,use_prebuild_dirlists,read_only,dbug;
|
||||||
|
extern int permit_passwordless_owners;
|
||||||
|
extern int use_access_files,use_directory_mtime;
|
||||||
|
extern int priv_mode,no_unnamed,logging,grab_enabled,ver_enabled;
|
||||||
|
extern int homedir_restricted;
|
||||||
|
extern uid_t run_uid;
|
||||||
|
extern gid_t run_gid;
|
||||||
|
extern unsigned int maxthcallowed;
|
||||||
|
extern unsigned short udp_port,packetsize;
|
||||||
|
extern time_t retry_timeout,session_timeout,stat_cache_timeout;
|
||||||
|
extern char *logname,*readme_file,*dumpname;
|
||||||
|
extern char *home_dir;
|
||||||
|
extern unsigned int dir_cache_limit, stat_cache_limit,fp_cache_limit;
|
||||||
|
extern char *tmp_dir;
|
||||||
|
extern mode_t upload_umask, system_umask;
|
||||||
|
void load_configuration PROTO1(const char *, conffile);
|
||||||
|
void destroy_configuration PROTO0((void));
|
||||||
|
|
||||||
|
/* file.c, file based disk i/o operations */
|
||||||
|
int init_caches PROTO0((void));
|
||||||
|
void shutdown_caches PROTO0((void));
|
||||||
|
void stat_caches PROTO1(FILE *,fp);
|
||||||
|
const char *validate_path PROTO0((char *, unsigned, PPATH *,DIRINFO **, int));
|
||||||
|
const char *server_get_dir PROTO0((DIRLISTING **,const DIRINFO *));
|
||||||
|
const char *server_del_file PROTO0((PPATH *, DIRINFO *));
|
||||||
|
const char *server_del_dir PROTO2(PPATH *, pp, DIRINFO *,di);
|
||||||
|
const char *server_make_dir PROTO0((PPATH *, unsigned long,DIRINFO **));
|
||||||
|
const char *server_get_file PROTO0((PPATH *, FILE **, unsigned long,
|
||||||
|
unsigned short,DIRINFO *));
|
||||||
|
const char *server_get_pro PROTO3(DIRINFO *, di, char *, result, const char *, acc);
|
||||||
|
const char *server_set_pro PROTO2(DIRINFO *,di, const char *, key);
|
||||||
|
const char *server_up_load PROTO0((char *, unsigned int, unsigned long, unsigned long,
|
||||||
|
unsigned short));
|
||||||
|
const char *server_install PROTO0((PPATH *, unsigned long, unsigned short,const char *,DIRINFO *,unsigned int,const char *));
|
||||||
|
const char *server_secure_file PROTO0((PPATH *, unsigned long,
|
||||||
|
unsigned short,DIRINFO *));
|
||||||
|
const char *server_grab_file PROTO0((FILE **, unsigned long,
|
||||||
|
unsigned short));
|
||||||
|
const char *server_grab_done PROTO0((unsigned long, unsigned short));
|
||||||
|
const char *server_stat PROTO1(UBUF *, buf);
|
||||||
|
const char *server_rename PROTO0((char *,unsigned int,unsigned int));
|
||||||
|
void init_home_dir PROTO0((void));
|
||||||
|
|
||||||
|
/* filecache.c, open filehandles cache */
|
||||||
|
|
||||||
|
/* iprange.c IP range services */
|
||||||
|
extern IPrange *iptab;
|
||||||
|
const char *check_ip_table PROTO2(unsigned long, inet_num,IPrange *,table);
|
||||||
|
void free_ip_table PROTO1(IPrange *,table);
|
||||||
|
void add_ipline PROTO2(const char *, text, IPrange **, table);
|
||||||
|
void dump_iptab PROTO2(IPrange *,table,FILE *, fp);
|
||||||
|
|
||||||
|
/* host.c, DNS and IP host databases */
|
||||||
|
HTAB *find_host PROTO0((unsigned long));
|
||||||
|
int init_htab PROTO0((void));
|
||||||
|
int dump_htab PROTO1(FILE *,fn);
|
||||||
|
|
||||||
|
/* server.c, network server operations */
|
||||||
|
extern time_t cur_time;
|
||||||
|
extern int shutdowning;
|
||||||
|
RETSIGTYPE server_interrupt PROTO1(int, signum);
|
||||||
|
RETSIGTYPE server_dump PROTO1(int, signum);
|
||||||
|
int server_loop PROTO2(int,fd,time_t,timeout);
|
||||||
|
int server_reply PROTO0((struct sockaddr_in *, UBUF *, unsigned int, unsigned int));
|
||||||
|
void send_file PROTO0((struct sockaddr_in *, UBUF *, FILE *, unsigned int,
|
||||||
|
char *));
|
||||||
|
|
||||||
|
/* acl.c, security code */
|
||||||
|
void load_access_rights PROTO1(DIRINFO *,di);
|
||||||
|
void save_access_rights PROTO1(DIRINFO *,di);
|
||||||
|
const char * require_access_rights PROTO4(const DIRINFO *,di,unsigned char,rights,unsigned long, ip_addr, const char *, passwd);
|
||||||
|
|
||||||
|
/* main.c, startup and init code */
|
||||||
|
|
||||||
|
/* log.c */
|
||||||
|
extern int logfd;
|
||||||
|
void fsplogf PROTO0((void));
|
||||||
|
void fsplogs PROTO0((void));
|
||||||
|
#ifdef __STDC__
|
||||||
|
void fsploga(const char *fmt, ...);
|
||||||
|
#else
|
||||||
|
void fsploga(va_alist);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FSP_S_EXTERN_H_ */
|
||||||
218
server/acl.c
Normal file
218
server/acl.c
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
/*********************************************************************\
|
||||||
|
* Copyright (c) 2003 by Radim Kolar (hsn@cybermail.net) *
|
||||||
|
* *
|
||||||
|
* You may copy or modify this file in any manner you wish, provided *
|
||||||
|
* that this notice is always included, and that you hold the author *
|
||||||
|
* harmless for any loss or damage resulting from the installation or *
|
||||||
|
* use of this software. *
|
||||||
|
\*********************************************************************/
|
||||||
|
|
||||||
|
#include "tweak.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "server_def.h"
|
||||||
|
#include "s_extern.h"
|
||||||
|
#include "my-string.h"
|
||||||
|
|
||||||
|
/* loads a password from file in current directory */
|
||||||
|
static char *load_password PROTO1(const char *, file)
|
||||||
|
{
|
||||||
|
/* load password */
|
||||||
|
FILE *f;
|
||||||
|
char fsp_passwd[80];
|
||||||
|
|
||||||
|
f=fopen(file,"r");
|
||||||
|
if(f) {
|
||||||
|
if(fscanf(f, "%79s", fsp_passwd) != 1) {
|
||||||
|
if(dbug) printf("load_pass: no password found in file\n");
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
fclose(f);
|
||||||
|
return strdup(fsp_passwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save a password to file in current directory */
|
||||||
|
static void save_password PROTO2(const char *,file,const char *,password)
|
||||||
|
{
|
||||||
|
/* load password */
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f=fopen(file,"w");
|
||||||
|
if(f) {
|
||||||
|
fprintf(f,"%s\n",password);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save access rights to filesystem */
|
||||||
|
void save_access_rights PROTO1(DIRINFO *,di)
|
||||||
|
{
|
||||||
|
/* step 1 - unlink everything */
|
||||||
|
unlink(FSP_NOGET);
|
||||||
|
unlink(FSP_DEL);
|
||||||
|
unlink(FSP_ADD);
|
||||||
|
unlink(FSP_MKDIR);
|
||||||
|
unlink(FSP_RENAME);
|
||||||
|
unlink(FSP_NOLIST);
|
||||||
|
unlink(FSP_PASSWORD);
|
||||||
|
unlink(FSP_OWNER);
|
||||||
|
unlink(FSP_OWNERPASSWORD);
|
||||||
|
unlink(FSP_DIRLISTING);
|
||||||
|
|
||||||
|
if(!use_access_files) return;
|
||||||
|
|
||||||
|
/* step2 save flagfiles */
|
||||||
|
if(! (di->protection & DIR_GET) ) touch(FSP_NOGET);
|
||||||
|
if(di->protection & DIR_DEL) touch(FSP_DEL);
|
||||||
|
if(di->protection & DIR_ADD) touch(FSP_ADD);
|
||||||
|
if(di->protection & DIR_MKDIR) touch(FSP_MKDIR);
|
||||||
|
if(di->protection & DIR_RENAME) touch(FSP_RENAME);
|
||||||
|
if(!di->protection& DIR_LIST) touch(FSP_NOLIST);
|
||||||
|
|
||||||
|
/* step3 pazzwordz */
|
||||||
|
if(di->public_password) save_password(FSP_PASSWORD,di->public_password);
|
||||||
|
if(di->owner_password) save_password(FSP_OWNERPASSWORD,di->owner_password);
|
||||||
|
|
||||||
|
/* save Owner ACL */
|
||||||
|
if(di->owner)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
f=fopen(FSP_OWNER,"w");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
dump_iptab(di->owner,f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called with current directory == tested directory */
|
||||||
|
/* load access rights for validated directory */
|
||||||
|
void load_access_rights PROTO1(DIRINFO *,di)
|
||||||
|
{
|
||||||
|
struct stat sf;
|
||||||
|
FILE *f;
|
||||||
|
char owner_line[256];
|
||||||
|
|
||||||
|
di->owner=NULL;
|
||||||
|
di->owner_password=NULL;
|
||||||
|
di->public_password=NULL;
|
||||||
|
di->protection=DIR_LIST|DIR_GET;
|
||||||
|
di->readme=NULL;
|
||||||
|
|
||||||
|
/* load directory readme file */
|
||||||
|
if(!FSP_STAT(readme_file,&sf))
|
||||||
|
{
|
||||||
|
f=fopen(readme_file,"r");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
unsigned int s;
|
||||||
|
/* max readme file size is
|
||||||
|
* packetsize - pro_bytes (now 1) - 1 (for /0)
|
||||||
|
*/
|
||||||
|
s=min(packetsize-PRO_BYTES-1,sf.st_size);
|
||||||
|
di->readme=malloc(s+1);
|
||||||
|
if(di->readme)
|
||||||
|
{
|
||||||
|
fread(di->readme,s,1,f);
|
||||||
|
di->protection|=DIR_README;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!use_access_files) return;
|
||||||
|
|
||||||
|
/* LOAD ACCESS RIGHTS FROM FILES IN CURRENT DIRECTORY */
|
||||||
|
if(fexist(FSP_NOGET)) di->protection^=DIR_GET;
|
||||||
|
if(fexist(FSP_DEL)) di->protection|=DIR_DEL;
|
||||||
|
if(fexist(FSP_ADD)) di->protection|=DIR_ADD;
|
||||||
|
if(fexist(FSP_MKDIR)) di->protection|=DIR_MKDIR;
|
||||||
|
if(fexist(FSP_RENAME)) di->protection|=DIR_RENAME;
|
||||||
|
if(fexist(FSP_NOLIST)) di->protection^=DIR_LIST;
|
||||||
|
if(!FSP_STAT(FSP_PASSWORD,&sf))
|
||||||
|
if(sf.st_size>0)
|
||||||
|
di->public_password=load_password(FSP_PASSWORD);
|
||||||
|
|
||||||
|
/* load owner info */
|
||||||
|
f=fopen(FSP_OWNER,"r");
|
||||||
|
if(!f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while(fscanf(f, "%255[^\n\r]", owner_line) == 1)
|
||||||
|
{
|
||||||
|
add_ipline(owner_line,&di->owner);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
/* .. and password */
|
||||||
|
if(!FSP_STAT(FSP_OWNERPASSWORD,&sf))
|
||||||
|
{
|
||||||
|
if(sf.st_size>0)
|
||||||
|
di->owner_password=load_password(FSP_OWNERPASSWORD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does caller has enough security rights? */
|
||||||
|
/* if rights has DIR_PRIV set than caller is restristed and need also
|
||||||
|
* at least 'N' record to get it, if he has DIR_README, we will send him
|
||||||
|
* a datagram with error reply */
|
||||||
|
|
||||||
|
const char * require_access_rights PROTO4(const DIRINFO *,di,unsigned char,rights,unsigned long, ip_addr, const char *, passwd)
|
||||||
|
{
|
||||||
|
const char *acc=NULL;
|
||||||
|
|
||||||
|
/* check if we has record in an owner tabl. */
|
||||||
|
if(di->owner)
|
||||||
|
{
|
||||||
|
/* check ip access */
|
||||||
|
acc=check_ip_table(ip_addr,di->owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(acc!=NULL)
|
||||||
|
{
|
||||||
|
if(acc[0]=='I' || acc[0]=='D')
|
||||||
|
/* bazmeg IP! */
|
||||||
|
return acc;
|
||||||
|
if(acc[0]=='O') /* possible owner */
|
||||||
|
{
|
||||||
|
if(di->owner_password==NULL)
|
||||||
|
{
|
||||||
|
if(permit_passwordless_owners)
|
||||||
|
return acc; /* passwordless owner */
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* do we have a password? */
|
||||||
|
if(passwd)
|
||||||
|
{
|
||||||
|
/* compare passwords */
|
||||||
|
if(!strcmp(passwd,di->owner_password))
|
||||||
|
return acc; /* owner with good password */
|
||||||
|
} else
|
||||||
|
if(rights & DIR_OWNER)
|
||||||
|
return "DPassword required for owner";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rights & DIR_OWNER)
|
||||||
|
return "DNot an owner";
|
||||||
|
/* is password needed for public access? */
|
||||||
|
if(di->public_password)
|
||||||
|
{
|
||||||
|
if(passwd==NULL)
|
||||||
|
return "DYou need a password";
|
||||||
|
else
|
||||||
|
if(strcmp(di->public_password,passwd))
|
||||||
|
return "DInvalid password";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now check public access rights */
|
||||||
|
if( (rights & di->protection) ||
|
||||||
|
(rights==0)
|
||||||
|
)
|
||||||
|
return "NWelcome on board captain!";
|
||||||
|
else
|
||||||
|
return "DPermission denied";
|
||||||
|
}
|
||||||
258
server/fifocache.c
Normal file
258
server/fifocache.c
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
* Simple FIFO generic cache. (c) Radim Kolar 2003.
|
||||||
|
* This file is copyrighted as LGPL.
|
||||||
|
*
|
||||||
|
* When this file is used as part of FSP, it uses 2-term BSD license
|
||||||
|
* (aka MIT/X11 License).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tweak.h"
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "fifocache.h"
|
||||||
|
|
||||||
|
/* allocates a memory for new cache stucture and init it */
|
||||||
|
struct FifoCache * f_cache_new(unsigned int cachesize,unsigned int entrysize,
|
||||||
|
void (*edf) (void *),unsigned int keysize, void (*kdf) (void *), int (*kcf)(const void *,const void *))
|
||||||
|
{
|
||||||
|
struct FifoCache *cache;
|
||||||
|
if(cachesize==0) return NULL;
|
||||||
|
if(entrysize==0 && keysize==0) return NULL;
|
||||||
|
cache=calloc(1,sizeof(struct FifoCache));
|
||||||
|
if(cache==NULL) return NULL;
|
||||||
|
|
||||||
|
cache->cachesize=cachesize;
|
||||||
|
cache->keysize=keysize;
|
||||||
|
cache->entrysize=entrysize;
|
||||||
|
|
||||||
|
if(entrysize==0)
|
||||||
|
cache->e_head=calloc(1,1);
|
||||||
|
else
|
||||||
|
cache->e_head=calloc(cachesize,entrysize);
|
||||||
|
|
||||||
|
if(keysize==0)
|
||||||
|
cache->k_head=calloc(1,1);
|
||||||
|
else
|
||||||
|
cache->k_head=calloc(cachesize,keysize);
|
||||||
|
|
||||||
|
if(!cache->e_head || !cache->k_head)
|
||||||
|
{
|
||||||
|
f_cache_destroy(cache);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
cache->k_next=cache->k_head;
|
||||||
|
|
||||||
|
if(keysize==0)
|
||||||
|
cache->k_stop=NULL;
|
||||||
|
else
|
||||||
|
cache->k_stop=cache->k_head+cache->keysize*cache->cachesize;
|
||||||
|
|
||||||
|
cache->e_next=cache->e_head;
|
||||||
|
if(entrysize==0)
|
||||||
|
cache->e_stop=NULL;
|
||||||
|
else
|
||||||
|
cache->e_stop=cache->e_head+cache->entrysize*cache->cachesize;
|
||||||
|
|
||||||
|
cache->k_destroy_func=kdf;
|
||||||
|
cache->e_destroy_func=edf;
|
||||||
|
cache->k_compare_func=kcf;
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
/* set memory profile functions */
|
||||||
|
void f_cache_set_memory_profilers(struct FifoCache *cache,unsigned int (*keysize) (void *key),unsigned int (*entrysize) (void *entry))
|
||||||
|
{
|
||||||
|
cache->get_keysize=keysize;
|
||||||
|
cache->get_entrysize=entrysize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f_cache_stats(struct FifoCache *cache,FILE *f)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int used=0;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int dkey=0;
|
||||||
|
unsigned int dentry=0;
|
||||||
|
|
||||||
|
if(f==NULL) return;
|
||||||
|
/* count used items */
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
{
|
||||||
|
if(cache->keysize>0)
|
||||||
|
{
|
||||||
|
for(j=0;j<cache->keysize;j++)
|
||||||
|
{
|
||||||
|
if( *(cache->k_head+i*cache->keysize+j) != 0)
|
||||||
|
{
|
||||||
|
used++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* calculate dynamic memory used */
|
||||||
|
if(cache->get_keysize)
|
||||||
|
{
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
{
|
||||||
|
dkey+=cache->get_keysize(cache->k_head+i*cache->keysize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cache->get_entrysize)
|
||||||
|
{
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
{
|
||||||
|
dentry+=cache->get_entrysize(cache->e_head+i*cache->entrysize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(f,"%u entries (%u used). Memory: %u hdr, keys %u static + %u dynamic, entries %u static + %u dynamic. Hit ratio: %u hit, %u miss.\n",
|
||||||
|
cache->cachesize,used,sizeof(struct FifoCache), cache->cachesize*cache->keysize,dkey,cache->cachesize*cache->entrysize,dentry,cache->hit,cache->miss);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int f_cache_void_profiler(void *anything)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* destroys cache without deallocationg of elements itself */
|
||||||
|
void f_cache_destroy(struct FifoCache *cache)
|
||||||
|
{
|
||||||
|
if(cache==NULL) return;
|
||||||
|
if(cache->e_head)
|
||||||
|
{
|
||||||
|
memset(cache->e_head,0,cache->entrysize*cache->cachesize);
|
||||||
|
free(cache->e_head);
|
||||||
|
}
|
||||||
|
if(cache->k_head) {
|
||||||
|
memset(cache->k_head,0,cache->keysize*cache->cachesize);
|
||||||
|
free(cache->k_head);
|
||||||
|
}
|
||||||
|
cache->e_head=NULL;
|
||||||
|
cache->k_head=NULL;
|
||||||
|
free(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy record into cache, free existing record */
|
||||||
|
/* returns pointer to data entry in cache */
|
||||||
|
void * f_cache_put(struct FifoCache *cache,const void *key,const void *data)
|
||||||
|
{
|
||||||
|
void *where;
|
||||||
|
/* free place for new element */
|
||||||
|
if(cache->k_destroy_func) cache->k_destroy_func(cache->k_next);
|
||||||
|
if(cache->e_destroy_func) cache->e_destroy_func(cache->e_next);
|
||||||
|
|
||||||
|
/* copy new element in */
|
||||||
|
where=cache->e_next;
|
||||||
|
memcpy(cache->k_next,key,cache->keysize);
|
||||||
|
memcpy(cache->e_next,data,cache->entrysize);
|
||||||
|
|
||||||
|
/* update next pos. */
|
||||||
|
cache->e_next+=cache->entrysize;
|
||||||
|
cache->k_next+=cache->keysize;
|
||||||
|
|
||||||
|
/* roll over? */
|
||||||
|
if(cache->e_next==cache->e_stop || cache->k_next==cache->k_stop)
|
||||||
|
{
|
||||||
|
cache->e_next=cache->e_head;
|
||||||
|
cache->k_next=cache->k_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
return where;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find element by key */
|
||||||
|
void *f_cache_find(struct FifoCache *cache,const void *key)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!cache->k_compare_func) return NULL;
|
||||||
|
if(cache->keysize==0) return NULL;
|
||||||
|
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
if(!cache->k_compare_func(key,cache->k_head+i*cache->keysize))
|
||||||
|
{
|
||||||
|
cache->hit++;
|
||||||
|
return cache->e_head+i*cache->entrysize;
|
||||||
|
}
|
||||||
|
cache->miss++;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear all elements from the cache */
|
||||||
|
void f_cache_clear(struct FifoCache *cache)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* free entries */
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
{
|
||||||
|
if(cache->k_destroy_func)
|
||||||
|
cache->k_destroy_func(cache->k_head+i*cache->keysize);
|
||||||
|
if(cache->e_destroy_func)
|
||||||
|
cache->e_destroy_func(cache->e_head+i*cache->entrysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear entries */
|
||||||
|
memset(cache->k_head,0,cache->cachesize*cache->keysize);
|
||||||
|
memset(cache->e_head,0,cache->cachesize*cache->entrysize);
|
||||||
|
|
||||||
|
cache->k_next=cache->k_head;
|
||||||
|
cache->e_next=cache->e_head;
|
||||||
|
|
||||||
|
cache->hit=0;
|
||||||
|
cache->miss=0;
|
||||||
|
}
|
||||||
|
/* find key for given entry */
|
||||||
|
void * f_cache_get_key(struct FifoCache *cache,const void *entry)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
if(cache->entrysize==0 || cache->keysize==0) return NULL;
|
||||||
|
|
||||||
|
/* check if pointer is good */
|
||||||
|
if(entry<(const void *)cache->e_head || entry>=(const void *)cache->e_stop) return NULL;
|
||||||
|
/* find cache index */
|
||||||
|
i=((const BYTE *)(entry)-cache->e_head)/cache->entrysize;
|
||||||
|
return cache->k_head+cache->keysize*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* delete entry from cache, returns one if object is deleted */
|
||||||
|
int f_cache_delete_entry(struct FifoCache *cache, void *entry)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(cache->entrysize==0) return 0;
|
||||||
|
/* check if pointer is good */
|
||||||
|
if(entry<(const void *)cache->e_head || entry>=(const void *)cache->e_stop) return 0;
|
||||||
|
/* find cache index */
|
||||||
|
i=((BYTE *)(entry)-cache->e_head)/cache->entrysize;
|
||||||
|
|
||||||
|
/* deallocate */
|
||||||
|
if(cache->k_destroy_func) cache->k_destroy_func(cache->k_head+cache->keysize*i);
|
||||||
|
if(cache->e_destroy_func) cache->e_destroy_func(entry);
|
||||||
|
/* zero them */
|
||||||
|
memset(entry,0,cache->entrysize);
|
||||||
|
memset(cache->k_head+cache->keysize*i,0,cache->keysize);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns how many objects was deleted */
|
||||||
|
int f_cache_delete_by_key(struct FifoCache *cache, void *key)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int deleted=0;
|
||||||
|
|
||||||
|
if(!cache->k_compare_func) return 0;
|
||||||
|
|
||||||
|
for(i=0;i<cache->cachesize;i++)
|
||||||
|
{
|
||||||
|
if(!cache->k_compare_func(key,cache->k_head+i*cache->keysize))
|
||||||
|
{
|
||||||
|
deleted+=f_cache_delete_entry(cache,cache->e_head+i*cache->entrysize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
309
server/iprange.c
Normal file
309
server/iprange.c
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*********************************************************************\
|
||||||
|
* Copyright (c) 2003 by Radim Kolar (hsn@cybermail.net) *
|
||||||
|
* Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu) *
|
||||||
|
* *
|
||||||
|
* You may copy or modify this file in any manner you wish, provided *
|
||||||
|
* that this notice is always included, and that you hold the author *
|
||||||
|
* harmless for any loss or damage resulting from the installation or *
|
||||||
|
* use of this software. *
|
||||||
|
\*********************************************************************/
|
||||||
|
|
||||||
|
#include "tweak.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include "server_def.h"
|
||||||
|
#include "s_extern.h"
|
||||||
|
#include "my-string.h"
|
||||||
|
|
||||||
|
/* Function for IPrange structure */
|
||||||
|
|
||||||
|
IPrange *iptab=NULL;
|
||||||
|
|
||||||
|
#define skip_whitespace(x) do {while (*(x)&&isspace(*(x))) (x)++;} while (0)
|
||||||
|
|
||||||
|
/* check if inet_number matches entry in IPrange table */
|
||||||
|
/* return pointer to specified message */
|
||||||
|
|
||||||
|
static char *check_ip PROTO2(unsigned long, inet_num, const IPrange *, iprange)
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned char val[4];
|
||||||
|
|
||||||
|
inet_num = ntohl(inet_num);
|
||||||
|
|
||||||
|
val[0] = (inet_num & 0x000000ff) ;
|
||||||
|
val[1] = (inet_num & 0x0000ff00) >> 8;
|
||||||
|
val[2] = (inet_num & 0x00ff0000) >> 16;
|
||||||
|
val[3] = (inet_num & 0xff000000) >> 24;
|
||||||
|
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
if (iprange->lo[j] > val[j] || val[j] > iprange->hi[j]) return NULL;
|
||||||
|
|
||||||
|
return iprange->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *check_ip_table PROTO2(unsigned long, inet_num,IPrange *,table)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
while(table)
|
||||||
|
{
|
||||||
|
if(!table->text) return NULL; /* EOT! */
|
||||||
|
res=check_ip(inet_num,table);
|
||||||
|
if(res) return res;
|
||||||
|
table++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_ip_table PROTO1(IPrange *,table)
|
||||||
|
{
|
||||||
|
IPrange *head=table;
|
||||||
|
/* free strings */
|
||||||
|
while(table++)
|
||||||
|
{
|
||||||
|
if(!table->text) break;
|
||||||
|
free(table->text);
|
||||||
|
}
|
||||||
|
free(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IP parsing fun */
|
||||||
|
/* parse the text string as an integer and return a value between 0x00 and 0xff
|
||||||
|
if there is any error in forming the value (e.g., the text string
|
||||||
|
isn't an integer, or the integer value is too large) then make the
|
||||||
|
text string NULL */
|
||||||
|
static unsigned char parse_ipcomponentnum PROTO1(const char * *, textp)
|
||||||
|
{
|
||||||
|
unsigned long val = 0;
|
||||||
|
|
||||||
|
if (!isdigit(**textp)) {
|
||||||
|
*textp = 0;
|
||||||
|
} else
|
||||||
|
do {
|
||||||
|
val = 10 * val + (**textp - '0');
|
||||||
|
(*textp)++;
|
||||||
|
} while (isdigit(**textp));
|
||||||
|
|
||||||
|
if (val > 0xff) {
|
||||||
|
val = 0;
|
||||||
|
*textp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a whole field of a numerical IP address; it can be one of:
|
||||||
|
integer >> fixed value
|
||||||
|
integer '-' integer >> range of values
|
||||||
|
'*' >> same as 0-255
|
||||||
|
*/
|
||||||
|
static const char *parse_ipcomponent PROTO3(const char *, text, unsigned char *, lo,
|
||||||
|
unsigned char *, hi)
|
||||||
|
{
|
||||||
|
if (*text == '*') {
|
||||||
|
*lo = 0x00;
|
||||||
|
*hi = 0xff;
|
||||||
|
return (text + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
*lo = parse_ipcomponentnum(&text);
|
||||||
|
if (!text) return 0;
|
||||||
|
|
||||||
|
if (*text == '-') {
|
||||||
|
text++;
|
||||||
|
*hi = parse_ipcomponentnum(&text);
|
||||||
|
} else *hi = *lo;
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPrange *parse_ipnumber PROTO1(const char *, text)
|
||||||
|
{
|
||||||
|
IPrange *reply;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
reply = (IPrange *)malloc(sizeof(IPrange));
|
||||||
|
|
||||||
|
for (i = 3; i >= 0 && !isspace(*text); i--) {
|
||||||
|
if (i < 3) {
|
||||||
|
if (*text != '.') return 0;
|
||||||
|
else text++;
|
||||||
|
}
|
||||||
|
text = parse_ipcomponent(text, &reply->lo[i], &reply->hi[i]);
|
||||||
|
if (!text) {
|
||||||
|
free((char *)reply);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill in the gaps in the case that the loop terminated due to
|
||||||
|
the occurrence of white-space */
|
||||||
|
for (; i >= 0; i--) {
|
||||||
|
reply->lo[i] = 0x00;
|
||||||
|
reply->hi[i] = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPrange *parse_hostname PROTO2(const char *, text, unsigned int, len)
|
||||||
|
{
|
||||||
|
IPrange *reply;
|
||||||
|
struct hostent *hostaddr;
|
||||||
|
unsigned long inet_num;
|
||||||
|
char *hostname;
|
||||||
|
|
||||||
|
hostname = malloc(len + 1);
|
||||||
|
strncpy(hostname, text, len);
|
||||||
|
hostname[len] = 0;
|
||||||
|
|
||||||
|
hostaddr = gethostbyname(hostname);
|
||||||
|
free(hostname);
|
||||||
|
|
||||||
|
if (!hostaddr) return 0;
|
||||||
|
|
||||||
|
reply = (IPrange *)malloc(sizeof(IPrange));
|
||||||
|
inet_num = ((struct in_addr *)(hostaddr->h_addr))->s_addr;
|
||||||
|
reply->lo[0] = reply->hi[0] = (inet_num & 0x000000ff) ;
|
||||||
|
reply->lo[1] = reply->hi[1] = (inet_num & 0x0000ff00) >> 8;
|
||||||
|
reply->lo[2] = reply->hi[2] = (inet_num & 0x00ff0000) >> 16;
|
||||||
|
reply->lo[3] = reply->hi[3] = (inet_num & 0xff000000) >> 24;
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse a single line for the IP hosts file */
|
||||||
|
/* returns IPrange structure,first letter in message is type */
|
||||||
|
|
||||||
|
/*
|
||||||
|
# syntax of ipline is: host_mask host_type [message]
|
||||||
|
# host_type is one of D, I, or N :
|
||||||
|
# I hosts are ignored
|
||||||
|
# N hosts are treated as normal
|
||||||
|
# D hosts will receive the error string message given as the third parameter
|
||||||
|
# 128.4-8.*.* -- (* acts as the range 0 - 255)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static IPrange *parse_ipline PROTO1(const char *, text)
|
||||||
|
{
|
||||||
|
IPrange *reply;
|
||||||
|
char type = 0;
|
||||||
|
const char *message = 0;
|
||||||
|
size_t messlen = 0, addresslen;
|
||||||
|
|
||||||
|
/* skip the leading white-space */
|
||||||
|
skip_whitespace(text);
|
||||||
|
/* if the line is commented or empty, ignore it */
|
||||||
|
if (!*text || *text == '#') return 0;
|
||||||
|
|
||||||
|
/* load hostname range (can not have spaces inside) */
|
||||||
|
message = text;
|
||||||
|
while (*message && !isspace(*message)) message++;
|
||||||
|
addresslen = message - text;
|
||||||
|
|
||||||
|
/* find the first non-space character after the address - this
|
||||||
|
identifies the type of host this is */
|
||||||
|
skip_whitespace(message);
|
||||||
|
|
||||||
|
if (!*message || *message == '#') {
|
||||||
|
fprintf(stderr, "No host type specified in config file:\n\t%s\n", text);
|
||||||
|
/* if a host name is mentioned by itself, then treat it as ignored
|
||||||
|
or normal depending on the value of priv_mode */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the first character after the host name is the type of host */
|
||||||
|
type = *message;
|
||||||
|
|
||||||
|
/* skip over the white space trailing the type - the start of the
|
||||||
|
associated message */
|
||||||
|
message++; /* remember skip_whitespace() is a macro... */
|
||||||
|
skip_whitespace(message);
|
||||||
|
|
||||||
|
/* `remove' the trailing white-space from the message */
|
||||||
|
messlen = strlen(message);
|
||||||
|
while (messlen > 0 && isspace(message[messlen-1])) messlen--;
|
||||||
|
|
||||||
|
/* if the first character of the address is numerical or '*' then parse
|
||||||
|
as a numerical address, otherwise we do a host lookup on the name. */
|
||||||
|
if (*text == '*' || isdigit(*text))
|
||||||
|
reply = parse_ipnumber(text);
|
||||||
|
else
|
||||||
|
reply = parse_hostname(text, addresslen);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
fprintf(stderr, "Badly formed address in config file:\n\t%s\n", text);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a string to hold the message */
|
||||||
|
reply->text = malloc(1 + messlen + 1); /* type + text + '\0' */
|
||||||
|
if(!reply->text)
|
||||||
|
{
|
||||||
|
free(reply);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
reply->text[0] = type;
|
||||||
|
strncpy(&reply->text[1], message, messlen);
|
||||||
|
reply->text[1 + messlen] = '\0';
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void add_ipline PROTO2(const char *, text, IPrange **, table)
|
||||||
|
{
|
||||||
|
IPrange *nl;
|
||||||
|
IPrange *newtab;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
nl = parse_ipline(text);
|
||||||
|
if(!nl) return;
|
||||||
|
/* add a new record to table */
|
||||||
|
if(*table==NULL)
|
||||||
|
{
|
||||||
|
*table=malloc(sizeof(IPrange)*2);
|
||||||
|
if(!*table) return;
|
||||||
|
memcpy(*table,nl,sizeof(IPrange));
|
||||||
|
free(nl);
|
||||||
|
((*table)+1)->text=NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* count records in IPrange table */
|
||||||
|
i=0;
|
||||||
|
while( ((*table)+i++)->text!=NULL);
|
||||||
|
newtab=realloc(table,sizeof (IPrange) * (i+1));
|
||||||
|
if(!newtab) return;
|
||||||
|
*table=newtab;
|
||||||
|
memcpy( (*table)+i,nl,sizeof(IPrange));
|
||||||
|
free(nl);
|
||||||
|
((*table)+i+1)->text=NULL;
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
* Write out the IP table in the .IPTAB_DUMP file.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void dump_iptab PROTO2(IPrange *,table,FILE *, fp)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(fp==NULL)
|
||||||
|
{
|
||||||
|
if(dbug)
|
||||||
|
fp=stdout;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(table) {
|
||||||
|
if(!table->text) break;
|
||||||
|
fprintf(fp, "%d-%d.%d-%d.%d-%d.%d-%d %c %s\n",
|
||||||
|
table->lo[3], table->hi[3],
|
||||||
|
table->lo[2], table->hi[2],
|
||||||
|
table->lo[1], table->hi[1],
|
||||||
|
table->lo[0], table->hi[0],
|
||||||
|
table->text[0],&table->text[1]);
|
||||||
|
table++;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user