📄 rsvp_mstat.c
字号:
/* * @(#) $Id: rsvp_mstat.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Shai Herzog, Derek Yeung, Nov. 1993. Current Version: Steven Berson & Bob Braden, May 1996 Copyright (c) 1996 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 any purpose and without fee is hereby granted, provided that both the above copyright notice and this permission notice appear in all copies, and that any documentation, advertising materials, and other materials related to such distribution and use acknowledge that the software was developed in part 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.********************************************************************//* * Routines to multicast state information to status display programs. * (Actually, could configure to send to a unicast address). * * Version 2 -- Handles variable-length objects, and tests for * sessions disappearing to give GONE indications. */#include "rsvp_daemon.h"#include "rsvp_api.h"#include "rsvp_mstat.h"#include "rapi_lib.h"#define d_addr d_session->sess4_addr#define d_port d_session->sess4_port#define _ps_phop ps_rsvp_phop.hop4_addr#define _rs_nhop rs_rsvp_nhop.hop_u.hop_ipv4.hop_ipaddr/* Global rsvpd control variables */extern if_rec *if_vec;extern Session *session_hash[];extern int probe_socket;extern int mstat_ttl;static int statsock = -1;static struct sockaddr_in mcast_sin;static char RSVPNodeName[NAME_LEN]; /* name of the current router */static char buff[2*STAT_MSG_SIZE];static int max_msg_size = STAT_MSG_SIZE;static int nSession, nStyle_Sess;static int IsDebugSess = 0;static int Send_Empty = 0;Object_header NULL_OBJECT = {4, 0, 0}; /* min length NULL object *//* external declarations */char *strtcpy(char *, char *, int);/* forward declarations */static void status_RSVP_Path(struct sockaddr_in *);static void status_RSVP_Resv(struct sockaddr_in *);static char *mstat_objcpy(Object_header *, Object_header *);static void status_send(char *, struct sockaddr_in *);static PathInfo_t *status_Path_Session(Session *, PathInfo_t *);static ResvInfo_t *fmt_WF_Resv(Session *, ResvInfo_t *);static ResvInfo_t *fmt_FF_Resv(Session *, ResvInfo_t *);static ResvInfo_t *fmt_SE_Resv(Session *, ResvInfo_t *);static void New_Resv_Session(Session *, ResvInfo_t *, int);static void Mark_Session(SESSION_ipv4 *, int);static void Gone_Session(int);/* * List of sessions. Use this list to detect deletion of session state, * so can explicitly notify display programs of session deletion. * For each session entry, make simple little FSM, separately for * Path and Resv state. */#define MAX_SL 4struct session_list { SESSION_ipv4 sl_dest; u_char sl_fsms[2]; /* FSM states */#define SL_FSM_PATH 0 /* Path state FSM */#define SL_FSM_RESV 1 /* Resv state FSM */#define SL_IDLE 0 /* Session_list entry unused */#define SL_OLD 1 /* Session existed */#define SL_ACTV 2 /* Session exists now */ } Session_List[MAX_SL], *Gone_Sessp, *Next_Sessp;/* * Initialize for sending status messages: * * Socket address mcast_sin * * UDP socket statsock * * RSVPNodeName * * Session list pointer Next_Sessp; */int Status_Init(char *destaddr) { char buf[256]; struct in_addr host; char *tp; char *rmsuffix(char *); u_char ttlval = mstat_ttl; int port = 0, one = 1; (void) strcpy(buf, destaddr); if ((tp = rmsuffix(buf))) port = hton16(atoi(tp)); if ((host.s_addr = inet_addr(buf)) == -1) { fprintf(stderr, "Status addr not dotted dec.: %s\n", buf); return (-1); } NET_SOCKADDR_UDP_IPv4( &mcast_sin, host, port); if ((statsock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { log(LOG_ERR, errno, "Socket Error\n"); return(-1); } /* Allow socket to be reused */ if (setsockopt(statsock, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one))) { log(LOG_ERR, errno, "Status SO_REUSE err\n"); close(statsock); return(-1); } /* Set multicast TTL */ if (IN_MULTICAST(ntoh32(host.s_addr))) { if (0 > setsockopt(statsock, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &ttlval, sizeof(ttlval))) { close(statsock); log(LOG_ERR, errno, "Status mcast TTL err\n"); return(-1); } } /* Get my node DNS name, and remove all trailing components */ gethostname(RSVPNodeName, NAME_LEN); while (rmsuffix(RSVPNodeName)) { }; /* Initialize session list pointer */ Next_Sessp = &Session_List[0]; return (0);}/* init_probe_socket(): Called from main() during RSVP initialization. * Initializes socket for receiving status probes. */voidinit_probe_socket() { struct sockaddr_in sin; int one = 1; /* * Create probe_socket, a UDP socket for receiving a state * probe packet. */ if ((probe_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { log(LOG_ERR, errno, "socket", 0); exit(-1); } if (setsockopt(probe_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one))) { log(LOG_ERR, errno, "Uisock REUSEADDR", 0); exit(-1); } /* * Bind to probe port. */ NET_SOCKADDR_UDP_IPv4(&sin, inaddr_any, htons(STAT_PROBE_PORT)); if (bind(probe_socket, (struct sockaddr *) &sin, sizeof(sin))) { log(LOG_ERR, errno, "bind", 0); exit(-1); }}/* * mcast_rsvp_state(): send Path State and Resv state information * to remote monitor programs (e.g., dmap or rsvpeep). * Called from dump_ds() in rsvp_debug.c. */void mcast_rsvp_state() { if (statsock < -1) return; /* ignore call */ if (statsock < 0) { /* * First call: Convert target address: <host>.<port> * and set up socket address. If it fails, set * statsock = -2 and ignore future calls. Currently * <host> must be dotted decimal string. */ if (Status_Init(STAT_DEST_ADDR) < 0) { statsock = -2; return; } } /* Now format and send path and reservation state */ Send_Empty = 0; status_RSVP_Path(&mcast_sin); status_RSVP_Resv(&mcast_sin);}voidsend_rsvp_state(char *probe_buf, int probe_len, struct sockaddr_in *fromp) { /* Probe packet may generally contain list of hosts to be * probed and list of sessions to be probed. For now, assume * only present host and all sessions. */ struct sockaddr_in to = *fromp; if (probe_len < sizeof(u_int32_t) || ntohl(*(u_int32_t *)probe_buf) != TYPE_RSVP_PROBE) return; if (statsock < -1) return; /* ignore call */ if (statsock < 0) { if (Status_Init(STAT_DEST_ADDR) < 0) { statsock = -2; return; } } /* Now format and send path and reservation state */ Send_Empty = 1; status_RSVP_Path(&to); status_RSVP_Resv(&to);}/* * This procedure extracts the Path State information from rsvpd * data structure, marshals it, and sends it out. */voidstatus_RSVP_Path(struct sockaddr_in *sinp) { RSVPInfo_t *Infop = (RSVPInfo_t *) buff; PathInfo_t *Pathp, *New_Pathp; Session *dst; int i; nSession = 0; Infop->type = hton32(TYPE_RSVP_VPATH); strtcpy(Infop->name, RSVPNodeName, NAME_LEN); Pathp = &Infop->Session_un.pathInfo; /* first session */ /* * For each session ... */ for (i= 0; i < SESS_HASH_SIZE; i++) for (dst = session_hash[i]; dst; dst = dst->d_next) { /* * Call subroutine to move session data into packet. Then, * if packet has overflown, write out data up through the * previous session, and copy new session back into first * place. Finally, count new session and record it in * cache. */ New_Pathp = status_Path_Session(dst, Pathp); if ((char *) New_Pathp > &buff[max_msg_size]) { int newlen = (char *)New_Pathp - (char *)Pathp; status_send((char *)Pathp, sinp); New_Pathp = &Infop->Session_un.pathInfo; memcpy(New_Pathp, Pathp, newlen); New_Pathp = (PathInfo_t *) ((char *)New_Pathp + newlen); nSession = 0; } nSession++; Pathp = New_Pathp; } /* * Scan my private Session_List, looking for sessions that had * path state last time but have none this time, and send an * "empty" entry for any that are found. */ Gone_Sessp = NULL; do { Gone_Session(SL_FSM_PATH); if (Gone_Sessp) { Pathp->path_session = Gone_Sessp->sl_dest; Pathp->path_R = 0; Pathp->nSender = 0; New_Pathp = (PathInfo_t *) &Pathp->path_sender; if ((char *) New_Pathp > &buff[max_msg_size]) { status_send((char *)Pathp, sinp); return; /* truncate... */ } nSession++; Pathp = New_Pathp; } } while (Gone_Sessp); /* * Write last data, if any */ if ((nSession) || Send_Empty) status_send((char *) Pathp, sinp);}/* Move path status of specified session into output packet at * location Pathp, return pointer to next. We assume an output * buffer large enough to hold max message plus the additional * session we will add here. */static PathInfo_t *status_Path_Session(Session *dstp, PathInfo_t *Pathp) { PathSender_t *PathSp; PSB *snd; char *if_name, *tp; int nSenders = 0; Pathp->path_session.sess_destaddr.s_addr = dstp->d_addr.s_addr; Pathp->path_session.sess_destport = dstp->d_port; Pathp->path_R = dstp->d_Rtimop; HTON32(Pathp->path_R); Mark_Session(&Pathp->path_session, SL_FSM_PATH); PathSp = &Pathp->path_sender; for (snd = dstp->d_PSB_list; snd != NULL; snd = snd->ps_next) { if_name = if_vec[snd->ps_in_if].if_name; strtcpy(PathSp->pathS_in_if, if_name, IFNAMSIZ); PathSp->pathS_phop.s_addr = snd->_ps_phop.s_addr; PathSp->pathS_routes = snd->ps_outif_list; PathSp->pathS_ttd = snd->ps_ttd; /* HTON32(PathSp->pathS_routes); */ HTON32(PathSp->pathS_ttd); /****** NOT IN USE: LPM has this info, but not RSVP.*/ tp = mstat_objcpy(Object_of(&PathSp->pathS_policy), &NULL_OBJECT); tp = mstat_objcpy(Object_of(tp), Object_of(snd->ps_templ)); tp = mstat_objcpy(Object_of(tp), Object_of(snd->ps_tspec)); PathSp = (PathSender_t *) tp; nSenders++; /**** CHECK FOR OVERFLOW ***/ } Pathp->nSender = nSenders; HTON32(Pathp->nSender); return((PathInfo_t *) PathSp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -