chap 11: icmp inet control message protocol RFC 792, 950, 1256, 1122. has ip_p value apps can use raw socket to send/recv (ping/traceroute) divide into 2 classes: 1. errors always include 1st 8 bytes of data from IP datagram that caused error (thus tcp/udp ports in there) 2. queries, msg/reply Figure 11.1/2 icmp mesage types/codes Figure 11.1 type/code description PRC (protocol independent error code) PRC is general error code ... e.g., tcp would return host unreachable Figure 11.2 shows functions that may be involved with the message as well as ERRNO icmp_input shows functions called by icmp_input e.g., icmp_reflect because it is a ping at the recv. rip_input because sender needs the reply udp functions that process icmp tcp functions that process icmp Figure 11.3 where we discuss the functions from figure 11.2 11.2 Code intro netinet/ip_icmp.h netinet/ip_icmp.c Stats Figure 11.7/8 icmpstat fields and netstat -s associativity 11.3 icmp structure struct icmp ... note type/code/cksum are the shared header cksum over the entire icmp pkt union of particular message follows icmp_hun - header union all use this icmp_dun - data union some use this 11.4 icmp protosw structure SOCK_RAW for access 11.5 input processing ip_p is 1, therefore thru ip_protox, we select inetsw[4] which is icmp calls pr_input function ptr, which is icmp_input which may call rip_input or hand it off to transport e.g., traceroute will return icmp "errors" ... can sometimes be useful to see that you can't get thru firewall/ACL strange case of udp "connection" is staring you in the face here why using connect with udp can be useful (at least with bsd) 1. sanity check the message 2. errors 3. requests 4. redirects 5. replys Figure 11.15 icmp_input start 11.6 error processing as inputs ... we are the ip_src message is from ip_dst or intermediate router Figure 11.17 message formats 1. unreachable/time exceeded/source quench 2. need fragmentation nextmtu is helpful ... 3. parameter problem (NEVER MIND) Figure 11.18 case ICMP_UNREACH: switch code note: icmpsrc is a lousy name ... it's just a variable. 228: based on original protocol (tcp/udp say) call protocol specific "control" function and pass it: 1. code, ip dst, and ip header + transport info Figure 11.19 protocol independent error codes 11.7 request processing ICMP requests may be generated by process using raw ip socket. Properly formatted request is responded to at L3. E.g. ping request reply from L3 Echo query: icmp_echo and icmp_echoreply "ping" based on app name, but ICMP actually has icmp_echo/icmp_echoreply messages ping named after sonar/ping idea, not packet inet groper Figure 11.20 form of ping icmp_code is 0 note icmp_id, icmp_seq, data icmp_id on unix is process id of ping sending packet, as all pings received are sent upstairs to all pinging processes ... there is no pcb ... (not UDP ...) Figure 11.21 icmp_input: case ICMP_ECHO type set to reply goto reflect; reflect: call icmp_reflect function ... use same mbuf Timestamp query: ICMP_TSTAMP and ICMP_TSTAMREPLY sender sets icmp_otime - originate time icmp_rtime, icmp_ttime set by reply box All times are in milliseconds since midnight UTC. high-order bit set if time value is nonstandard ("good luck" bit) Figure 11.23 call iptime() to get time ... and bail on ttime/rtime bsd kernel gets kernel idea of time in struct timeval and manipulates it to set rtime/ttime. rtime ... message may have set on input queue modify all device drivers? ttime ... message may sit in send queue modify all device drivers? Address Mask Query: ICMP_MASKREQ and ICMP_MASKREPLY in theory, a host sends this to a router on the same subnet. send to broadcast ... sysctl -a: net.inet.icmp.maskrepl: 0 select subnet mask if request mask is 0.0.0.0 or 255.255.255.255 ip_src is saved in icmpdst use ifaof_ifpforaddr to locate the address structure line 262: retain ptr to ip_dst as ip_src may be useless ia ... figure out input address acc. to i/f set mask based on input interface ip addr line 271: if src was 0 (boot) ip_src set to broadcast addr else ip_src set to us .. INFO QUERY: learn network ... obsolete Router Discovery: passed to rip_input as managed by daemon. routed(8), or rdisc(8) does this in BSD. in IPv6 this mechanism not only exists but can be said to be extended to take over arp functionality. this may be the biggest feature in ipv6. /etc/defaults/rc.conf: rtadvd_enable="NO" # Set to YES to enable an IPv6 router # advertisement daemon. If set to YES, # this router becomes a possible candidate # IPv6 default router for local subnets. rtadvd_interfaces="" # Interfaces rtadvd sends RA packets. So rtadvd(8) And ndp(8) for arp(8) ------------------------------------------------------------------------ 11.8 Redirect Processing icmp_gwaddr - preferred gateway ip as input, this means we must make routing table change Figure 11.26 set icmpgw.sin_addr to input ip src, of gateway that sent message icmpdst to desired gateway icmpsrc to ip_dst included as data (desired dst for route) call rtredirect to set host route net/3 never sends net redirects (can be wrong in terms of netmasks, since it doesn't have that info) update routes pfctlinput tells any protocols that need to know about the routing table change can invalidate route caches 11.9 reply processing As requests are generated by processes, kernel does not process the replies, but passes them upstairs. ... rip_input as in Figure 11.28 11.10 Output processing Figure 11.29 icmp output processing icmp_error may be called by ip/transports icmp_reflect used to send ICMP replies icmp_send called for last step process may form own icmp messages and send via raw socket 11.11 icmp_error Figure 11.30 icmp_error/validation arguments: n - mbuf chain containing invalid datagram type/code dest - next-hop router for icmp redirect destifp - which interface to send from desire to avoid broadcast storms in errors don't send it if: fragment already an error (no errors about errors) datagram was broadcast or multicast (no icmp) fails to check for: datagram sent to ip broadcast or multicast if datagram's src is not unicast ... handled by icmp_reflect function it is ok to respond to a request that way though ping broadcast response uses unicast src Figure 11.31, icmp error packet structure Figure 11.32 icmp error message header construction note: alignment done here, but not data copy m_gethdr - get hdr mbuf Figure 11.33, including original datagram copy data to back adjust mbuf copy data to front call icmp_reflect 11.12 icmp_reflect sends replies/errors back to the src of the request or offender icmp_reflect REVERSES ip_src and ip_dst Figure 11.34: icmp discard/address summary icmp_input: ip_src 0.0.0.0 with recv.if src or broadcast icmp_error: discard if link-level broadcast or multicast icmp_reflect: discard if multicast dst or class E convert nonunicast ip_dst to recv. i/f unicast ip swap src/dst ip_output discard outgoing broadcasts for icmp if input sent to broadcast address Figure 11:35 if we can't forward it, and/or loopback burn it store ip_dst set ip_dst to ip_src figure out ip_dst match our ips to see if unicast ip match if broadcast match if ia is null (no match) search on icmpdst ... if ia is still null take the 1st one !!! set ip_src and ttl Figure 11.36: option construction we SKIP THIS! 11.13 icmp_send function Figure 11.39 note moving of mbuf apparatus to hide ip hdr checksum is not computed over IP header icmp does not have route cache (tcp does) IP_ALLOWBROADCAST is NOT passed ... in flags, therefore ip_output does not allow it this does not mean icmp cannot generate broadcasts it can if icmp request ... 11.14 icmp_systcl icmp_maskrepl at time net.inet.icmp.maskrepl: 0 net.inet.icmp.icmplim: 200 limit icmp echo replies to N per second, -1 to turnoff dos limiter in theory net.inet.icmp.drop_redirect: 0 net.inet.icmp.log_redirect: 0 net.inet.icmp.icmplim_output: 1 ok for bandwidth limiter to printf net.inet.icmp.bmcastecho: 0 don't respond to broadcast ping (off) net.inet6.icmp6.rediraccept: 1 net.inet6.icmp6.redirtimeout: 600 net.inet6.icmp6.nd6_prune: 1 net.inet6.icmp6.nd6_delay: 5 net.inet6.icmp6.nd6_umaxtries: 3 net.inet6.icmp6.nd6_mmaxtries: 3 net.inet6.icmp6.nd6_useloopback: 1 net.inet6.icmp6.nodeinfo: 3 net.inet6.icmp6.errppslimit: 100 net.inet6.icmp6.nd6_maxnudhint: 0 net.inet6.icmp6.nd6_debug: 0 Note how icmpv6 gives us a whole raft of esoteric things to learn (sigh?)