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

📄 rsvptrace.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  @(#) $Id: rsvptrace.c,v   *//******************************************************************** * *            rsvptrace - trace RSVP state over reverse path  *                                                                           *              Written by: Subramaniam Vincent (svincent@isi.edu) *              USC Information Sciences Institute *              Marina del Rey, California *	        April 1997 *                                                                           *  Copyright (c) 1997 by the University of Southern California *  All rights reserved. * *  Permission to use, copy, modify, and distribute this software and its *  documentation in source and binary forms for non-commercial purposes *  and without fee is hereby granted, provided that the above copyright *  notice appear in all copies and that both the copyright notice and *  this permission notice appear in supporting documentation. and that *  any documentation, advertising materials, and other materials related *  to such distribution and use acknowledge that the software was *  developed by the University of Southern California, Information *  Sciences Institute.  The name of the University may not be used to *  endorse or promote products derived from this software without *  specific prior written permission. * *  THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about *  the suitability of this software for any purpose.  THIS SOFTWARE IS *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * *  Other copyrights might apply to parts of this software and are so *  noted when applicable. * ********************************************************************//*                            rsvptrace.c * *	This utility is intended to trace rsvp state from a specific starting  * 	hop called last hop, along the reverse path towards a specific sender.  *  *	Currently reservation and path (sender) state are collected for a session. * *      rsvptrace sends a UDP Diagnostic Request packet to a "Last-hop" rsvp router to        *	start the trace.  rsvptrace gathers the replies, and prints them out.  */#include "rsvp_daemon.h"#define tvsub(A, B)   (A)->tv_sec -= (B)->tv_sec ;\         if (((A)->tv_usec -= (B)->tv_usec) < 0) {\                  (A)->tv_sec-- ;\                  (A)->tv_usec += 1000000 ; }#define tvGEQ(A,B)   ( (A)->tv_sec > (B)->tv_sec || \	( (A)->tv_sec == (B)->tv_sec && (A)->tv_usec >= (B)->tv_usec))#define tvadd(A, B)   (A)->tv_sec += (B)->tv_sec ;\         if (((A)->tv_usec += (B)->tv_usec) > 1000000) {\                  (A)->tv_sec++ ;\                  (A)->tv_usec -= 1000000 ; }#define	UCAST_TTL	63/* 	DIAG_DEF_TIMEOUT : 10 seconds  *	Reply wait time for timeouts : If first reply comes within *	the specified timeout or the default value, we  * 	wait an equal amount of time for all the other replies.  * 	Each time we timeout waiting, increase timeout interval  * 	exponentially. * *	DIAG Retransmit count : 3 times * */#define DIAG_DEF_TIMEOUT 10#define DIAG_RETRY_COUNT  3/* 	NTP timestamp related */#define JAN_1970 	2208988800UL#define iptoname(x)	(IP_NumOnly ? net_inaddr_print((char *) (x),AF_INET) : net_inaddr_host((char *) (x),AF_INET))/*	external declarations */int 		net_init_udp_only(net_addr *);char 		*fmt_filtspec(), *fmt_flowspec(), *fmt_tspec();/* 	forward declarations */int	 	init_diag();int 		send_diag_request(struct packet *); int    		trace_prepare(struct packet *);int    		trace_accept_reply(struct packet *, net_addr *);int		trace_print_status(int ,int );int 		trace_waitfor_replies(struct timeval *, int *);int		trace_input();int 		next_wait(struct timeval *, int, struct timeval *);int 		do_sendmsg(int, net_addr *, net_addr *, int, u_char, u_char *, int);int		do_sendto(net_addr *, net_addr *, u_char *data, int len, u_char ttl);u_long 		get_time_constant();char 		*time_stamp(struct timeval *);enum    exitcode {	DIAG_ALL_RECVD,			DIAG_SOME_RECVD,	DIAG_NONE_RECVD};typedef struct diag_request {	SESSION_ipv4	rsvp_dsess;	net_addr 	sender;	net_addr 	last_hop;	u_int16_t	path_mtu ;#define DIAG_DEF_PATH_MTU	 		1400 	u_char 		max_hops;#define DIAG_DEF_MAX_HOPS	 		10 	u_char 		H;		#define DIAG_REPLY_DIRECT		0#define DIAG_REPLY_HBH			1	net_addr 	resp_to ;	struct 		packet req_pkt;	u_char		status;	u_int32_t	curr_id;	/* latch for message id of first received reply */	u_int32_t	timeout;	/* retransmit timeout for diag requests */	u_char 		rcount;} diag_req_t ;/* 	Global control */static int 	IP_NumOnly ;int 		Max_rsvp_msg ;diag_req_t 	diag_req ;char 		recv_buff[MAX_PKT]; char *version = "R1.0 April 10th 1997";char *Usage_text = "\Usage: rsvptrace  [-h<hops>] [-H] [-L<Last-hop addr>] [-m<path mtu>]\n\                  [-s<timeout>] [-{U|T|p <proto#>}] [-n]\n\	          <sess addr/port> <sender addr/port>\n"; intmain(argc, argv)	int argc ;	char **argv ;	{	u_int			c, ss = 0;	u_char	        	parse_fail = 0;	char 			*tp ;	u_long			host, addr;	u_int16_t		port;	int			mode = 0, count = 0;	struct  in_addr		iaddr;	struct  timeval		tsent;	struct  timezone	tz;    	/*	 *	Process command-line options	 */	if (argc < 2) {		fprintf(stderr,Usage_text);		exit(-1);	}/*      Initialize diagnostics */	(void)init_diag();	for (c = 1; c < argc ; c++) {		if (argv[c][0] == '-') {			switch(argv[c][1]) {			      case 's':  /* -s<timeout> -- wait time in seconds for first 					  * retransmit					  */				if((diag_req.timeout = (u_int32_t)atoi(&argv[c][2])) <= 0)				  parse_fail = 1;				break;			      case 'h':  /* -h<hops> -- max RSVP hops to traverse */				if((diag_req.max_hops = (u_char)atoi(&argv[c][2])) <= 0)				  parse_fail = 1;				break;							      case 'n':   /* -n -- Noconversion of host addrs to names */				IP_NumOnly = 1;				break;							      case 'H':   /* -H -- specifies HBH reply mode */				diag_req.H = DIAG_REPLY_HBH ;				break ; 			      case 'm':   /* -m<path_mtu> -- max diag pkt size for trim/forward */				if ((diag_req.path_mtu = atoi(&argv[c][2])) <= 0)				  parse_fail = 1;				break;							      case 'L':  /* -L<Last-hop> -- RSVP router to start diagnosis from */				if( (addr = resolve_name(&argv[c][2])) <= 0)				  parse_fail = 1;				else 				  NET_GET_ADDR_UDP_IPv4(&diag_req.last_hop).sin_addr.s_addr = addr;				break;							      case 'T':  /* -U -- session type is TCP, UDP is the default */					diag_req.rsvp_dsess.sess_protid = IPPROTO_TCP;				break ;			      case 'U':  /* -U -- session type is UDP, this is the default */					diag_req.rsvp_dsess.sess_protid = IPPROTO_UDP;				break ;			     case 'p': /* -p<proto> -- session type is IPPROTO_<proto> */				if((diag_req.rsvp_dsess.sess_protid = atoi(&argv[c][2])) <= 0)				  parse_fail = 1;				break ;			      default:    				fprintf(stderr, Usage_text);				exit(1) ;			}		}		else {	     			/* 	Parse in the sess addr/port & sender addr/port, in that order.			 * 	sess addr/port MUST come first, 			 * 	and these two arguments MUST be the last arguments 			 * 	Variable 'ss' tracks sess and sender info 			 */			if ((tp = strpbrk(argv[c],":/"))) {                                *tp = '\0';                                if ((port = hton16((u_int16_t)atoi(tp+1))) <= 0)                                  parse_fail = 1;                        }                        else 			  parse_fail = 1;     	                if((host = resolve_name(argv[c])) <= 0)       	                  parse_fail = 1;			if (ss == 0) { 		/* sess addr/port */				diag_req.rsvp_dsess.sess_destaddr.s_addr = host ;				diag_req.rsvp_dsess.sess_destport = port ;				ss++;			}			else 			  if (ss == 1) {	/* sender addr/port */				  iaddr.s_addr = host;				  NET_SET_ADDR3_UDP_IPv4(&diag_req.sender,iaddr,port);				  ss++;			  }			  else 			    parse_fail = 1;		}	}	if (parse_fail || ss != 2) {		fprintf(stderr, Usage_text);		exit(1) ;	}	(void)trace_prepare(&diag_req.req_pkt);	printf("Rsvptrace from %s ",	       iptoname(&(NET_GET_ADDR_UDP_IPv4(&diag_req.last_hop).sin_addr)));	printf("to %s/%d ",	       iptoname(&(NET_GET_ADDR_UDP_IPv4(&diag_req.sender).sin_addr)),	       ntoh16(NET_GET_ADDR_UDP_IPv4(&diag_req.sender).sin_port));        printf("for session %s/%d\n",iptoname(&diag_req.rsvp_dsess.sess_destaddr),	       ntoh16(diag_req.rsvp_dsess.sess_destport));	printf("Querying reverse path...");	if (diag_req.H)	  printf("for hop by hop replies\n");	else 	  printf("\n");        printf("Timeout in %d seconds...\n",diag_req.timeout);	mode = send_diag_request(&diag_req.req_pkt);	if (mode < 0) {	       perror("??");	       exit(-1);       }	if (gettimeofday(&tsent,&tz) < 0) {		perror("get time error ");		exit(-1);	}	mode = trace_waitfor_replies(&tsent,&count);/* 	if we come here, we must be done */		(void)trace_print_status(mode,count);	net_final();	return 0;}/* trace_print_status(): * *	Called to print a summary line, at the end of a trace.  */inttrace_print_status(int mode,int count) {	switch(mode) {	      case DIAG_ALL_RECVD : 		/*printf("\n%d replies received\n",count);*/		break ;	      case DIAG_NONE_RECVD : 		assert(count == 0);		printf("\nno replies received, timed out\n");		break;	      case DIAG_SOME_RECVD : 		assert(count > 0);		printf("\n%d replies received, fragments due, but timed out\n",count);		break ;	      default :		assert(0);	}	return 0;}/* send_diag_request(): * 	sends a diagnostic request packet, that has already been built.  * 	increments the message ID for each send.  */int send_diag_request(struct packet * pkt) {	/*	 *      TTL setup is only for unicast packets. If this was a	 *      diagnostics reply to a multicast address, ttl would have	 *      already been set.	 */	if(!IN_IS_ADDR_MULTICAST(&NET_GET_ADDR_IPv4(&diag_req.last_hop)))		pkt->pkt_ttl = UCAST_TTL;	pkt->pkt_flags |= PKTFLG_NOENCAP ;	pkt->pkt_map->rsvp_diag->diag_msgID++;	return(build_send_pkt(-1, &diag_req.last_hop, NULL, &diag_req.req_pkt));}	/* trace_waitfor_replies() *	 *	A sort of dispatcher for diagnostics. *	After the first DREQ is sent, this routine in called. *	Retransmits, timeout interval adjustments are done here. */int trace_waitfor_replies(struct timeval *snt_tv, int *num) {	struct timeval  t_intvl;	struct timeval	t_recv, t_sent;	struct timezone tz;        fd_set		rd_fds;	int		waittime  = diag_req.timeout;	int 		fd_wid, rc, wait;	u_char		rcount = 0, retr = 0, done = 0;	t_sent = *snt_tv ;	/* 	local copy */	wait   = waittime;     	/*      initialize wait to waittime *//* 	wait for "reply or multiple reply" I/O dispatcher loop  */	(void)next_wait(&t_sent,wait,&t_intvl);	fd_wid = getdtablesize();	while (!done) {	 		net_poll_list(&rd_fds);		rc = select(fd_wid,&rd_fds,(fd_set *)NULL,(fd_set *)NULL, &t_intvl);		if (rc < 0) {			assert(errno == EINTR);			continue;		}				/*	handle timeouts */		if (rc == 0) {			if(rcount > 0) /* 	fragment receive timeout, 					* 	finish trace and exit 					*/			  return DIAG_SOME_RECVD ;			if(rcount == 0 && retr == DIAG_RETRY_COUNT)			               /* 	No replies at all, and max 					* 	retransmits done 					*/			  return DIAG_NONE_RECVD ;						/*	retransmit the DREQ packet */			rc = send_diag_request(&diag_req.req_pkt);			if (rc < 0) 			  exit (-1) ; 						else {	  	/*	wait time for DREQ retransmit 					 * 	goes up exponentially with 					 *      retransmits, for now.					 *      {5,10,20} seconds, is the wait					 *	time sequence.					 */				(void)gettimeofday(&t_sent,&tz);				retr++;				wait = 2*wait;				/*(void)next_wait(&t_sent,((int)(retr+1)*waittime),&t_intvl);	*/				(void)next_wait(&t_sent,wait,&t_intvl); 				printf("* ");fflush(stdout);				continue ;				}		}		/*	If we come here then we have a reply. 		 *	The status'es ALL_RECVD and SOME_RECVD 		 * 	will be set while processing by 		 *	trace_accept_reply().		 */		(void)gettimeofday(&t_recv,&tz);		rc = trace_input();		if (rc == 0)		  *num = ++rcount;		else 		/* 	Some invalid reply was received, so continue */	  		  if (rc > 0)  		    continue;		/* 	In case there are more fragments and/or the 		 *	the udp read failed, continue waiting till 		 *	end of timeout. If the read succeeded for 		 *	an intermediary reply, but it had a parse error, 		 * 	we will not know that and just wait till 		 *	timeout.		 */		if (diag_req.status == DIAG_SOME_RECVD || rc == -1) {			tvsub(&t_recv,&t_sent);			assert(1 == tvGEQ(&t_intvl,&t_recv));			tvsub(&t_intvl,&t_recv);		}		else		 /* 	if the first reply had some corruption/parse error, 		  * 	we will not know if there are any more replies, so 		  *	we quit.		  */		  done = 1;	}	return 0;}/* trace_input() * *	Receive a UDP RSVP message, right now a diag reply. */

⌨️ 快捷键说明

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