⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radwatch.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 2 页
字号:
 * as restricted time for this user, count that time in... */static void update_user_time(radlast rl){    USER_TIME *ut;    int t;    t = strlen(rl.login);    if (!t || (t > USERNAME_MAX))	return; /* avoid invalid data */    ut = user_time_head;    while (ut != NULL) {        if (strcmp(ut->username, rl.login) == 0) {	    /* found on list */	    struct period u_time;	    u_time.start = rl.ut_time - rl.length;	    u_time.end = rl.ut_time;	    /* add this to this user ... */	    ut->counted += common_time(ut->period, u_time);	}	ut = ut->next;    }    return;}/*  * get_user_time * returns the used time by the user withing a certain frame period  */static int parse_radacct_file(void){    int fd;    char filename[PATH_MAX];    radlast rad_last;	     memset(filename, 0, sizeof(filename));    if (!monthly_detail)	sprintf(filename, "%s/%s", rad_acctdir, RADIUS_LAST);    else {	time_t crt_time;	struct tm *time_info;		crt_time = time(NULL);	time_info = localtime(&crt_time);	sprintf(filename, "%s/%d/%s-%02d", rad_acctdir, 	        1900+time_info->tm_year, RADIUS_LAST,		time_info->tm_mon + 1);    }    fd = open(filename, O_RDONLY);    if (fd < 0)	return -1;    if (debug_flag) {	printf("Parsing radlast (%s) file: ", filename);	fflush(stdout);    }    memset(&rad_last, 0, sizeof(radlast));       /* okay, start reading the radlast log file */    while(read(fd, &rad_last, sizeof(radlast)) == sizeof(radlast)) {	update_user_time(rad_last);	memset(&rad_last, 0, sizeof(rad_last));    }    /* done reading radlast logging info */    close(fd);    if (debug_flag) {	printf("OK.\n");	fflush(stdout);    }    return 0;}/* * Print a short (and hopefully clear) usage screen.  */static void radwatch_usage(void){    printf("\n%s version %s\n", progname, REVISION);    printf("Usage: %s <option>\nValid options are:\n", progname);    printf("\t-a\t\taccounting dir for radiusd\n");    printf("\t-d\t\tconfiguration dir for radiusd\n");    printf("\t-h\t\toutput this help screen\n");    printf("\t-m\t\tuse the monthly status files created by radiusd\n");    printf("\t-x\t\tenable debugging\n");    printf("\nNOTE: all these flags should match the flags currently in use\n");    printf("        by radiusd daemon.\n");}/* * Open the radlist database for the current month. The algorithm will * fail at the end of the month, but this will be fixed in a future * release (if the period wraps around midnight - end < start - we * won't be able to read the last month statistics. Hopefully no one * will be hurt so bad at this stage....  */static GDBM_FILE open_radlist(void){    GDBM_FILE dbf;    char db_name[PATH_MAX];    int month;    time_t crt_time;    struct tm *time_info;    crt_time = time(NULL);    time_info = localtime(&crt_time);    month = time_info->tm_mon + 1;    sprintf(db_name, "%s/%d/%s",            rad_acctdir, 1900+time_info->tm_year,RADIUS_USER_STATS);    if (debug_flag)        printf("Using database file %s ...\n", db_name);    dbf = gdbm_open(db_name,0,GDBM_READER, 0600,NULL);    if (dbf == NULL)	fprintf(stderr, "Error opening the radlist (%s) database.\n",db_name);    return dbf;}/*  * Well, this programs accepts arguments and flags...  * Isn't it cool ? :-)  */static void parse_args(int argc, char **argv){    int flag;    while ((flag = getopt(argc, argv, "ma:d:xh")) != EOF) {        switch (flag) {            case 'm':                monthly_detail++;                break;            case 'a':                rad_acctdir = optarg;                break;            case 'd':                radius_dir = optarg;                break;	    case 'h':		radwatch_usage();                exit(0);            case 'x':                debug_flag++;                break;            default:                radwatch_usage();                exit(-1);        }    }    return;}/* * check the timerestriction for a certain user  * * return: *   0 = okay * < 0 = time exceeded  */static void insert_user_in_list(char *username, struct time_frame *tf, time_t when, int max_seconds, user_entry *ue, int ue_size){    int usr_time = 0;    struct period period;    int present_entries;    int i;    if (!username || !strlen(username))	return;    /* build the start time and the end time for the frame period */    get_period(&period, tf, when);    /* if this use is logged in ... */    present_entries = (ue_size - sizeof(user_entry))/sizeof(port_entry);    /* be safe */    present_entries = min(present_entries, (unsigned int)ue->logins);    for (i=0; i < present_entries; i++) {	port_entry *pe_tmp;	struct period u_time;		pe_tmp = (port_entry *)((char *)ue + sizeof(user_entry)) + i;	u_time.start = pe_tmp->time;	u_time.end = when;	if (u_time.end < u_time.start)	    /* non-sense - claculating for the past... */	    continue;	usr_time += common_time(period, u_time);    }    add_user_time_list(username, period, max_seconds, usr_time);}/*  * Opens the radius stop list file, in the mode supplied by argument. * Returns the result of the call to fopen */static FILE *open_radstop_file(const char * mode){    FILE *fp;    char filename[PATH_MAX];    sprintf(filename, "%s/%s", radius_dir, RADIUS_STOP);    fp = fopen(filename, mode);    return fp;}/* * Returns true if the account is locked.  * used by the lock_accounts function.  */static int is_locked(char *user){    FILE *fp;    char buffer[1024];    fp = open_radstop_file("r");    if (fp == NULL) {	/* file not found, account is no locked */	return 0;    }    while (fgets(buffer, sizeof(buffer), fp) != NULL) {	if (strlen(buffer) == 0)	    continue;	buffer[strlen(buffer)-1] = '\0';	if (strcmp(user, buffer) == 0) {	    fclose(fp);	    return 1;	}    }    return 0; /* default: not locked */}/*  * This function adds the supplied user at the end of the radius stop file * No checking for the previous existence in that file is done since this * test is supposed to be already done somewhere else */static void lock_account(char *user){    FILE *fp;    fp = open_radstop_file("a");    if (fp == NULL) {	/* very odd error */	fprintf(stderr, "Could not open/creat the radius stop list file !\n");	exit(-3);    }    fprintf(fp, "%s\n", user);    fclose(fp);}/* * Iterate through the user list and check for over-quota accounts. If it * is not already locked, lock the account. */static void lock_accounts(void){    USER_TIME *ut;        ut = user_time_head;    while (ut != NULL) {	if (ut->restriction > ut->counted) {	    ut = ut->next;	    continue;	}	printf("%s\n", ut->username);	/* this account needs to be locked out */	if (is_locked(ut->username)) {	    ut = ut->next;	    continue;	}	lock_account(ut->username);	ut = ut->next;    }}/*  * Given an user, walks through the user_time list and see if this * user is over quota.  */static int over_quota(char *user){    USER_TIME *ut;    ut = user_time_head;    while (ut != NULL) {	if (strncmp(ut->username, user, USERNAME_MAX) == 0)	    /* our account */	    if (ut->restriction < ut->counted)		return 1;	ut = ut->next;    }    return 0;}/*  * Verify each account listed in radiusd stop list to see if it * still match the restriction time criteria. If it does NOT, then * this user should not be black-listed anymore... */static void unlock_accounts(void){    FILE *fo, *fn;    char fileold[PATH_MAX], filenew[PATH_MAX];    char buffer[1024];    sprintf(fileold, "%s/%s", radius_dir, RADIUS_STOP);    sprintf(filenew, "%s/%s.new", radius_dir, RADIUS_STOP);    fo = fopen(fileold, "r");    if (fo == NULL) {	/* no stoplist, bail out */	if (debug_flag) {	    printf("!!!");	    fflush(stdout);	}	return;    }    fn = fopen(filenew, "w");    if (!fn) {	fprintf(stderr, "Error creating file %s (permission problem ?)\n",		filenew);	exit(-3);    }    while (fgets(buffer, sizeof(buffer), fo) != NULL) {	if (buffer[strlen(buffer)-1] != '\n') {	    /* line too long ... */	    fprintf(stderr, "line too long reading from %s\n", fileold);	    fclose(fn);	    fclose(fo);	    exit(-3);	}	if (strlen(buffer) > USERNAME_MAX) {	    /* not a username line */	    fprintf(fn, "%s", buffer);	    if (debug_flag) {		printf("!-!-!");		fflush(stdout);	    }	    continue;	}	buffer[strlen(buffer)-1] = '\0';	if (over_quota(buffer))	    /* this user is still over quota */	    fprintf(fn, "%s\n", buffer);	else if (debug_flag) {		printf("%s ", buffer);		fflush(stdout);	}	/* else will be skipped */    }    fclose(fo);    fclose(fn);    unlink(fileold);    link(filenew, fileold);    unlink(filenew);}    /* * Just to be fancy and put two calls to other functions in their own block... * Overall, this is the idea of this program: unlock the accounts which are * no longer under quota constraints, and add the new ones after that. */static void check_user_times(void){    if (debug_flag)	print_user_list();    if (debug_flag) {	printf("Unlocking accounts no longer over quota: ");	fflush(stdout);    }    unlock_accounts();    if (debug_flag)	printf("DONE. \n");    if (debug_flag) {	printf("Locking accounts over quota: ");	fflush(stdout);    }    lock_accounts();    if (debug_flag)	printf("DONE.\n");}/* * The Main Thing: make this program work. */int main(int argc, char ** argv){    GDBM_FILE dbf;    datum key, content, nextkey;    time_t crt_time;    /* init paramaters */    progname = argv[0];    monthly_detail = 0;        rad_acctdir = RADACCT_DIR;    radius_dir = RADIUS_DIR;    radius_log = NULL;    parse_args(argc, argv);    crt_time = time(NULL); /* by default check against current time */    dbf = open_radlist();    if (dbf == NULL)	exit(-1);    if (debug_flag) {	printf("Building preliminary list of users: ");	fflush(stdout);    }    key = gdbm_firstkey(dbf);    while (key.dptr != NULL) {	static char str_user[1024];	struct  conf_line *pp;	struct  tm *tm;	short   dtime;	int     i;	/* init those each time for safety */	memset(str_user, 0, sizeof(str_user));	memcpy(str_user, key.dptr, min(key.dsize, sizeof(str_user)-1));	/*	 * The current time is converted to HHMM format for	 * comparision against the time values in the TTY entry.	 */	tm = localtime(&crt_time);	dtime = tm->tm_hour * 100 + tm->tm_min;	content = gdbm_fetch(dbf, key);	if (content.dptr == NULL) {	    fprintf(stderr, "Can not retrieve data for user %s\n",str_user);	    nextkey = gdbm_nextkey(dbf,key);	    free(key.dptr);	    key=nextkey;	    continue;	}	/*	 * Try to find a matching entry for this user.  Default to	 * letting the user in - there are pleny of ways to have an	 * entry to match all users.	 */	if ((pp = get_user_line (str_user)) == NULL) {	    /* no restriction */	    nextkey = gdbm_nextkey(dbf,key);	    free(key.dptr);	    key=nextkey;            continue;	}	if (pp->times == 0) {	    /*	     * The entry is there, but has no time entries	     */	    nextkey = gdbm_nextkey(dbf,key);	    free(key.dptr);	    key=nextkey;            continue;	}	/*	 * Each time entry is compared against the current	 * time. For entries with the start after the end time,	 * the comparision is made so that the time is between	 * midnight and either the start or end time.	 */	for (i = 0; pp->times[i].t_start != -1; i++) {	    if (! (pp->times[i].t_days & PORT_DAY(tm->tm_wday)))		continue;	    if (pp->times[i].t_start <= pp->times[i].t_end) {		if (dtime >= pp->times[i].t_start && dtime <= pp->times[i].t_end)		    insert_user_in_list(str_user, pp->times+i, crt_time, pp->restriction, 					(user_entry *)content.dptr, content.dsize);	    } else {		if (dtime >= pp->times[i].t_start || dtime <= pp->times[i].t_end)		    insert_user_in_list(str_user, pp->times+i, crt_time, pp->restriction, 					(user_entry *)content.dptr, content.dsize);	    }	}	nextkey = gdbm_nextkey(dbf,key);	free(key.dptr);	key=nextkey;    }    gdbm_close(dbf);    if (debug_flag) {	printf("OK.\n");	fflush(stdout);    }    if (parse_radacct_file() != 0)	fprintf(stderr, "Unable to open radlast log file !\n");    else check_user_times();    empty_user_time_list();    exit(0);}void rad_exit(int code){        exit(code);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -