ftp.nice.ch/pub/next/unix/network/system/gated.2.1pl2.NI.bs.tar.gz#/gated-2.1/src/icmp.c

This is icmp.c in view mode; [Download] [Up]

/*
 *  $Header: /disk/d/src/devel/gated/dist/src/RCS/icmp.c,v 2.1 92/02/24 14:12:35 jch Exp $
 */

/*%Copyright%*/
/************************************************************************
*									*
*	GateD, Release 2						*
*									*
*	Copyright (c) 1990,1991,1992 by Cornell University		*
*	    All rights reserved.					*
*									*
*	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.				*
*									*
*	Royalty-free licenses to redistribute GateD Release		*
*	2 in whole or in part may be obtained by writing to:		*
*									*
*	    GateDaemon Project						*
*	    Information Technologies/Network Resources			*
*	    143 Caldwell Hall						*
*	    Cornell University						*
*	    Ithaca, NY 14853-2602					*
*									*
*	GateD is based on Kirton's EGP, UC Berkeley's routing		*
*	daemon	 (routed), and DCN's HELLO routing Protocol.		*
*	Development of Release 2 has been supported by the		*
*	National Science Foundation.					*
*									*
*	Please forward bug fixes, enhancements and questions to the	*
*	gated mailing list: gated-people@gated.cornell.edu.		*
*									*
*	Authors:							*
*									*
*		Jeffrey C Honig <jch@gated.cornell.edu>			*
*		Scott W Brim <swb@gated.cornell.edu>			*
*									*
*************************************************************************
*									*
*      Portions of this software may fall under the following		*
*      copyrights:							*
*									*
*	Copyright (c) 1988 Regents of the University of California.	*
*	All rights reserved.						*
*									*
*	Redistribution and use in source and binary forms are		*
*	permitted provided that the above copyright notice and		*
*	this paragraph are duplicated in all such forms 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 California, Berkeley.  The name of the		*
*	University may not be used to endorse or promote		*
*	products derived from this software without specific		*
*	prior written permission.  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.		*
*									*
************************************************************************/


/*
 *  Routines for handling ICMP messages
 */

#include "include.h"

#if	defined(PROTO_ICMP) && !defined(RTM_ADD)

task *icmp_task = (task *) 0;

struct icmptype {
    const char *typename;
    int codes;
    const char *codenames[6];
};

static struct icmptype icmp_types[ICMP_MAXTYPE + 1] =
{
    {"EchoReply", 0,
     {""}},
    {"", 0,
     {""}},
    {"", 0,
     {""}},
    {"UnReachable", 5,
   {"Network", "Host", "Protocol", "Port", "NeedFrag", "SourceFailure"}},
    {"SourceQuench", 0,
     {""}},
    {"ReDirect", 4,
     {"Network", "Host", "TOSNetwork", "TOSHost"}},
    {"", 0,
     {""}},
    {"", 0,
     {""}},
    {"Echo", 0,
     {""}},
    {"", 0,
     {""}},
    {"", 0,
     {""}},
    {"TimeExceeded", 1,
     {"InTransit", "Reassembly"}},
    {"ParamProblem", 0,
     {""}},
    {"TimeStamp", 0,
     {""}},
    {"TimeStampReply", 0,
     {""}},
    {"InfoRequest", 0,
     {""}},
    {"InfoRequestReply", 0,
     {""}},
    {"MaskRequest", 0,
     {""}},
    {"MaskReply", 0,
     {""}}
};

/*
 * icmp_recv() handles ICMP redirect messages.
 */

static void
icmp_recv(tp)
task *tp;
{
    int count;
    struct icmp *icmppkt = (struct icmp *) recv_iovec[RECV_IOVEC_DATA].iov_base;
    struct sockaddr_in gateway;		/* gateway address */
    struct sockaddr_in dest;		/* destination addr */
    struct sockaddr_in who_from;
    const char *type_name, *code_name;
    struct icmptype *itp;

    if (task_receive_packet(tp, &count)) {
	return;
    }
    sockclear_in(&who_from);
#ifdef	ICMP_IP_HEADER
    who_from.sin_addr = recv_ip.ip_src;
#else				/* ICMP_IP_HEADER */
    who_from.sin_addr = recv_addr.in.sin_addr;
#endif				/* ICMP_IP_HEADER */

    if (icmppkt->icmp_type <= ICMP_MAXTYPE) {
	itp = &icmp_types[icmppkt->icmp_type];
	type_name = itp->typename;
	if (icmppkt->icmp_code <= itp->codes) {
	    code_name = itp->codenames[icmppkt->icmp_code];
	} else {
	    code_name = "Invalid";
	}
    } else {
	type_name = "Invalid";
	code_name = "";
    }

    tracef("ICMP from %A type %s(%u) code %s(%u)",
	   &who_from,
	   type_name,
	   icmppkt->icmp_type,
	   code_name,
	   icmppkt->icmp_code);

    if (trace_flags & TR_UPDATE) {
	int do_mask = FALSE;
	int do_dest = FALSE;
	int do_idseq = FALSE;

	switch (icmppkt->icmp_type) {
	    case ICMP_ECHOREPLY:
	    case ICMP_ECHO:
		do_idseq = TRUE;
		break;

	    case ICMP_UNREACH:
		do_dest = TRUE;
		break;

	    case ICMP_SOURCEQUENCH:
		break;

	    case ICMP_REDIRECT:
		sockclear_in(&gateway);
		gateway.sin_addr = icmppkt->icmp_gwaddr;
		sockclear_in(&dest);
		dest.sin_addr = icmppkt->icmp_ip.ip_dst;
		tracef(" dest %A via %A",
		       &dest,
		       &gateway);
		break;

	    case ICMP_TIMXCEED:
	    case ICMP_PARAMPROB:
		do_dest = TRUE;
		break;

	    case ICMP_TSTAMP:
	    case ICMP_TSTAMPREPLY:
		tracef(" originate %T.%u receive %T.%u transmit %T.%u",
		       icmppkt->icmp_otime / 1000,
		       icmppkt->icmp_otime % 1000,
		       icmppkt->icmp_rtime / 1000,
		       icmppkt->icmp_rtime % 1000,
		       icmppkt->icmp_ttime / 1000,
		       icmppkt->icmp_ttime % 1000);
		break;

	    case ICMP_IREQ:
	    case ICMP_IREQREPLY:
		do_idseq = do_dest = TRUE;
		break;

	    case ICMP_MASKREQ:
	    case ICMP_MASKREPLY:
		do_idseq = do_mask = TRUE;
		break;

	}

	if (do_idseq) {
	    tracef(" id %u sequence %u",
		   icmppkt->icmp_id,
		   icmppkt->icmp_seq);
	}
	if (do_dest) {
	    sockclear_in(&dest);
	    dest.sin_addr = icmppkt->icmp_ip.ip_dst;
	    tracef(" dest %A protocol %u",
		   &dest,
		   icmppkt->icmp_ip.ip_p);
	}
	if (do_mask) {
	    sockclear_in(&dest);
	    dest.sin_addr.s_addr = icmppkt->icmp_mask;
	    tracef(" mask %A",
		   &dest);
	}
    }
    trace(TR_ICMP, 0, NULL);
    trace(TR_ICMP, 0, NULL);

    /*
     * filter ICMP network redirects
     */
    if (icmppkt->icmp_type == ICMP_REDIRECT) {
	if ((icmppkt->icmp_code == ICMP_REDIRECT_NET) || (icmppkt->icmp_code == ICMP_REDIRECT_HOST)) {
	    sockclear_in(&gateway);
	    gateway.sin_addr = icmppkt->icmp_gwaddr;
	    sockclear_in(&dest);
	    dest.sin_addr = icmppkt->icmp_ip.ip_dst;
	    if (icmppkt->icmp_code == ICMP_REDIRECT_NET) {
		dest.sin_addr = gd_inet_makeaddr(gd_inet_netof(dest.sin_addr), 0, TRUE);
	    }
	    rt_redirect(icmp_task,
			(sockaddr_un *) & dest,
			(sockaddr_un *) & gateway,
			(sockaddr_un *) & who_from,
	      (icmppkt->icmp_code == ICMP_REDIRECT_HOST) ? TRUE : FALSE);
	}
    }
    return;
}


/*
 *  Initialize ICMP socket and ICMP task
 */

void
icmp_init()
{

    if (!icmp_task) {
	icmp_task = task_alloc("ICMP");
#ifdef	ICMP_IP_HEADER
	icmp_task->task_flags = TASKF_IPHEADER;
#endif				/* ICMP_IP_HEADER */
	icmp_task->task_proto = IPPROTO_ICMP;
	if ((icmp_task->task_socket = task_get_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
	    quit(errno);
	}
	icmp_task->task_recv = icmp_recv;
	if (!task_create(icmp_task, BUFSIZ)) {	/* XXX - How big is an ICMP packet */
	    quit(EINVAL);
	}
    }
}

#endif				/* defined(PROTO_ICMP) && !defined(RTM_ADD) */

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.