130 likes | 278 Views
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
E N D
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 0 /* redirect: net */ #define ICC_HOSTRD 1 /* redirect: host */ #define IC_TOSNRD 2 /* redirect: type of service, net */ #define IC_TOSHRD 3 /* redirect: type of service, host */ #define ICC_TIMEX 0 /* time exceeded, ttl */ #define ICC_FTIMEX 1 /* time exceeded, frag */ #define IC_HLEN 8 /* octets */ #define IC_PADLEN 3 /* 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 */ #define ic_id icu.ic1.ic1_id #define ic_seq icu.ic1.ic1_seq /* format 2 */ #define ic_gw icu.ic2_gw /* format 3 */ #define ic_ptr icu.ic3.ic3_ptr #define ic_pad icu.ic3.ic3_pad /* format 4 */ #define ic_mbz icu.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; }