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.