/* * @(#) $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] [-H] [-L] [-m]\n\ [-s] [-{U|T|p }] [-n]\n\ \n"; int main(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 -- 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 -- 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 -- max diag pkt size for trim/forward */ if ((diag_req.path_mtu = atoi(&argv[c][2])) <= 0) parse_fail = 1; break; case 'L': /* -L -- 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 -- session type is IPPROTO_ */ 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. */ int trace_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. */ int trace_input() { struct sockaddr_in from; net_addr src; net_if inf; int recv_len, rc; struct packet packet; packet_map map; recv_len = net_recv(&src, recv_buff, sizeof(recv_buff), &inf); if (recv_len < 0) { perror("recvfrom "); return (-1); } packet.pkt_order = BO_NET; packet.pkt_len = recv_len; packet.pkt_data = (common_header *) recv_buff; packet.pkt_offset = 0; packet.pkt_map = (packet_map *) ↦ packet.pkt_flags = PKTFLG_USE_UDP; packet.pkt_ttl = packet.pkt_data->rsvp_snd_TTL; /* * Call our common routine to do initial processing of RSVP packet. */ rc = rsvp_pkt_map(&packet); if (rc != PKT_OK) { printf("\nParse error in packet received from %s\n", iptoname(&from.sin_addr)); return (0); } switch (map.rsvp_msgtype) { case RSVP_DREP: return(trace_accept_reply(&packet,&src)); default: return (0); } } /* next_wait() : * * Starting from a given timeval and "wait" time in seconds, * calulate a wait timeval. The given timeval is typically some * time of an event like a sent or received packet . * * returns 1 for no wait time, zero otherwise. */ int next_wait(struct timeval *tfrom, int wait,struct timeval *twait) { struct timeval t_now; struct timezone tz; if (gettimeofday(&t_now,&tz) < 0) { perror("get time error "); exit(-1); } twait->tv_sec = (tfrom->tv_sec + wait) - t_now.tv_sec ; twait->tv_usec = tfrom->tv_usec - t_now.tv_usec; if(twait->tv_usec < 0) { twait->tv_usec += 1000000; twait->tv_sec--; } if (twait->tv_sec < 0) { twait->tv_sec = twait->tv_usec = 0; return 1; } return 0; } /* init_diag(): * * initialize diag request with valid defaults */ int init_diag() { /* the lite version of net_init returns a system selected * default address and port. We will receive the diagnostic * response here. */ net_init_udp_only(&diag_req.resp_to); Max_rsvp_msg = MAX_PKT ; /* allow conversion of addresses to names */ IP_NumOnly = 0; /* initialize the request info structure */ diag_req.path_mtu = DIAG_DEF_PATH_MTU; diag_req.max_hops = DIAG_DEF_MAX_HOPS; diag_req.H = DIAG_REPLY_DIRECT; diag_req.status = DIAG_NONE_RECVD; diag_req.rcount = 0; diag_req.curr_id = 0; diag_req.timeout = DIAG_DEF_TIMEOUT; /* Initialize the diag_req net_addr structures * the DREQ is sent to the Last_hop rsvp router's Pu port */ NET_SET_ADDR3_UDP_IPv4(&diag_req.last_hop, NET_GET_ADDR_UDP_IPv4(&diag_req.resp_to).sin_addr, hton16(RSVP_ENCAP_PORT)); NET_SET_ADDR3_UDP_IPv4(&diag_req.sender,inaddr_any,0); memset(&diag_req.rsvp_dsess,0,sizeof(SESSION_ipv4)); diag_req.rsvp_dsess.sess_protid = IPPROTO_UDP ; return 0; } /* Lifted directly from rsvp_api.c : * Macro used in api_prepare_xxxx to add an object to API packet and * to the map of the packet. The map address is 'var'; the object * has class (typedef) 'cls' and ctype (value) 'ctype'. * We use this macro while building the DREQ packet. */ #define New_Object(var, cls, ctype) \ Init_Object(objp, cls, ctype); \ var = (cls *) objp; \ objp = Next_Object(objp); /* trace_prepare(): * * Allocate new packet buffer and new map. * (Use max message size; could compute actual size) XXX??? * Prepare an rsvp diagnostic request (DREQ) in the packet_map */ int trace_prepare(struct packet *pkt) { common_header *hdrp; packet_map *mapp; int map_len = sizeof(packet_map); Object_header *objp; if ((hdrp = (common_header *) malloc(Max_rsvp_msg))==NULL || (mapp = (packet_map *) malloc(map_len))==NULL) { perror("Trace Prepare: "); return (-1); } /* offset may be set to 0. However in the future we may need this * so we harmlessly set it to this value */ pkt->pkt_offset = 0; pkt->pkt_map = mapp; pkt->pkt_data = hdrp; pkt->pkt_len = 0; pkt->pkt_flags = pkt->pkt_ttl = 0; pkt->pkt_order = BO_HOST; memset((char *)mapp, 0, sizeof(packet_map)); /* Initialize RSVP objects needed in the packet with requested information, * in host byte order. */ memset((char *)pkt->pkt_data, 0, sizeof(common_header)); pkt->pkt_len = sizeof(common_header); mapp->rsvp_msgtype = pkt->pkt_data->rsvp_type = RSVP_DREQ; pkt->pkt_map->rsvp_resplist = 0; objp = (Object_header *)(pkt->pkt_data + 1); /* Fill the DIAGNOSTIC Object */ New_Object(mapp->rsvp_diag, DIAGNOSTIC, DIAGNOSTIC_ipv4); /* ID of the DREQ packet is set to 0. * This is actually in send_diag_request, just before sending. */ pkt->pkt_map->rsvp_diag->diag_msgID = 0; /* If the Last_hop was not specified, then this machine becomes the last hop. * If this machine is not running rsvpd, the packet will be dropped. */ pkt->pkt_map->rsvp_diag->diag_laddr = NET_GET_ADDR_UDP_IPv4(&diag_req.last_hop).sin_addr; /* Setup sender/port and response/port */ Init_Object(&mapp->rsvp_diag->diag_rfiltp, FILTER_SPEC, FILTER_SPEC_ipv4); pkt->pkt_map->rsvp_diag->diag_raddr = NET_GET_ADDR_UDP_IPv4(&diag_req.resp_to).sin_addr; pkt->pkt_map->rsvp_diag->diag_rport = NET_GET_ADDR_UDP_IPv4(&diag_req.resp_to).sin_port; Init_Object(&mapp->rsvp_diag->diag_sfiltp, FILTER_SPEC, FILTER_SPEC_ipv4); pkt->pkt_map->rsvp_diag->diag_saddr = NET_GET_ADDR_UDP_IPv4(&diag_req.sender).sin_addr; pkt->pkt_map->rsvp_diag->diag_sport = NET_GET_ADDR_UDP_IPv4(&diag_req.sender).sin_port; /* Read reply mode and set H bit */ pkt->pkt_map->rsvp_diag->diag_replymode |= diag_req.H << 1; /* other diagnostic header settings */ pkt->pkt_map->rsvp_diag->diag_hopcount = 0; pkt->pkt_map->rsvp_diag->diag_maxhops = diag_req.max_hops; pkt->pkt_map->rsvp_diag->diag_pMTU = diag_req.path_mtu; pkt->pkt_map->rsvp_diag->diag_frag_off = 0; pkt->pkt_len += sizeof(DIAGNOSTIC); /* Fill the SESSION object */ New_Object(mapp->rsvp_session, SESSION, SESSION_ipv4); pkt->rsvp_sess->sess4_addr = diag_req.rsvp_dsess.sess_destaddr; pkt->rsvp_sess->sess4_port = diag_req.rsvp_dsess.sess_destport; pkt->rsvp_sess->sess4_prot = diag_req.rsvp_dsess.sess_protid; pkt->rsvp_sess->sess4_flgs = SESSFLG_E_Police; pkt->pkt_len += sizeof(SESSION); /* Finish up common header. */ pkt->pkt_data->rsvp_cksum = 0; pkt->pkt_data->rsvp_length = pkt->pkt_len = (char *)objp - (char *) pkt->pkt_data; pkt->pkt_data->rsvp_snd_TTL = RSVP_TTL_MAX; return (0); } /* trace_accept_reply() * * Process received diagnostic reply (DREP). * Set status flag to indicate to dispatcher that there * are more replies. * Printout results. */ int trace_accept_reply( struct packet *pkt, net_addr *fromp ) { struct timeval tm ; u_long t_const ; DIAG_RESPONSE *dresp; packet_map *mapp ; int c, dr_err; Object_header *op; char *end_of_dresp; mapp = pkt->pkt_map; /* If we already have some fragments pending, we ignore any * duplicate replies. */ if (diag_req.status == DIAG_SOME_RECVD && diag_req.curr_id != mapp->rsvp_diag->diag_msgID) return 1; /* Update the request status, so that the waiting routine gets * to know. Latch the message ID, if this is first reply ever. */ if (DIAG_MFBIT(mapp->rsvp_diag)) { if (diag_req.status != DIAG_SOME_RECVD) { diag_req.status = DIAG_SOME_RECVD; diag_req.curr_id = mapp->rsvp_diag->diag_msgID; } } else diag_req.status = DIAG_ALL_RECVD; printf("Reply from %s, %d hop(s), %d response(s)\n", iptoname(&(NET_GET_ADDR_UDP_IPv4(fromp).sin_addr)), mapp->rsvp_diag->diag_hopcount, mapp->rsvp_resplist); dresp = mapp->rsvp_diag_response; for (c = 0; c < mapp->rsvp_resplist; c++) { printf("\n%d) ",diag_req.rcount+c+1); /* this is to print the hop name along with * each response */ if(dresp->resp_in_addr.s_addr != INADDR_ANY) printf("%s ",iptoname(&dresp->resp_in_addr)); else if(dresp->resp_out_addr.s_addr != INADDR_ANY) printf("%s ",iptoname(&dresp->resp_out_addr)); else printf("%s ",iptoname(&(NET_GET_ADDR_UDP_IPv4(fromp).sin_addr))); dr_err = DIAG_RESPONSE_RERROR(dresp); if (dr_err) { switch(dr_err) { case RSVP_Erv_Diag_NOPATH : printf("PATH ?\n"); break ; case RSVP_Erv_Diag_MTUBIG : printf("MTU too big\n"); break ; case RSVP_Erv_Diag_ROUTEBIG : printf("ROUTE too big\n"); break ; default : printf("unknown err ??\n"); break ; } } if (!(dr_err & RSVP_Erv_Diag_NOPATH)) { t_const = get_time_constant(); tm.tv_sec = ((dresp->resp_arrtime >> 16) | t_const) - JAN_1970; tm.tv_usec = ((dresp->resp_arrtime & 0x0000FFFF) * 15625) >> 10; printf("[arr time: %s]\n",time_stamp(&tm)); if (dresp->resp_in_addr.s_addr != INADDR_ANY ) printf("[IN->%s", iptoname(&dresp->resp_in_addr)); else printf("[IN->local"); if (dresp->resp_out_addr.s_addr != INADDR_ANY) printf(", OI<-%s", iptoname(&dresp->resp_out_addr)); else printf(", OI<-local"); if (dresp->resp_pre_addr.s_addr != INADDR_ANY) { printf(", Phop->%s", iptoname(&dresp->resp_pre_addr)); } else printf(", Phop->N/A"); printf(", timer: %d, DTTL: %d]\n",dresp->resp_timeval, dresp->resp_DTTL); if (Obj_Length(dresp) > DRESP_BASIC_SIZE) { op = (Object_header *)((char *)dresp + DRESP_BASIC_SIZE); printf("%s",fmt_tspec((SENDER_TSPEC *)op)); op = Next_Object(op); } if (Obj_Length(dresp) > DRESP_BASIC_SIZE + sizeof(SENDER_TSPEC)) { printf(" %s",fmt_flowspec((FLOWSPEC *)op)); /*fmt_object(op, ctype_FLOWSPEC_Intserv0);*/ op = Next_Object(op); } if (Obj_Length(dresp) > DRESP_BASIC_SIZE + sizeof(SENDER_TSPEC) + sizeof(FILTER_SPEC)) { switch(dresp->resp_rstyle) { case STYLE_WF: printf(" WF"); break ; case STYLE_FF: printf(" FF"); break ; case STYLE_SE: printf(" SE"); break ; default : printf("Style ??"); } if (DIAG_RESPONSE_MFLAG(dresp)) printf(", M"); end_of_dresp = (char *)dresp + Obj_Length(dresp); while ((char *)op < end_of_dresp) { printf("\n{%s}",fmt_filtspec((FILTER_SPEC *)op)); /*fmt_object(op,ctype_FILTER_SPEC_ipv4);*/ op = Next_Object(op); } } (char *)dresp += Obj_Length(dresp); } printf("\n"); } diag_req.rcount += mapp->rsvp_resplist; return 0; } /* do_sendmsg() : * * Stub for sending generic rsvp packets without the extra machinery * of the same functions in rsvp_main.c (a lot of #ifdefs are needed!) * vif is a dummy parameter. */ int do_sendmsg( int vif, net_addr *to, net_addr *src, int flags, u_char ttl, u_char *data, int len) { return(net_send(to,src,data,len,NULL,ttl,FALSE)); } /* get_time_constant() : * * Used for getting the constant part of the ntp time stamp. * The diag object contains the 64k differential only. * We recompute the MSB 16bits of the original 32bit NTP * time stamp which will be constant for all time sync'ed hosts, * within the 64k second range. */ u_long get_time_constant() { struct timeval tm ; gettimeofday(&tm,0); tm.tv_sec += JAN_1970 ; return (tm.tv_sec & 0xFFFF0000) ; } char *time_stamp(struct timeval *tv) { struct tm tmv; static char buff[16]; 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); } u_long resolve_name(name) char *name; { net_addr addr; if (!net_addr_ascii(&addr,name)) return(INADDR_ANY); if (NET_GET_TYPE(&addr) != NET_ADDR_IPv4) return(INADDR_ANY); return(NET_GET_ADDR_IPv4(&addr).s_addr); }