8 IP: Error Processing (ICMP)

Download Report

Transcript 8 IP: Error Processing (ICMP)

8 IP: Error Processing (ICMP)
• Any computer using IP must accept ICMP
messages and change behavior in response to the
reported error.
• ICMP messages are type-dependent
• All ICMP messages begin with a fixed header:
– ic_type: message type
– ic_code: message subtype
– ic_cksum: message checksum
• next 32-bit in an ICMP message depend on the
message type (using union to declare)
/* icmp.h */
/* Internet Control Message Protocol Constants */
/* ic_type field */
#define ICT_ECHORP
0
/* Echo reply
#define ICT_DESTUR
3
/* Destination unreachable*/
#define ICT_SRCQ
4
/* Source quench
#define ICT_REDIRECT 5 /* Redirect message type*/
#define ICT_ECHORQ
8
/* Echo request
#define ICT_TIMEX
11
/* Time exceeded
#define ICT_PARAMP
12
/* Parameter Problem
#define ICT_TIMERQ
13
/* Timestamp request
#define ICT_TIMERP
14
/* Timestamp reply */
#define ICT_INFORQ
15
/* Information request
#define ICT_INFORP
16
/* Information reply
#define ICT_MASKRQ
17
/* Mask request
*/
#define ICT_MASKRP
18
/* Mask reply
*/
*/
*/
*/
*/
*/
*/
*/
*/
/* ic_code field */
#define ICC_NETUR
0
/* dest unreachable, net unreachable
#define ICC_HOSTUR 1
/* dest unreachable, host unreachable
#define ICC_PROTOUR 2
/* dest unreachable, proto unreachable
#define ICC_PORTUR 3
/* dest unreachable, port unreachable
#define ICC_FNADF
4
/* dest unr, frag needed & don't frag
#define ICC_SRCRT
5
/* dest unreachable, src route failed */
*/
*/
*/
*/
*/
#define ICC_NETRD
#define ICC_HOSTRD
#define IC_TOSNRD
#define IC_TOSHRD
0
/* redirect: net
*/
1
/* redirect: host
2
/* redirect: type of service, net
3
/* redirect: type of service, host
*/
*/
*/
#define ICC_TIMEX
0
/* time exceeded, ttl
#define ICC_FTIMEX 1 /* time exceeded, frag
*/
*/
#define IC_HLEN
#define IC_PADLEN
3
8
/* octets
/* pad length (octets)
*/
*/
#define IC_RDTTL
300
/* ttl for redirect routes
*/
/* ICMP packet format (following the IP header)
*/
struct icmp
{
/* ICMP packet
*/
char
ic_type;
/* type of message (ICT_* above)*/
char
ic_code;
/* code (ICC_* above)
*/
short
ic_cksum;
/* checksum of ICMP header+data*/
union {
struct {
int
ic1_id:16; /* echo type, a message id
*/
int
ic1_seq:16;/* echo type, a seq. number*/
} ic1;
IPaddr ic2_gw;
/* for redirect, gateway*/
struct {
char
ic3_ptr;/* pointer, for ICT_PARAMP*/
char
ic3_pad[IC_PADLEN];
} ic3;
int
ic4_mbz;
/* must be zero
*/
} icu;
char
ic_data[1];
/* data area of ICMP message*/
};
/* format 1 */
#defineic_id icu.ic1.ic1_id
#defineic_seq icu.ic1.ic1_seq
/* format 2 */
#defineic_gw icu.ic2_gw
/* format 3 */
#defineic_ptr icu.ic3.ic3_ptr
#defineic_pad icu.ic3.ic3_pad
/* format 4 */
#defineic_mbzicu.ic4_mbz
Received Frame Processing flow
• Driver p.39 ni_in()->ip_in() p.82: enqueue to IP process
->arp_in() p.54
->rarp_in()
• IP process p.68 ipproc(): routing rtget(), put the datagram
to appropriate interface, ipputp() p.110
– Ipputp() decides whether need to fragment and call netwrite()
– P. 49 netwrite()-> local_out() for upper layer
->write() write to network interface
/*-----------------------------------------------------------------------* local_out - handle an IP datagram headed for a local process
*------------------------------------------------------------------------ */
Int local_out(struct ep *pep)
{ struct netif
*pni = &nif[NI_LOCAL];
struct ip
*pip = (struct ip *)pep->ep_data;
int
rv;
ipnet2h(pip);
pep->ep_order |= EPO_IP;
pep = ipreass(pep);
if (pep == 0) return OK;
pip = (struct ip *)pep->ep_data;
ipdstopts(pni, pep);
/* do IP option processing
switch (pip->ip_proto) {
case IPT_ICMP: rv = icmp_in(pni, pep);
break;
case IPT_IGMP: rv = igmp_in(pni, pep);
break;
case IPT_TCP: rv = tcp_in(pni, pep); break;
case IPT_UDP: rv = udp_in(pni, pep); break;
default:
IpInUnknownProtos++;
icmp(ICT_DESTUR, ICC_PROTOUR, pip->ip_src, pep, 0);
return OK;
}
IpInDelivers++;
return rv;
}
*/
8.4 handling Incoming ICMP messages
When receive an ICMP message, Net-Interface => IP => icmp_in
/*------------------------------------------------------*icmp_in - handle ICMP packet coming in from the network
*------------------------------------------------------*/
int icmp_in(struct netif *pni, struct ep *pep)
{
struct ip
*pip;
struct icmp
*pic;
int
i, len;
pip = (struct ip *)pep->ep_data;
pic = (struct icmp *) pip->ip_data;
len = pip->ip_len - IP_HLEN(pip);
if (cksum((WORD *)pic, len)) {
IcmpInErrors++;
freebuf(pep);
return SYSERR; }
IcmpInMsgs++;
switch(pic->ic_type) {
case ICT_ECHORQ:
IcmpInEchos++;
return icmp(ICT_ECHORP, 0, pip->ip_src, pep, 0);
case ICT_MASKRQ:
IcmpInAddrMasks++;
if (!gateway) {
freebuf(pep);
return OK;
}
pic->ic_type = (char) ICT_MASKRP;
*(IPaddr *)pic->ic_data = netmask(pip->ip_dst);
break;
case ICT_MASKRP:
IcmpInAddrMaskReps++;
for (i=0; i<Net.nif; ++i)
if (nif[i].ni_ip == pip->ip_dst)
break;
if (i != Net.nif) {
setmask(i, *(IPaddr *)pic->ic_data);
send(pic->ic_id, ICT_MASKRP); }
freebuf(pep);
return OK;
case ICT_ECHORP:
IcmpInEchoReps++;
if (send(pic->ic_id, (int)pep) != OK)
freebuf(pep);
return OK;
case ICT_REDIRECT:
IcmpInRedirects++;
icredirect(pep);
return OK;
case ICT_DESTUR: IcmpInDestUnreachs++;
freebuf(pep); return OK;
case ICT_SRCQ: IcmpInSrcQuenchs++;
freebuf(pep); return OK;
case ICT_TIMEX: IcmpInTimeExcds++;
freebuf(pep); return OK;
case ICT_PARAMP: IcmpInParmProbs++;
freebuf(pep); return OK;
case ICT_TIMERQ: IcmpInTimestamps++;
freebuf(pep); return OK;
case ICT_TIMERP: IcmpInTimestampReps++;
freebuf(pep); return OK;
default:
IcmpInErrors++;
freebuf(pep);
return OK;
}
icsetsrc(pip);
len = pip->ip_len - IP_HLEN(pip);
pic->ic_cksum = 0;
pic->ic_cksum = cksum((WORD *)pic, len);
IcmpOutMsgs++;
ipsend(pip->ip_dst, pep, len, IPT_ICMP, IPP_INCTL, IP_TTL);
return OK;
}