/* * @(#) $Id: rsvp_print.c,v 4.18 1998/08/17 20:52:35 mtalwar Exp $ */ /**************************************************************************** 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. ********************************************************************/ /* * rsvp_print.c * * Common routine for formatting and printing/logging an RSVP packet. */ #include #include #include #include #include #include #include #ifdef RSVP_TCPDUMP #define _MACHINE_ENDIAN_H_ 1 #endif #include "rsvp_socks.h" #include "rsvp_trans.h" #include "rsvp_types.h" #include "rsvp.h" #include "rsvp_objs.h" #ifdef RSVP_TCPDUMP /* tcpdump */ #include "interface.h" #include "addrtoname.h" #define OUT0(x) printf((x)) #define OUT1(x, y) printf((x), (y)) #define OUT2(x, y, z) printf((x), (y), (z)) #define OUT3(w, x, y, z) printf((w), (x), (y), (z)) #define OUT4(w, x, y, z, a) printf((w), (x), (y), (z), (a)) #else #define OUT0(x) log(LOG_DEBUG, 0, (x)) #define OUT1(x, y) log(LOG_DEBUG, 0, (x), (y)) #define OUT2(x, y, z) log(LOG_DEBUG, 0, (x), (y), (z)) #define OUT3(w, x, y, z) log(LOG_DEBUG, 0, (w), (x), (y), (z)) #define OUT4(w, x, y, z, a) log(LOG_DEBUG, 0, (w), (x), (y), (z), (a)) void log(int, int, const char *, ...); #endif #define Next_Object(x) (Object_header *)((char *) (x) + Obj_Length(x)) char *fmt_filtspec(); extern char *fmt_flowspec(); extern char *fmt_tspec(); extern char *fmt_adspec(); void fmt_object(Object_header *, int type); char *fmt_style(style_t); char *cnv_flags(char *, u_char); static int objcol; /* Not sure best way to format sender descriptor lists and flow * descriptor lists. For now, simply put each two objects into * a single line. */ #ifdef RSVP_TCPDUMP /* tcpdump */ char *Type_name[] = {"", "PATH ", "RESV ", "PATH-ERR", "RESV-ERR", "PATH-TEAR", "RESV-TEAR", "", "", "DREQ", "DREP"}; #else extern char *Type_name[]; #endif char *style_names[] = {"?", "WF", "FF", "SE"}; style_t style_optvs[] = {0, STYLE_WF, STYLE_FF, STYLE_SE}; /* * Format and print RSVP packet */ void rsvp_print_pkt(hdrp, length) common_header *hdrp; int length; /* Actual length */ { Object_header *objp; char *end_of_data = (char *) hdrp + length; int flags = RSVP_FLAGS_OF(hdrp); NTOHS(hdrp->rsvp_length); if (hdrp->rsvp_type > RSVP_MAX_MSGTYPE) { OUT1(" ??Type= %d\n", hdrp->rsvp_type); return; } OUT1(" %s", Type_name[hdrp->rsvp_type]); if (flags) OUT1(" %x", flags); objp = (Object_header *) (hdrp + 1); objcol = 0; while (objp < (Object_header *)end_of_data) { if ((Obj_Length(objp)&3) || Obj_Length(objp)<4 || (char *)Next_Object(objp) > end_of_data) { if (length < hdrp->rsvp_length) OUT0(" ... Truncated by tcpdump\n"); else OUT0(" ... Bad object format\n"); return; } fmt_object(objp, hdrp->rsvp_type); objp = Next_Object(objp); } if (length < hdrp->rsvp_length) OUT0(" ... Truncated by tcpdump\n"); else if (length > hdrp->rsvp_length) OUT0(" ... ?? Too long\n"); return; } void fmt_object(Object_header *op, int type) { struct in_addr *in_iface, *out_iface, *pre_iface; int n, i, af, size; style_t style; char *flagstr,*cp; struct in_addr *lasthop, *resp_addr ; DIAG_RESPONSE *dresp ; DIAGNOSTIC *dreq ; ROUTE *droute; char *end_of_dresp; u_int32_t *lp; if(!op) return; switch (Obj_Class(op)) { case class_NULL: OUT0(" (Null Obj)"); break; case class_DIAGNOSTIC: dreq = (DIAGNOSTIC *)op; lasthop = &dreq->diag_laddr; resp_addr = &dreq->diag_raddr; OUT1("Mesg ID: %u\n", dreq->diag_msgID); OUT1("\tTowards: %s",fmt_filtspec(&dreq->diag_sfiltp)); OUT1(" last_hop: %s", net_inaddr_host((char *) lasthop,AF_INET)); OUT2(" resp_to: %s/%d\n", net_inaddr_host((char *) resp_addr,AF_INET),ntohs(dreq->diag_rport)); OUT1("\tmax_hops %u",dreq->diag_maxhops); OUT1(" hop_count %u",dreq->diag_hopcount); OUT1(" mcast_TTL %u",dreq->diag_ttl); OUT2(" reply_mode:[H %u, F %u]\n",DIAG_HBIT(dreq),DIAG_MFBIT(dreq)); OUT1("\tpath MTU %d",dreq->diag_pMTU); OUT1(" frag_off %d\n",dreq->diag_frag_off); break; case class_DIAG_RESPONSE: dresp = (DIAG_RESPONSE *)op; OUT1("\tDREQ arr time %lu", ((DIAG_RESPONSE *)op)-> resp_arrtime); OUT1(" DTTL %d",((DIAG_RESPONSE *)op)->resp_DTTL); OUT1(" R-Error %d,", DIAG_RESPONSE_RERROR((DIAG_RESPONSE *)op)); OUT1(" K=%d",DIAG_RESPONSE_K((DIAG_RESPONSE *)op)); if (DIAG_RESPONSE_MFLAG((DIAG_RESPONSE *)op)) OUT0(", M\n"); else OUT0("\n"); in_iface =&((DIAG_RESPONSE *)op)->resp_in_addr; out_iface =&((DIAG_RESPONSE *)op)->resp_out_addr; pre_iface =&((DIAG_RESPONSE *)op)->resp_pre_addr; OUT1("\tIn_if: %s", net_inaddr_host((char *) in_iface,AF_INET)); OUT1(" Out_if: %s", net_inaddr_host((char *) out_iface,AF_INET)); OUT1(" Phop: %s\n",net_inaddr_host((char *) pre_iface,AF_INET)); /* We expect a strict order here * TSPEC , FLOWSPEC , {FILTER_SPEC, FILTER_SPEC,..} */ if (Obj_Length(dresp) > DRESP_BASIC_SIZE) { /*tspec = &((DIAG_RESPONSE *)op)->resp_tspec; */ op = (Object_header *)((char *)dresp + DRESP_BASIC_SIZE); fmt_object(op, 0); op = Next_Object(op); } if (Obj_Length(dresp) > DRESP_BASIC_SIZE + sizeof(SENDER_TSPEC)) { /*flowspec = &((DIAG_RESPONSE *)op)->resp_rflow;*/ fmt_object(op, 0); op = Next_Object(op); } if (Obj_Length(dresp) > DRESP_BASIC_SIZE + sizeof(SENDER_TSPEC) + sizeof(FLOWSPEC)) { end_of_dresp = ((char *)dresp + Obj_Length(dresp)); while ((char *)op < end_of_dresp) { /*filterspec = &((DIAG_RESPONSE *)op)->resp_filtp;*/ fmt_object((Object_header *)op, 0); op = Next_Object(op); } } OUT0("\n"); break; case class_ROUTE: droute = (ROUTE *)op; if (Obj_CType(op) != ctype_ROUTE_ipv4) { OUT1("Unknown ROUTE ctype= %d\n", Obj_CType(op)); break; } OUT0("\t"); for (i=0; i <= droute->R_pointer_ipv4; i++) OUT1("%s ", net_inaddr_host((char *) &route(droute,i),AF_INET)); OUT0("\n"); break; case class_SESSION: switch(Obj_CType((SESSION *) op)) { case ctype_SESSION_ipv4: cp = ""; break; case ctype_SESSION_ipv4GPI: cp = "GPI"; break; #ifdef USE_IPV6 case ctype_SESSION_ipv6: cp = "v6"; break; case ctype_SESSION_ipv6GPI: cp = "GPI6"; break; #endif /* USE_IPV6 */ case ctype_LSP_TUNNEL_IPv4: cp = "LSP Tunnel"; break; default: cp = ""; break; } OUT2(" Sess: %s%s ", session_print((SESSION *) op),cp); break; OUT0(cnv_flags("??????P", session_get_flags((SESSION *) op))); /* P => Police */ break; case class_SESSION_GROUP: OUT0(" Sess_Grp!!"); break; case class_RSVP_HOP: OUT2(" %s: <%s>\n", (type&1)?" PHOP":" NHOP", hop_print((RSVP_HOP *) op)); break; case class_INTEGRITY: lp = NULL; switch (Obj_CType(op)) { case ctype_INTEGRITY_MD5: OUT0(" Intgrty{Kid, Seq#, Digest.\n"); lp = (u_int32_t *) ((INTEGRITY *)op)->intgr_keyid; for (i = 0; i < KEYID_LENG/4; i++) OUT1(" %8.8x", *(lp++)); OUT0("\n"); lp = ((INTEGRITY *)op)->intgr_seqno; OUT2(" %u-%u\n", lp[0], lp[1]); lp = (u_int32_t *) ((INTEGRITY *)op)->intgr_digest; for (i = 0; i < MD5_LENG/4; i++) OUT1(" %8.8x", *(lp++)); OUT0("}\n"); break; default: OUT1("Unknown INTEGRITY ctype= %d\n", Obj_CType(op)); break; } break; case class_TIME_VALUES: if (Obj_CType(op) != ctype_TIME_VALUES_CTYPE) { OUT1("Unknown TIME_VALUES ctype= %d\n", Obj_CType(op)); break; } OUT1(" R: %d", ((TIME_VALUES *)op)->timev_R); break; case class_ERROR_SPEC: switch (Obj_CType(op)) { case ctype_ERROR_SPEC_ipv4: OUT2("\tERR#: %d Value: %d", ((ERROR_SPEC *)op)->errspec4_code, ((ERROR_SPEC *)op)->errspec4_value); flagstr = cnv_flags("??????NI", ((ERROR_SPEC *)op)->errspec4_flags); OUT2("\tNode: %s Flags: %s\n", net_inaddr_host((char *) &((ERROR_SPEC *)op)->errspec4_enode, AF_INET),flagstr); break; #ifdef USE_IPV6 case ctype_ERROR_SPEC_ipv6: OUT2("\tERR#: %d Value: %d", ((ERROR_SPEC *)op)->errspec6_code, ((ERROR_SPEC *)op)->errspec6_value); flagstr = cnv_flags("??????NI", ((ERROR_SPEC *)op)->errspec6_flags); OUT2("\tNode: %s Flags: %s\n", net_inaddr_host((char *) &((ERROR_SPEC *)op)->errspec6_enode, AF_INET6),flagstr); break; #endif /* USE_IPV6 */ default: OUT1("Unknown ERROR_SPEC ctype= %d\n", Obj_CType(op)); break; } break; case class_CONFIRM: switch (Obj_CType(op)) { case ctype_CONFIRM_ipv4: OUT1(" CONFIRMto: %s\n",net_inaddr_host( (char *) &((CONFIRM *)op)->conf4_addr, AF_INET)); break; #ifdef USE_IPV6 case ctype_CONFIRM_ipv6: OUT1(" CONFIRMto: %s\n",net_inaddr_host( (char *) &((CONFIRM *)op)->conf6_addr, AF_INET6)); break; #endif /* USE_IPV6 */ default: OUT1("Unknown CONFIRM ctype= %d\n", Obj_CType(op)); break; } break; case class_SCOPE: switch (Obj_CType(op)) { case ctype_SCOPE_list_ipv4: cp = (char *) ((SCOPE *)op)->scope4_addr; size = sizeof(struct in_addr); af = AF_INET; break; #ifdef USE_IPV6 case ctype_SCOPE_list_ipv6: cp = (char *) ((SCOPE *)op)->scope6_addr; size = sizeof(struct in6_addr); af = AF_INET6; break; #endif /* USE_IPV6 */ default: OUT1("Unknown SCOPE ctype= %d\n", Obj_CType(op)); break; } n = (Obj_Length(op) - sizeof(Object_header)) / size; OUT0("\tScope={"); for (i = 0; i < n; i++) { if (i) OUT0(" "); OUT1("%s", net_inaddr_host(cp,af)); if (((i+1)|3) == 0) OUT0("\n\t\t"); cp += size; } OUT0("}"); break; case class_STYLE: if (Obj_CType(op) != ctype_STYLE_CTYPE) { OUT1("\tSTYLE(??%d)\n", Obj_CType(op)); break; } style = ((STYLE *)op)->style_word; OUT2("\t%s %x", fmt_style(style), (u_int32_t) style); break; case class_FLOWSPEC: if (objcol++ >= 2) { objcol = 0; OUT0("\n"); } OUT1("\t%s", fmt_flowspec((FLOWSPEC *)op) ); break; case class_SENDER_TEMPLATE: case class_FILTER_SPEC: if (objcol++ >= 2) { objcol = 0; OUT0("\n"); } OUT1("\t{%s}", fmt_filtspec((FILTER_SPEC *)op) ); break; case class_SENDER_TSPEC: if (objcol++ >= 2) { objcol = 0; OUT0("\n"); } OUT1("\t%s", fmt_tspec((FLOWSPEC *)op) ); break; case class_ADSPEC: OUT1(" %s", fmt_adspec((ADSPEC *)op)); break; case class_POLICY_DATA: default: OUT3("\tUnkn Object class %d ctype %d len %d\n", Obj_Class(op), Obj_CType(op), Obj_Length(op)); break; } } /* * Format RSVP filter spec and return pointer to string in static area. */ char * fmt_filtspec(filtp) FILTER_SPEC *filtp; { static char buff[256]; if (!filtp) return "(null)"; buff[0] = '\0'; switch (Obj_CType(filtp)) { case ctype_FILTER_SPEC_ipv4: if (IN_ARE_ADDR_EQUAL(&filtp->filt4_srcaddr,&inaddr_any)) strcpy(buff,"(*)"); else sprintf(buff, "%s/%hu",net_inaddr_host((char *) &filtp->filt4_srcaddr,AF_INET), ntoh16(filtp->filt4_srcport)); break; case ctype_FILTER_SPEC_ipv4GPI: if (IN_ARE_ADDR_EQUAL(&filtp->filtgpi4_srcaddr,&inaddr_any)) strcpy(buff,"(*)"); else sprintf(buff, "%s%d",net_inaddr_host((char *) &filtp->filtgpi4_srcaddr,AF_INET), filtp->filtgpi4_srcgpi); break; #ifdef USE_IPV6 case ctype_FILTER_SPEC_ipv6: if (IN6_ARE_ADDR_EQUAL(&filtp->filt6_srcaddr,&in6addr_any)) strcpy(buff,"(*)"); else sprintf(buff, "%s/%hu",net_inaddr_host((char *) &filtp->filt6_srcaddr,AF_INET6), ntoh16(filtp->filt6_srcport)); break; case ctype_FILTER_SPEC_ipv6GPI: if (IN6_ARE_ADDR_EQUAL(&filtp->filtgpi6_srcaddr,&in6addr_any)) strcpy(buff,"(*)"); else sprintf(buff, "%s%d",net_inaddr_host((char *) &filtp->filtgpi6_srcaddr,AF_INET6), filtp->filtgpi6_srcgpi); break; #endif /* USE_IPV6 */ case ctype_FILTER_SPEC_lsp_tunv4: sprintf(buff, "%s LSP ID %hu",net_inaddr_host((char *)&filtp->filtlsp4_saddr, AF_INET), ntoh16(filtp->filtlsp4_id)); break; default: sprintf(buff, "Filtspec CType %d ??", Obj_CType(filtp)); break; } return(buff); } char * fmt_style(style_t style) { int i, n = sizeof(style_names)/sizeof(char *); for (i=1; i < n; i++) if (style_optvs[i] == style) break; return (i == n)? "?Sty" : style_names[i]; } static char out_flgs[80]; char * cnv_flags(char *equiv, u_char flgs) { int i, bit; char *p = out_flgs; *p++ = ' '; for (bit = 0x80, i = 0; bit; bit>>=1, i++) { if (flgs&bit) { out_flgs[0] = '*'; *p++ = equiv[i]; } } *p = '\0'; return(out_flgs); }