/* * @(#) $Id: rsvp_debug.c,v 4.34 1998/08/18 17:31:24 lindell Exp $ */ /***************************** rsvp_debug.c ****************************** * * * * * Code to format a trace of events and internal state for debugging, * * and code to log debugging, warning, and informational messages. * * * * * *************************************************************************/ /**************************************************************************** RSVPD -- ReSerVation Protocol Daemon USC Information Sciences Institute Marina del Rey, California Original Version: Shai Herzog, 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. ********************************************************************/ #include "rsvp_daemon.h" #ifdef __STDC__ #include #include #else #include #endif /* * External declarations */ char *fmt_tspec(SENDER_TSPEC *); char *fmt_filtspec(FILTER_SPEC *); char *fmt_flowspec(FLOWSPEC *); char *fmt_adspec(ADSPEC *); void fmt_object(); char *strtcpy(); char *fmt_style(style_t); char *cnv_flags(char *, u_char); char *bm_expand(); int debug_filter; int debug_filter_num; extern net_addr debug_filters[]; extern char * RSVPstat_msg[]; /* * Forward declarations */ void print_senders(), print_flwds(); void dump_PSB(PSB *), dump_RSB(RSB *); void dump_session_state(Session *); void dump_filtstar(FiltSpecStar *, FLOWSPEC *); void dump_rsvp_stats(); int bmp_equ(bitmap *, bitmap *); int bmp_zero(bitmap *); void bmp_rst(bitmap *); void bmp_set(bitmap *, int); void bmp_clr(bitmap *, int); int bmp_tst(bitmap *, int); bitmap * bmp_shift(bitmap *, bitmap *, int); bitmap * bmp_create(u_long, bitmap *); bitmap * bmp_convert(rsrr_bmp *, bitmap *); /* * Exported variables. */ char s1[19]; /* buffers to hold the string representations */ char s2[19]; /* of IP addresses, to be passed to inet_fmt() */ char s3[19]; /* or inet_fmts(). */ char s4[19]; char s[2*RSRR_MAX_VIFS_V2]; /* char buff for bm_expand() */ char *r_type[] = {"RSVP_Unknown", "PATH", "RESV", "PATH_ERR", "RESV_ERR", "PTEAR", "RTEAR","CONFIRM", "", "DREQ", "DREP"}; /* * dump_ds(): This function is called to log and possibly multicast the * internal state. */ void dump_ds(int force) { Session *dst; static int last_print = 0; int i; /* * Don't print state too often, wait at least DUMP_DS_TIMO, unless a * force option is specified. */ if (!force && (abs((int) (time_now - last_print)) < DUMP_DS_TIMO)) return; /* If flag set, multicast the state to remote display programs */ if (m_debug & DEBUG_MCAST_STATE) { mcast_rsvp_state(); last_print = time_now; } /* If state dump flag bit not set, exit now. */ if (!IsDebug(DEBUG_DS_DUMP)) return; last_print = time_now; log(LOG_DEBUG, 0, "\n%12s >>>>>>>>>> Internal STATE: <<<<<<< %u <<<<<<\n", rsvp_timestamp(),time_now); /* Dump each session */ for (i = 0; i < SESS_HASH_SIZE; i++) for (dst = session_hash[i]; dst; dst = dst->d_next) dump_session_state(dst); return; } void dump_session_state(Session *dst) { PSB *snd; RSB *rp; int i; net_if inf; fmt_object(dst->d_session, 0); if (debug_filter) { for (i = 0; i < debug_filter_num; i++) { NET_SET_IF_PHY(&inf,debug_filters[i],0); if (session_if_eq(dst->d_session,&inf)) break; } if (i == debug_filter_num) return; } log(LOG_DEBUG, 0, " Refresh intervals: Path R= %d Resv R=%d\n", dst->d_Rtimop, dst->d_Rtimor); for (snd = dst->d_PSB_list; snd != NULL; snd = snd->ps_next) dump_PSB(snd); for (rp = dst->d_RSB_list; rp != NULL; rp = rp->rs_next) dump_RSB(rp); for (i = 0; i < if_num; i++) LL_BugDump(i, dst); log(LOG_DEBUG, 0, " ------------- End of Dest state dump ---------------\n\n"); } void dump_PSB(PSB *sp) { Fobject *fop; log(LOG_DEBUG, 0, " Sender: %s PHOP: <%s> TTD: %d\n", fmt_filtspec(sp->ps_templ), (IsHopAPI(&sp->ps_phop)) ? "(API)" : hop_print(&sp->ps_phop), sp->ps_ttd); log(LOG_DEBUG, 0, " In_if %d=>%s Outlist %s flags %s ip_ttl %d\n", sp->ps_in_if, IF_NAME(sp->ps_in_if), bm_expand(&(sp->ps_outif_list), s), cnv_flags("SRPULE?N", sp->ps_flags), sp->ps_ip_ttl); log(LOG_DEBUG, 0, " %s", fmt_tspec(sp->ps_tspec)); if (sp->ps_adspec) log(LOG_DEBUG, 0, " %s\n", fmt_adspec(sp->ps_adspec)); else log(LOG_DEBUG, 0, "\n"); for (fop = sp->ps_UnkObjList; fop; fop= fop->Fobj_next) fmt_object(&fop->Fobj_objhdr, 0); if (sp->ps_BSB_Qb) log(LOG_DEBUG, 0, " Blockade: Tb= %d Qb= %s\n", sp->ps_BSB_Tb, fmt_flowspec(sp->ps_BSB_Qb)); } void dump_RSB(RSB *rp) { char temp[256]; Fobject *fop; sprintf(temp, "Iface %d=>%s Nhop <%s>", rp->rs_OIf, IF_NAME(rp->rs_OIf), hop_print(&rp->rs_nhop)); log(LOG_DEBUG, 0, " %s Resv: %s TTD %d\n", fmt_style(rp->rs_style), temp, rp->rs_ttd); if (rp->rs_scope) fmt_object(rp->rs_scope, RSVP_RESV); if (rp->rs_confirm) fmt_object(rp->rs_confirm, RSVP_RESV); else if (rp->rs_scope) log(LOG_DEBUG, 0, "\n"); for (fop = rp->rs_UnkObjList; fop; fop= fop->Fobj_next) fmt_object(&fop->Fobj_objhdr, 0); dump_filtstar(rp->rs_filtstar, rp->rs_spec); } void dump_filtstar(FiltSpecStar *fstp, FLOWSPEC *specp) { int i; if (fstp->fst_count == 0) { log(LOG_DEBUG, 0, " Flowspec %s\n", fmt_flowspec(specp)); return; } for (i=0; i < fstp->fst_count; i++) { if (fstp->fst_Filtp(i) == NULL) continue; if (i) log(LOG_DEBUG, 0, " %s\n", fmt_filtspec(fstp->fst_Filtp(i))); else log(LOG_DEBUG, 0, " Filter %s Flowspec %s\n", fmt_filtspec(fstp->fst_filtp0), fmt_flowspec(specp)); } } /* * print_rsvp(): Log a dump of an RSVP message. */ void print_rsvp(struct packet *pkt) { packet_map *mapp = pkt->pkt_map; enum byteorder old_order = pkt->pkt_order; SCOPE *scp; DIAG_RESPONSE *d_resp ; Fobject *fop; int i; net_if inf; ntoh_packet(pkt); /* It would be nicer to make copy if necessary to convert byte order, * avoid converting back at end. */ if (!(mapp->rsvp_session)) { log (LOG_DEBUG, 0, "Missing session obj\n"); return; } if (debug_filter) { for (i = 0; i < debug_filter_num; i++) { NET_SET_IF_PHY(&inf,debug_filters[i],0); if (session_if_eq(pkt->rsvp_sess,&inf)) break; } if (i == debug_filter_num) return; } if (mapp->rsvp_integrity) fmt_object(mapp->rsvp_integrity, 0); log(LOG_DEBUG, 0, " %-4s:", r_type[mapp->rsvp_msgtype]); fmt_object(mapp->rsvp_session, 0); switch (mapp->rsvp_msgtype) { case (RSVP_PATH): case (RSVP_PATH_TEAR): fmt_object(mapp->rsvp_timev, RSVP_PATH); fmt_object(mapp->rsvp_hop, RSVP_PATH); print_senders(pkt); break; case (RSVP_RESV): case (RSVP_RESV_TEAR): fmt_object(mapp->rsvp_timev, RSVP_RESV); fmt_object(mapp->rsvp_hop, RSVP_RESV); if ((scp = mapp->rsvp_scope_list)) fmt_object(scp, RSVP_RESV); if (mapp->rsvp_confirm) fmt_object(mapp->rsvp_confirm, RSVP_RESV); print_flwds(pkt); log(LOG_DEBUG, 0, "\n"); break; case (RSVP_PATH_ERR): log(LOG_DEBUG, 0, "\n"); fmt_object(mapp->rsvp_errspec, RSVP_RESV_ERR); print_senders(pkt); break; case (RSVP_RESV_ERR): log(LOG_DEBUG, 0, "\n"); fmt_object(mapp->rsvp_errspec, RSVP_RESV_ERR); print_flwds(pkt); break; case (RSVP_CONFIRM): log(LOG_DEBUG, 0, "\n"); fmt_object(mapp->rsvp_confirm, RSVP_CONFIRM); fmt_object(mapp->rsvp_errspec, RSVP_RESV_ERR); print_flwds(pkt); break; case (RSVP_DREQ): fmt_object(mapp->rsvp_diag, RSVP_DREQ); if (mapp->rsvp_diag_response) { d_resp = mapp->rsvp_diag_response ; log(LOG_DEBUG, 0, " Responses: %d\n",mapp->rsvp_resplist); for(i=0;irsvp_resplist;i++) { fmt_object(d_resp, RSVP_DREQ); (char *)d_resp += Obj_Length(d_resp); } } if(mapp->rsvp_route) { log(LOG_DEBUG, 0, " Route: \n"); fmt_object(mapp->rsvp_route,RSVP_DREQ); } break; case (RSVP_DREP): fmt_object(mapp->rsvp_diag, RSVP_DREP); if (mapp->rsvp_diag_response) { d_resp = mapp->rsvp_diag_response ; log(LOG_DEBUG, 0, " Responses: %d\n",mapp->rsvp_resplist); for(i=0;irsvp_resplist;i++) { fmt_object(d_resp, RSVP_DREP); (char *)d_resp += Obj_Length(d_resp); } } if(mapp->rsvp_route) { log(LOG_DEBUG, 0, " Route: \n"); fmt_object(mapp->rsvp_route,RSVP_DREP); } break; default: log(LOG_DEBUG, 0, "unknown rsvp packet type: %d\n", RSVP_TYPE_OF(pkt->pkt_data)); break; } for (fop = mapp->rsvp_UnkObjList; fop; fop = fop->Fobj_next) fmt_object(&fop->Fobj_objhdr, 0); /**** log(LOG_DEBUG, 0, " --------------- end packet parse ---------------------------\n\n" ); ****/ log(LOG_DEBUG, 0, "\n"); if (old_order != BO_HOST) { hton_packet(pkt); } } void print_senders(struct packet *pkt) { SenderDesc *sdscp = SenderDesc_of(pkt); log(LOG_DEBUG, 0, "\t%s %s\n", fmt_filtspec(sdscp->rsvp_stempl), fmt_tspec(sdscp->rsvp_stspec)); if (sdscp->rsvp_adspec) log(LOG_DEBUG, 0, "\t\t%s", fmt_adspec(sdscp->rsvp_adspec)); } void print_flwds(struct packet *pkt) { int i; style_t style = Style(pkt); FlowDesc *flwdp = FlowDesc_of(pkt, 0); switch (style) { case STYLE_WF: log(LOG_DEBUG, 0, " WF %s\n", fmt_flowspec(flwdp->rsvp_specp)); break; case STYLE_FF: for (i = 0; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); log(LOG_DEBUG, 0, " FF %s %s\n", fmt_filtspec(flwdp->rsvp_filtp), fmt_flowspec(flwdp->rsvp_specp)); } break; case STYLE_SE: log(LOG_DEBUG, 0, " SE %s %s\n", fmt_filtspec(flwdp->rsvp_filtp), fmt_flowspec(flwdp->rsvp_specp)); for (i = 1; i < pkt->rsvp_nflwd; i++) { flwdp = FlowDesc_of(pkt, i); log(LOG_DEBUG, 0, " %s\n", fmt_filtspec(flwdp->rsvp_filtp)); } break; default: log(LOG_DEBUG, 0, " ??Style= %d\n", style); break; } } char * rsvp_timestamp(void) { struct timeval tv; struct tm tmv; static char buff[16]; gettimeofday(&tv, NULL); memcpy(&tmv, localtime((time_t *) &tv.tv_sec), sizeof(struct tm)); sprintf(buff, "%02d:%02d:%02d.%03d", tmv.tm_hour, tmv.tm_min, tmv.tm_sec, (int) tv.tv_usec/1000); return(buff); } /* log(): write to the log. * * Write all messages of severity <= l_severity into log file; if * not in daemon mode, write them onto console (stderr) as well. */ void log(int severity, int syserr, const char *format, ...) { char *a_time = rsvp_timestamp(); va_list ap; assert(severity == LOG_ALWAYS || severity >= LOG_ERR); va_start(ap, format); if (severity <= l_debug) { if (severity < LOG_DEBUG) fprintf(stderr, "%s ", a_time); vfprintf(stderr, format, ap); } if (severity < LOG_DEBUG) fprintf(logfp, "%s ", a_time); vfprintf(logfp, format, ap); if (syserr == 0) { /* Do nothing for now */ } else if (syserr < sys_nerr) { if (severity <= l_debug) fprintf(stderr, ": %s\n", sys_errlist[syserr]); fprintf(logfp, ": %s\n", sys_errlist[syserr]); } else { if (severity <= l_debug) fprintf(stderr, ": errno %d\n", syserr); fprintf(logfp, ": errno %d\n", syserr); } if (ftell(logfp) > MAX_LOG_SIZE) reset_log(0); } static char *Log_Event_Types[] = {"Rcv UDP", "Rcv Raw", "Rcv API", "Snd UDP", "Snd Raw", "Snd U+R", "API Reg", "API Rsv", "API Cls", "API Upc", "APIdbug", "APIstat", "AddFlow", "ModFlow", "DelFlow", "AddFilt", "DelFilt", "Ignore", "Gen Err" }; /* log_event(): write event entry to log and to stderr if logging * severity (l_debug) is LOG_DEBUG. */ void log_event(int evtype, char *type, SESSION *destp, const char *format, ...) { va_list ap; char *a_time = rsvp_timestamp(); char *sess; if (l_debug < LOG_DEBUG) /* (Extra test: call has already tested */ return; /* l_debug >= LOG_DEBUG, in IsDebug macro.*/ va_start(ap, format); if (!destp) return; if (Log_Event_Cause == NULL) Log_Event_Cause = " "; sess = session_print(destp); fprintf(stderr, "%12s|%s %-8.8s %-9.9s %s ", a_time, Log_Event_Cause, Log_Event_Types[evtype], type, sess); vfprintf(stderr, format, ap); fprintf(logfp, "%12s|%s %-8.8s %-9.9s %-24s ", a_time, Log_Event_Cause, Log_Event_Types[evtype], type, sess); vfprintf(logfp, format, ap); Log_Event_Cause = NULL; if (ftell(logfp) > MAX_LOG_SIZE) reset_log(0); } /* Print out statistics */ #define MAX_RSVP_STAT (sizeof(RSVPstat)/sizeof(u_int32_t)) void dump_rsvp_stats() { int i, j; union { RSVPstat str; u_int32_t vec[MAX_RSVP_STAT]; } sum_stat; memset(sum_stat.vec, 0, sizeof(sum_stat)); for (i=0; i 0) { if (hcnt == 0) fprintf(fp, "x%2.2lx: ", (unsigned long)(cp-p)); if ((hcnt%4) == 0) fprintf(fp, " "); fprintf(fp, "%2.2x", (0xff&*cp++)) ; len--; hcnt++; if (hcnt >= 16 || len == 0) { fprintf(fp, "\n"); hcnt = 0; } } } /* String copy routine that truncates if necessary to n-1 characters, * but always null-terminates. */ char *strtcpy(s1, s2, n) char *s1, *s2; int n; { strncpy(s1, s2, n); *(s1+n-1) = '\0'; return(s1); } /* * Convert an IP address in u_long (network) format into a printable string. * Taken from mrouted code. */ char *inet_fmt(addr, s) u_int32_t addr; char *s; { register u_char *a; a = (u_char *)&addr; sprintf(s, "%u.%u.%u.%u", a[0], a[1], a[2], a[3]); return (s); } /* * Format bitmask into string s */ char * bm_expand(bm,s) bitmap *bm; char *s; { int i,first=1; char t[4]; memset(s,0,sizeof(*s)); sprintf(s,"<"); for (i=0; i<(NBBY * sizeof(*bm)); i++) { if (bmp_tst(bm,i)) { if (first) { sprintf(t,"%d",i); strcat(s,t); first = 0; } else { sprintf(t,",%d",i); strcat(s,t); } } } strcat(s,">"); return s; } /* * test if two bitmaps are equal */ int bmp_equ(bitmap *x, bitmap *y) { int i; for (i = 0; i < BMP_SIZE; i++) { if (x->bmp[i] != y->bmp[i]) return 0; } return 1; } /* * test if this bitmap is zero */ int bmp_zero(bitmap *x) { int i; for (i = 0; i < BMP_SIZE; i++) { if (x->bmp[i] != 0) return 0; } return 1; } /* * reset this bitmap to all zero */ void bmp_rst(bitmap *x) { int i; for (i = 0; i < BMP_SIZE; i++) { x->bmp[i] = 0; } return; } /* * set specific bit in this bitmap */ void bmp_set(bitmap *x, int n) { int i = (n)/NBBY; int j = (n)%NBBY; x->bmp[i] |= (1 << j); return; } /* * clear specific bit in this bitmap */ void bmp_clr(bitmap *x, int n) { int i = (n)/NBBY; int j = (n)%NBBY; x->bmp[i] &= ~(1 << j); return; } /* * test if specific bit in this bitmap is set */ int bmp_tst(bitmap *x, int n) { int i = (n)/NBBY; int j = (n)%NBBY; return ((x->bmp[i]) & (1 << j)); } /* * shift this bitmap left to some number of bits * (to be used for RSRR) */ bitmap * bmp_shift(bitmap *x, bitmap *y, int n) { u_long i; bmp_rst(y); for (i = 0; i < BMP_SIZE*NBBY; i++) { if (bmp_tst(x, i)) { if ((i+n) < (BMP_SIZE*NBBY)) bmp_set(y,i+n); } } return y; } /* * create a bitmap from a unsigned long integer * (to be used by RSRR) */ bitmap * bmp_create(u_long x, bitmap *y) { u_long i; bmp_rst(y); for (i = 0; i < sizeof(u_long)*NBBY; i++) { if (BIT_TST(x, i)) { bmp_set(y,i); } } return y; } /* * convert from a larger rsrr_bmp to smaller bitmap * (usually rsrr_bmp has 256 bits, and bitmap has only 64 bits) */ bitmap * bmp_convert(rsrr_bmp *x, bitmap *y) { int i; bmp_rst(y); for (i=0; i<(RSRR_MAX_VIFS_V2/NBBY); i++) { if (i < BMP_SIZE) { y->bmp[i] = x->bm[i]; } else { if (x->bm[i] !=0) { log(LOG_DEBUG,0,"Please increase the BMP_SIZE"); break; } } } return y; }