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

📄 radrelay.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -1;	if (rename(from, to) < 0)		return -1;	oldmask = umask(0);	if ((n = open(from, O_CREAT|O_RDWR, st.st_mode)) >= 0)		close(n);	umask(oldmask);	return 0;}/* *	Open detail file, collect records, send them to the *	remote accounting server, yadda yadda yadda. * *	STATE_RUN:	Reading from detail file, sending to server. *	STATE_BACKLOG:	Reading from the detail.work file, for example *			after a crash or restart. Sending to server. *	STATE_WAIT:	Waiting for all outstanding requests to be handled. *	STATE_CLOSE:	Reached end of detail.work file, waiting for *			outstanding requests, and removing the file. *	STATE_SHUTDOWN:	Got SIG_TERM, waiting for outstanding requests *			and exiting program. */void loop(struct relay_misc *r_args){	FILE *fp = NULL;	struct relay_request *r;	struct timeval tv;	fd_set readfds;	char work[1030];	time_t now, last_rename = 0;	int i, n;	int state = STATE_RUN;	int id;	long fpos;	strNcpy(work, r_args->detail, sizeof(work) - 6);	strcat(work, ".work");	id = ((int)getpid() & 0xff);	/*	 * Initialize all our slots, might as well do this right away.	 */	for (i = 0; i < NR_SLOTS; i++) {		if ((slots[i].req = rad_alloc(1)) == NULL) {			librad_perror("radrelay");			exit(1);		}		slots[i].state = STATE_EMPTY;		slots[i].retrans = 0;		slots[i].retrans_num = 0;		slots[i].timestamp = 0;		slots[i].client_ip = 0;		slots[i].req->sockfd = r_args->sockfd;		slots[i].req->dst_ipaddr = r_args->dst_addr;		slots[i].req->dst_port = r_args->dst_port;		slots[i].req->src_ipaddr = r_args->src_addr;		slots[i].req->code = PW_ACCOUNTING_REQUEST;		slots[i].req->vps = NULL;		slots[i].req->data = NULL;	}	while(1) {		if (got_sigterm) state = STATE_SHUTDOWN;		/*		 *	Open detail file - if needed, and if we can.		 */		if (state == STATE_RUN && fp == NULL) {			if ((fp = fopen(work, "r+")) != NULL)				state = STATE_BACKLOG;			else				fp = fopen(r_args->detail, "r+");			if (fp == NULL) {				fprintf(stderr, "%s: Unable to open detail file - %s\n", progname, r_args->detail);				perror("fopen");				return;			}		}		/*		 *	If "request_head" points to a free or not-completely-		 *	filled slot, we can read from the detail file.		 */		r = &slots[request_head];		if (fp && (state == STATE_RUN || state == STATE_BACKLOG) &&		    r->state != STATE_FULL) {			if (read_one(fp, r) == EOF) do {				/*				 *	We've reached end of the <detail>.work				 *	It's going to be closed as soon as all				 *	outstanting requests are handled				 */				if (state == STATE_BACKLOG) {					state = STATE_CLOSE;					break;				}				/*				 *	End of file. See if the file has				 *	any size, and if we renamed less				 *	than 10 seconds ago or not.				 */				now = time(NULL);				if (ftell(fp) == 0 || now < last_rename + 10) {					fpos = ftell(fp);					fseek(fp, 0L, SEEK_SET);					rad_unlockfd(fileno(fp), 0);					fseek(fp, fpos, SEEK_SET);					break;				}				last_rename = now;				/*				 *	We rename the file to <file>.work				 *	and create an empty new file.				 */				if (detail_move(r_args->detail, work) == 0) {					if (debug_flag > 0)						fprintf(stderr, "Moving %s to %s\n",							r_args->detail, work);					/*					 *	rlm_detail might still write					 *	something to <detail>.work if					 *	it opens <detail> before it is					 *	renamed (race condition)					 */					ms_sleep(1000);					state = STATE_BACKLOG;				}				fpos = ftell(fp);				fseek(fp, 0L, SEEK_SET);				rad_unlockfd(fileno(fp), 0);				fseek(fp, fpos, SEEK_SET);			} while(0);			if (r->state == STATE_FULL)				request_head = (request_head + 1) % NR_SLOTS;		}		/*		 *	Perhaps we can receive something.		 */		tv.tv_sec = 0;		tv.tv_usec = 25000;		FD_ZERO(&readfds);		FD_SET(r_args->sockfd, &readfds);		n = 0;		while (select(r_args->sockfd + 1, &readfds, NULL, NULL, &tv) > 0) {			do_recv(r_args);			if (n++ >= NR_SLOTS) break;		}		/*		 *	If we're in STATE_WAIT and all slots are		 *	finally empty, we can remove the <detail>.work		 */		if (state == STATE_WAIT || state == STATE_CLOSE || state == STATE_SHUTDOWN) {			for (i = 0; i < NR_SLOTS; i++)				if (slots[i].state != STATE_EMPTY)					break;			if (i == NR_SLOTS) {				if (state == STATE_CLOSE) {					if (fp) fclose(fp);					fp = NULL;					if (debug_flag > 0)						fprintf(stderr, "Unlink file %s\n", work);					unlink(work);				}				else if (state == STATE_SHUTDOWN) {					for (i = 0; i < NR_SLOTS; i++) {						rad_free(&slots[i].req);					}					exit(0);				}				state = STATE_RUN;			}		}		/*		 *	See if there's anything to send.		 */		n=0;		for (i = 0; i < NR_SLOTS; i++) {			if (slots[i].state == STATE_FULL) {				n += do_send(&slots[i], r_args->secret);				ms_sleep(140);				if (n > NR_SLOTS / 2)					break;			}		}	}}/* * Search through the "client" config sections (usually in clients.conf). * This is an easy way to find a secret and an host. */int find_shortname(char *shortname, char **host, char **secret){	CONF_SECTION *maincs, *cs;	/*	 *	Ensure that the configuration is initialized.	 */	memset(&mainconfig, 0, sizeof(mainconfig));	if ((maincs = read_radius_conf_file()) == NULL) {		fprintf(stderr, "Error reading radiusd.conf\n");		exit(1);	}	/*	 * Find the first 'client' section.	 */	cs = cf_section_sub_find(maincs, "client");	if (cs) {		c_shortname = cf_section_value_find(cs, "shortname");		c_secret = cf_section_value_find(cs, "secret");		/*		 * Keep searching for 'client' sections until they run out		 * or we find one that matches.		 */		while (cs && strcmp(shortname, c_shortname)) {			free(c_shortname);			free(c_secret);			cs = cf_subsection_find_next(cs, cs, "client");			if (cs) {				c_shortname = cf_section_value_find(cs, "shortname");				c_secret = cf_section_value_find(cs, "secret");			}		};	};	if (cs) {		*host = cf_section_name2(cs);		*secret = c_secret;		if (host && secret)			return 0;	}	return -1;}void usage(void){	fprintf(stderr, "Usage: radrelay [-a accounting_dir] [-d radius_dir] [-i local_ip] [-s secret]\n");	fprintf(stderr, "[-S secret_file] [-fx] <[-n shortname] [-r remote-server[:port]]> detailfile\n");	fprintf(stderr, " -a accounting_dir     Base accounting directory.\n");	fprintf(stderr, " -d radius_dir         Base radius (raddb) directory.\n");	fprintf(stderr, " -f                    Stay in the foreground (don't fork).\n");	fprintf(stderr, " -h                    This help.\n");	fprintf(stderr, " -i local_ip           Use local_ip as source address.\n");	fprintf(stderr, " -n shortname          Use the [shortname] entry from clients.conf for\n");	fprintf(stderr, "                       ip-adress and secret.\n");	fprintf(stderr, " -r remote-server      The destination address/hostname.\n");	fprintf(stderr, " -s secret             Server secret.\n");	fprintf(stderr, " -S secret_file        Read server secret from file.\n");	fprintf(stderr, " -x                    Debug mode (-xx gives more debugging).\n");	exit(1);}int main(int argc, char **argv){	struct servent *svp;	char *server_name;	char *shortname;	char *p;	int c;	int i;	int dontfork = 0;	struct relay_misc r_args;	FILE *sfile_fp;	progname = argv[0];	r_args.sockfd = -1;	r_args.dst_addr = 0;	r_args.dst_port = 0;	r_args.src_addr = 0;	memset((char *) r_args.detail, 0, 1024);	memset((char *) r_args.f_secret, 0, 256);	r_args.secret = NULL;	shortname = NULL;	server_name = NULL;	radius_dir = strdup(RADIUS_DIR);	librad_debug = 0;	/*	 *	Make sure there are stdin/stdout/stderr fds.	 */	while ((c = open("/dev/null", O_RDWR)) < 3 && c >= 0);	if (c >= 3) close(c);	/*	 *	Process the options.	 */	while ((c = getopt(argc, argv, "a:d:fhi:n:r:s:S:x")) != EOF) switch(c) {		case 'a':			if (strlen(optarg) > 1021) {				fprintf(stderr, "%s: acct_dir to long\n", progname);				exit(1);			}			strncpy(r_args.detail, optarg, 1021);			break;		case 'd':			if (radius_dir)				free(radius_dir);			radius_dir = strdup(optarg);			break;		case 'f':			dontfork = 1;			break;		case 'n':			shortname = optarg;			break;		case 'r':			server_name = optarg;			break;		case 's':			r_args.secret = optarg;			break;		case 'x':			/*			 * If -x is called once we enable internal radrelay			 * debugging, if it's called twice we also active			 * lib_rad debugging (fairly verbose).			 */			if (debug == 1)				librad_debug = 1;			debug = 1;			dontfork = 1;			break;		case 'S':			sfile_fp = fopen(optarg, "r");			if (sfile_fp == NULL) {				fprintf(stderr, "Error opening %s: %s\n",				        optarg, strerror(errno));				exit(1);			}			if (fgets(r_args.f_secret, 256, sfile_fp) == NULL) {				fprintf(stderr, "Error reading from %s: %s\n",				        optarg, strerror(errno));				fclose(sfile_fp);				exit(1);			}			fclose(sfile_fp);			for (c = 0; c < strlen(r_args.f_secret); c++)				if (r_args.f_secret[c] == ' ' ||				    r_args.f_secret[c] == '\n')					r_args.f_secret[c] = '\0';			if (strlen(r_args.f_secret) < 2) {				fprintf(stderr, "Secret in %s is to short\n",				        optarg);				exit(1);			}			r_args.secret = r_args.f_secret;			break;		case 'i':			if ((r_args.src_addr = ip_getaddr(optarg)) == 0) {				fprintf(stderr, "%s: unknown host %s\n",					progname, optarg);				exit(1);			}			break;		case 'h':		default:			usage();			break;	}	/*	 *	No detail file: die.	 */	if (argc == optind) {		usage();	}	argc -= (optind - 1);	argv += (optind - 1);	if (shortname && server_name)		usage();	if (!shortname && !server_name)		usage();	if (r_args.secret != NULL && shortname != NULL)		usage();	/*	 * If we've been given a shortname, try to fetch the secret and	 * adress from the config files.	 */	if (shortname != NULL) {		if (find_shortname(shortname, &server_name, &r_args.secret) == -1) {			fprintf(stderr, "Couldn't find %s in configuration files.\n", shortname);			exit(1);		}	}	/*	 * server_name should already be set either by the -r or the -s	 * commandline argument.	 */	if ((p = strrchr(server_name, ':')) != NULL) {		*p = 0;		p++;		r_args.dst_port = ntohs(atoi(p));	}	if (r_args.dst_port == 0) {		svp = getservbyname ("radacct", "udp");		r_args.dst_port = svp ? ntohs(svp->s_port) : PW_ACCT_UDP_PORT;	} else {		r_args.dst_port = ntohs(r_args.dst_port);	}	r_args.dst_addr = ip_getaddr(server_name);	if (r_args.dst_addr == 0) {		fprintf(stderr, "%s: unknown host\n",			server_name);		exit(1);	}	if (r_args.secret == NULL || r_args.secret[0] == 0) {		fprintf(stderr, "No secret available for server %s\n",			server_name);		exit(1);	}	/*	 * Find what detail file to read from.	 *	 * FIXME: We should be able to expand dates etc. based on the pathname,	 * just like the detail module does.	 */	if (r_args.detail[0] == '\0') {		if (strlen(RADIR) > 1021) {			fprintf(stderr, "acct_dir to long\n");			exit(1);		}		strncpy(r_args.detail, RADIR, 1021);	}	if (chdir(r_args.detail) == -1) {		perror("chdir");		exit(1);	}	if (strlen(argv[1]) + strlen(r_args.detail) > 1023) {		fprintf(stderr, "Detail file path to long");		exit(1);	} else {		if (r_args.detail[strlen(r_args.detail) - 1] != '/')			r_args.detail[strlen(r_args.detail)] = '/';		strncat (r_args.detail, argv[1], 1023 - strlen(r_args.detail));	}	/*	 *	Initialize dictionary.	 */	if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {		librad_perror("radrelay");		exit(1);	}	/*	 *	Open a socket to the remote server.	 */	if ((r_args.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {		fprintf(stderr, "Error opening socket: %s", strerror(errno));		exit(1);	}	signal(SIGTERM, sigterm_handler);	if (!dontfork) {		if (fork() != 0)			exit(0);		close(0);		close(1);		close(2);		(void)open("/dev/null", O_RDWR);		dup(0);		dup(0);		signal(SIGHUP,  SIG_IGN);		signal(SIGINT,  SIG_IGN);		signal(SIGQUIT, SIG_IGN);#ifdef HAVE_SETSID		setsid();#endif	}	/*	 * Initialize the radius id map	 */	for(i=0;i<256;i++)		id_map[i] = 0;	/*	 *	Call main processing loop.	 */	loop(&r_args);	return 0;}

⌨️ 快捷键说明

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