From: Ted Lemon Date: Mon, 12 Feb 2001 19:42:21 +0000 (+0000) Subject: Add support for tracing ICMP messages. X-Git-Tag: V3-BETA-2-PATCH-18~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=53802791c53b5350a6ed7f07bc83ed3bb7582733;p=thirdparty%2Fdhcp.git Add support for tracing ICMP messages. --- diff --git a/common/icmp.c b/common/icmp.c index 6bc10edc7..0b06216eb 100644 --- a/common/icmp.c +++ b/common/icmp.c @@ -4,7 +4,7 @@ responses. */ /* - * Copyright (c) 1996-2000 Internet Software Consortium. + * Copyright (c) 1996-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -44,7 +44,7 @@ #ifndef lint static char copyright[] = -"$Id: icmp.c,v 1.25 2000/10/10 22:33:56 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: icmp.c,v 1.26 2001/02/12 19:42:21 mellon Exp $ Copyright (c) 1996-2001 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -60,6 +60,11 @@ struct icmp_state { static struct icmp_state *icmp_state; static omapi_object_type_t *dhcp_type_icmp; +#if defined (TRACING) +trace_type_t *trace_icmp_input; +trace_type_t *trace_icmp_output; +#endif + /* Initialize the ICMP protocol. */ void icmp_startup (routep, handler) @@ -95,33 +100,48 @@ void icmp_startup (routep, handler) new -> type = dhcp_type_icmp; new -> icmp_handler = handler; - /* Get the protocol number (should be 1). */ - proto = getprotobyname ("icmp"); - if (proto) - protocol = proto -> p_proto; - - /* Get a raw socket for the ICMP protocol. */ - new -> socket = socket (AF_INET, SOCK_RAW, protocol); - if (new -> socket < 0) - log_fatal ("unable to create icmp socket: %m"); +#if defined (TRACING) + trace_icmp_input = trace_type_register ("icmp-input", (void *)0, + trace_icmp_input_input, + trace_icmp_input_stop, MDL); + trace_icmp_output = trace_type_register ("icmp-output", (void *)0, + trace_icmp_output_input, + trace_icmp_output_stop, MDL); + + /* If we're playing back a trace file, don't create the socket + or set up the callback. */ + if (!trace_playback ()) { +#endif + /* Get the protocol number (should be 1). */ + proto = getprotobyname ("icmp"); + if (proto) + protocol = proto -> p_proto; + + /* Get a raw socket for the ICMP protocol. */ + new -> socket = socket (AF_INET, SOCK_RAW, protocol); + if (new -> socket < 0) + log_fatal ("unable to create icmp socket: %m"); #if defined (HAVE_SETFD) - if (fcntl (new -> socket, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on icmp socket: %m"); + if (fcntl (new -> socket, F_SETFD, 1) < 0) + log_error ("Can't set close-on-exec on icmp: %m"); #endif - /* Make sure it does routing... */ - state = 0; - if (setsockopt (new -> socket, SOL_SOCKET, SO_DONTROUTE, - (char *)&state, sizeof state) < 0) - log_fatal ("Can't disable SO_DONTROUTE on ICMP socket: %m"); - - result = omapi_register_io_object ((omapi_object_t *)new, - icmp_readsocket, 0, - icmp_echoreply, 0, 0); - if (result != ISC_R_SUCCESS) - log_fatal ("Can't register icmp handle: %s", - isc_result_totext (result)); + /* Make sure it does routing... */ + state = 0; + if (setsockopt (new -> socket, SOL_SOCKET, SO_DONTROUTE, + (char *)&state, sizeof state) < 0) + log_fatal ("Can't disable SO_DONTROUTE on ICMP: %m"); + + result = omapi_register_io_object ((omapi_object_t *)new, + icmp_readsocket, 0, + icmp_echoreply, 0, 0); + if (result != ISC_R_SUCCESS) + log_fatal ("Can't register icmp handle: %s", + isc_result_totext (result)); +#if defined (TRACING) + } +#endif icmp_state = new; } @@ -140,6 +160,9 @@ int icmp_echorequest (addr) struct sockaddr_in to; struct icmp icmp; int status; +#if defined (TRACING) + trace_iov_t iov [2]; +#endif if (!icmp_state) log_fatal ("ICMP protocol used before initialization."); @@ -166,14 +189,41 @@ int icmp_echorequest (addr) icmp.icmp_cksum = wrapsum (checksum ((unsigned char *)&icmp, sizeof icmp, 0)); - /* Send the ICMP packet... */ - status = sendto (icmp_state -> socket, (char *)&icmp, sizeof icmp, 0, - (struct sockaddr *)&to, sizeof to); - if (status < 0) - log_error ("icmp_echorequest %s: %m", inet_ntoa(to.sin_addr)); - - if (status != sizeof icmp) - return 0; +#if defined (TRACING) + if (trace_playback ()) { + char *buf = (char *)0; + unsigned buflen = 0; + + /* Consume the ICMP event. */ + status = trace_get_packet (&trace_icmp_output, &buflen, &buf); + if (status != ISC_R_SUCCESS) + log_error ("icmp_echorequest: %s", + isc_result_totext (status)); + if (buf) + dfree (buf, MDL); + } else { + if (trace_record ()) { + iov [0].buf = (char *)addr; + iov [0].len = sizeof *addr; + iov [1].buf = (char *)&icmp; + iov [1].len = sizeof icmp; + trace_write_packet_iov (trace_icmp_output, + 2, iov, MDL); + } +#endif + /* Send the ICMP packet... */ + status = sendto (icmp_state -> socket, + (char *)&icmp, sizeof icmp, 0, + (struct sockaddr *)&to, sizeof to); + if (status < 0) + log_error ("icmp_echorequest %s: %m", + inet_ntoa(to.sin_addr)); + + if (status != sizeof icmp) + return 0; +#if defined (TRACING) + } +#endif return 1; } @@ -189,6 +239,9 @@ isc_result_t icmp_echoreply (h) int hlen, len; struct iaddr ia; struct icmp_state *state; +#if defined (TRACING) + trace_iov_t iov [2]; +#endif state = (struct icmp_state *)h; @@ -222,7 +275,50 @@ isc_result_t icmp_echoreply (h) memcpy (ia.iabuf, &from.sin_addr, sizeof from.sin_addr); ia.len = sizeof from.sin_addr; +#if defined (TRACING) + if (trace_record ()) { + iov [0].buf = (char *)&ia; + iov [0].len = sizeof ia; + iov [1].buf = icbuf; + iov [1].len = len; + trace_write_packet_iov (trace_icmp_input, 2, iov, MDL); + } +#endif (*state -> icmp_handler) (ia, icbuf, len); } return ISC_R_SUCCESS; } + +#if defined (TRACING) +void trace_icmp_input_input (trace_type_t *ttype, unsigned length, char *buf) +{ + struct iaddr *ia; + unsigned len; + char *icbuf; + ia = (struct iaddr *)buf; + icbuf = (char *)(ia + 1); + if (icmp_state -> icmp_handler) + (*icmp_state -> icmp_handler) (*ia, icbuf, + (int)(length - sizeof ia)); +} + +void trace_icmp_input_stop (trace_type_t *ttype) { } + +void trace_icmp_output_input (trace_type_t *ttype, unsigned length, char *buf) +{ + struct icmp *icmp; + struct iaddr *ia; + + if (length != (sizeof (*icmp) + (sizeof *ia))) { + log_error ("trace_icmp_output_input: data size mismatch %d:%d", + length, (sizeof (*icmp) + (sizeof *ia))); + return; + } + ia = (struct iaddr *)buf; + icmp = (struct icmp *)(ia + 1); + + log_error ("trace_icmp_output_input: unsent ping to %s", piaddr (*ia)); +} + +void trace_icmp_output_stop (trace_type_t *ttype) { } +#endif /* TRACING */