📄 rstat.c
字号:
/* * @(#) $Id: rstat.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//******************************************************************** * * rstat - Display RSVP status * * Written by: Bob Braden (braden@isi.edu) * USC Information Sciences Institute * Marina del Rey, California * September 1995 * * Copyright (c) 1995 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. * ********************************************************************//* rstat.c * * This is intended to give the kind of local status display that * netstat provides, but for RSVP specifically. It may be extended * in the future to query remote RSVPs, and to do other fancy * things. * * rstat sends a UDP probe packet to the local RSVP daemon, and * then gathers and formats the reply packet(s). */#include "rsvp_daemon.h"#include "rsvp_mstat.h"char *version = "R1.4 May 2 1996";char *Usage_text = "\ Usage: rstat [-p] [-f] [-n] [-h node_name ]\n\ -p => show path state\n\ -f => show flowspecs and sender Tspecs\n\ -n => show only numeric (dotted-decimal) IP addresses\n\ -h => get status from specified node (default is self)\n";/* * Global control variables * */int Xdebug= 0;int Show_Path = 0;int Show_Flowspecs = 0;int Printed_header = 0;char From_name[128] = "";char Node_name[128] = "";char probe_buff[4];char *Type_name[] = {"", "PATH ", "RESV ", "PATH-ERR", "RESV-ERR", "PATH-TEAR", "RESV-TEAR"};#include <setjmp.h>jmp_buf savej; /* longjmp environ for receiving response */#define RESP_TIMEOUT 4 /* response timeout time */#define WFp(rp) ((ResvWF_t *)(rp))#define FFp(rp) ((ResvFF_t *)(rp))#define SEp(rp) ((ResvSE_t *)(rp))char *Heading = "\Iface Session Sender Neighbor\n";char SpecFormat[] = "%30s>> %s\n";int udpsock = -1;#define NIFACES 8#define NSTATS 32/* Define queue element structure. This precedes a PathInfo_t or * ResvInfo_t area and is used to sort them into order. */typedef struct Sess_Elem { struct Sess_Elem *selm_next; /* chain pointer */ int selm_size; /* #bytes of data following */ int selm_type; /* path/resv data */ SESSION_ipv4 selm_session;} sess_element_t;sess_element_t selm_head;/* Forward and external declarations */u_long resolve_name();extern char *fmt_filtspec(), *fmt_flowspec(), *fmt_tspec();extern void ntoh_flowspec(FLOWSPEC *), ntoh_tspec(SENDER_TSPEC *);#define ip_convert(addr) (IP_NumOnly ? net_inaddr_print((char *) &(addr),AF_INET) : net_inaddr_host((char *) &(addr),AF_INET))static int IP_NumOnly;char *fmt_session();void queue_info(char *, int, SESSION_ipv4 *, int);void recvstatus(void);void print_status();void hexf(FILE *, char *, int);int ntoh_Path(PathInfo_t *);int ntoh_Resv(ResvInfo_t *);int ntoh_session_ipv4(SESSION_ipv4 *);int ntoh_policydata(POLICY_DATA *);int ntoh_filterspec(FILTER_SPEC *);char *filtsptoa(FILTER_SPEC *);ResvInfo_t *Next_Resv_Session(ResvInfo_t *);PathInfo_t *Next_Path_Session(PathInfo_t *);void print_sess_Path();void print_sess_Resv();void print_header();void timeout();char *prune_hostname();void sort_ifaces(char **, int, int);#define fspectoa(x) fmt_flowspec((Obj_Class(x) != class_NULL)? (x):NULL)#define ftspectoa(x) (Obj_Class(x) != class_NULL)? fmt_tspec(x): "TS[]"#define From_addr(hop, w) (((&(hop))->s_addr == INADDR_ANY)? "API" : \ prune_hostname(ip_convert(hop), w))#define Iface_name(ifp) ((!strcmp((ifp), "local"))? "API" : (ifp))#define sess_data(x) (char *)((sess_element_t *)(x)+1)#define Sess_LT(x, y) ((x)->sess_destaddr.s_addr < (y)->sess_destaddr.s_addr ||\ ((x)->sess_destaddr.s_addr == (y)->sess_destaddr.s_addr && \ (x)->sess_destport < (y)->sess_destport) )#define Sess_EQ(x, y) ((x)->sess_destaddr.s_addr == (y)->sess_destaddr.s_addr \ && (x)->sess_destport == (y)->sess_destport )#define NotNULL(x) (Obj_Class(x) != class_NULL)intmain(argc, argv) int argc ; char **argv ; { extern char *optarg; u_int c; char *rmsuffix(), *tp; u_int32_t host; u_int16_t port; int one = 1; void (*prev_func)(); struct sockaddr_in sin; net_addr *addr; IP_NumOnly = 0; /* * Process command-line options */ while ((c = getopt(argc, argv, "fh:npx")) != -1) { switch (c) { case 'x': /* -x -- Debug flag */ Xdebug = 1 ; break ; case 'p': /* -p -- Show path state */ Show_Path = 1; break ; case 'n': /* -n -- Noconversion of host addrs to names */ IP_NumOnly = 1; break; case 'h': /* -h <host/router> */ strcpy(Node_name, optarg); break; case 'f': /* -f -- Show flowspecs */ Show_Flowspecs = 1; break; default: fprintf(stderr, Usage_text); exit(1) ; } } /* * Init socket */ if ((udpsock = socket(AF_INET, SOCK_DGRAM, 0))< 0) { perror("Socket Error") ; exit(1) ; } if (setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))){ perror("sockopt"); exit(1); } bzero((char *) &sin, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = 0; /* Wildcard port */ if (bind(udpsock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in)) < 0) { perror("Bind error"); exit(1); } if (Node_name[0] != '\0') { /* * Convert node address: <host>[ {:|/}<port> ] */ if ((tp = strpbrk(Node_name, ":/"))) { *tp = '\0'; port = htons((u_int16_t)atoi(tp+1)); } else port = htons(STAT_PROBE_PORT); host = resolve_name(Node_name); if (host == INADDR_ANY) { fprintf(stderr, "Unknown node %s\n", Node_name); return (-1); } } else { port = htons(STAT_PROBE_PORT); addr = net_get_default_interface(); if ((addr != NULL) && (NET_GET_TYPE(addr) == NET_ADDR_IPv4)) host = NET_GET_ADDR_IPv4(addr).s_addr; else { fprintf(stderr, "No default hostname\n"); return (-1); } } if (Xdebug) { struct in_addr addr; addr.s_addr = host; printf("Probe: %s:%d\n", inet_ntoa(addr), port); fflush(stdout); } sin.sin_addr.s_addr = host; sin.sin_port = port; if (IN_MULTICAST(ntoh32(host))) { printf("Multicast node address not allowed\n"); exit(-1); } *(int *)probe_buff = hton32(TYPE_RSVP_PROBE); if (sendto(udpsock, probe_buff, sizeof(probe_buff), 0, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { perror("sendto"); exit(-1); } if (Xdebug) { recvstatus(); /* Path */ recvstatus(); /* Resv */ } else { if (setjmp(savej) == 0) { prev_func = signal(SIGALRM, timeout); alarm(RESP_TIMEOUT); recvstatus(); /* Path */ recvstatus(); /* Resv */ alarm(0); } signal(SIGALRM, prev_func); } print_status(); return(0);}void timeout() { printf("...timeout\n"); fflush(stdout); longjmp(savej, 1);}/* * recvstatus(): Receive UDP packets and display status */voidrecvstatus() { struct sockaddr_in from; int fromlen = sizeof(struct sockaddr_in); char buff[2 * STAT_MSG_SIZE]; RSVPInfo_t *Infop = (RSVPInfo_t *) buff; ResvInfo_t *r_sesp, *new_r_sesp; PathInfo_t *p_sesp, *new_p_sesp; int i, n, size; n = recvfrom(udpsock, buff, sizeof(buff), 0, (struct sockaddr *)&from, &fromlen); if (n < 0) { perror("recvfrom"); exit(1); } strcpy(From_name, ip_convert(from.sin_addr)); print_header(); NTOH32(Infop->type); NTOH32(Infop->nSession); switch (Infop->type) { /* first fullword is type */ case TYPE_RSVP_VPATH: if (Xdebug) { printf("RCVD PATH:\n"); hexf(stdout, buff, n); fflush(stdout); } p_sesp = &Infop->Session_un.pathInfo; for (i= 0; i<Infop->nSession; i++) { ntoh_Path(p_sesp); new_p_sesp = Next_Path_Session(p_sesp); size = (char *) new_p_sesp - (char *)p_sesp; queue_info((char *)p_sesp, size, &p_sesp->path_session, Infop->type); p_sesp = new_p_sesp; } break; case TYPE_RSVP_VRESV: if (Xdebug) { printf("RCVD RESV:\n"); hexf(stdout, buff, n); } r_sesp = &Infop->Session_un.resvInfo; for (i= 0; i< Infop->nSession; i++) { ntoh_Resv(r_sesp); new_r_sesp = Next_Resv_Session(r_sesp); size = (char *) new_r_sesp - (char *)r_sesp; queue_info((char *)r_sesp, size, &r_sesp->resv_session, Infop->type); r_sesp = new_r_sesp; } break; default: fprintf(stderr, "Unknown RSVP mstat pkt type %d from host %s\n", Infop->type, inet_ntoa(from.sin_addr)); if (Xdebug) hexf(stdout, buff, n); break; } }voidqueue_info(char *data, int size, SESSION_ipv4 *sessp, int type) { sess_element_t *selmp, **p; selmp = (sess_element_t *) malloc(size+sizeof(sess_element_t)); selmp->selm_size = size; selmp->selm_type = type; selmp->selm_session = *sessp; memcpy(sess_data(selmp), data, size); p = &selm_head.selm_next; while(*p != NULL && Sess_LT(&(*p)->selm_session, sessp)){ p = &((*p)->selm_next); } selmp->selm_next = *p; *p = selmp;}PathInfo_t *Next_Path_Session(PathInfo_t *sesp) { PathSender_t *Pp; int j; Pp = &sesp->path_sender; for (j=0; j < sesp->nSender; j++) { Pp = (PathSender_t *) Next_Object( Next_Object( Next_Object(&Pp->pathS_policy))); } return((PathInfo_t *)Pp);}ResvInfo_t *Next_Resv_Session(ResvInfo_t *sesp) { int style = sesp->resv_style; char *rp; int j, k; rp = (char *) Next_Object(&sesp->resv_policy); for (j=0; j < sesp->nStruct; j++) { switch (style) { case RAPI_RSTYLE_WILDCARD: rp = (char *) Next_Object( Next_Object(&WFp(rp)->WF_flowspec)); break; case RAPI_RSTYLE_FIXED: rp = (char *) Next_Object( Next_Object(&FFp(rp)->FF_flowspec)); break; case RAPI_RSTYLE_SE: rp = (char *) Next_Object(&SEp(rp)->SE_flowspec); for (k = 0; k < ((ResvSE_t *)rp)->nSE_filts; k++) rp = (char *) Next_Object(rp); break; default: break; } } return((ResvInfo_t *) rp);}/* Display status from sorted queue of session elements * List has form: [Resv1] Path1 [Resv2] Path2 ... * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -