From 2a963be06d04cd7d93452101a0f018568d2a7092 Mon Sep 17 00:00:00 2001 From: hsn <> Date: Sat, 4 Oct 2003 12:56:32 +0000 Subject: [PATCH] Initial revision --- include/s_extern.h | 89 +++++++++++++ server/acl.c | 218 ++++++++++++++++++++++++++++++++ server/fifocache.c | 258 +++++++++++++++++++++++++++++++++++++ server/iprange.c | 309 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 874 insertions(+) create mode 100644 include/s_extern.h create mode 100644 server/acl.c create mode 100644 server/fifocache.c create mode 100644 server/iprange.c diff --git a/include/s_extern.h b/include/s_extern.h new file mode 100644 index 0000000..e01b0db --- /dev/null +++ b/include/s_extern.h @@ -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_ */ diff --git a/server/acl.c b/server/acl.c new file mode 100644 index 0000000..ea25c64 --- /dev/null +++ b/server/acl.c @@ -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 +#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"; +} diff --git a/server/fifocache.c b/server/fifocache.c new file mode 100644 index 0000000..9c9e151 --- /dev/null +++ b/server/fifocache.c @@ -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 +#include +#include +#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;icachesize;i++) + { + if(cache->keysize>0) + { + for(j=0;jkeysize;j++) + { + if( *(cache->k_head+i*cache->keysize+j) != 0) + { + used++; + break; + } + } + } + } + + /* calculate dynamic memory used */ + if(cache->get_keysize) + { + for(i=0;icachesize;i++) + { + dkey+=cache->get_keysize(cache->k_head+i*cache->keysize); + } + } + if(cache->get_entrysize) + { + for(i=0;icachesize;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;icachesize;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;icachesize;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;icachesize;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; +} diff --git a/server/iprange.c b/server/iprange.c new file mode 100644 index 0000000..7005ccc --- /dev/null +++ b/server/iprange.c @@ -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 +#include +#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++; + } +}