! ICMP module for (Moose) INet process, GDMR, Jan 1988 %option "-NonStandard-NoCheck-NoTrace-NoDiag-NoStack-NoLine" %include "INet:Formats.Inc" %include "INet:Utility.Inc" %include "INet:INet.Inc" %include "INet:Stats.Inc" %include "INet:Lights.Inc" %systemstring(127)%fnspec itos(%integer n, p) %systemroutinespec phex(%integer i) %externalroutinespec IP outbound(%record(buffer fm)%name b) %externalrecord(INet statistics fm)%spec stats %constinteger ICMP echo reply = 0 %constinteger ICMP destination unreachable = 3 %constinteger ICMP source quench = 4 %constinteger ICMP redirect = 5 %constinteger ICMP echo = 8 %constinteger ICMP time exceeded = 11 %constinteger ICMP parameter problem = 12 %constinteger ICMP timestamp = 13 %constinteger ICMP timestamp reply = 14 %constinteger ICMP information request = 15 %constinteger ICMP information reply = 16 %constinteger ICMP protocol unreachable = 2 %constinteger ICMP port unreachable = 3 %conststring(31)%array ICMP message text(0 : 16) = { 0} "Echo reply", { 1} "?? 1", { 2} "?? 2", { 3} "Destination unreachable", { 4} "Source quench", { 5} "Redirect", { 6} "?? 6", { 7} "?? 7", { 8} "Echo", { 9} "?? 9", {10} "?? 10", {11} "Time exceeded", {12} "Parameter problem", {13} "Timestamp", {14} "Timestamp reply", {15} "Information request", {16} "Information reply" %owninteger ICMP echo sequence = 0 %externalroutine ICMP inbound(%record(buffer fm)%name b) %string(127) message, source %integer c, x, host, net, class !L! lights or A(ICMP light) !! printstring("ICMP inbound from ") !! print inet address(b_IP header_source); newline !! dump(byteinteger(addr(b_ICMP header)), b_IP bytes) message = "ICMP: from " . inet address to S(b_IP header_source) !source = INet address to name(b_IP header_source) !message = message . " (" . source . ")" %if source # "" split INet address(b_IP header_destination, host, net, class) message = message . " (broadcast??)" %if b_flags & broadcast flag # 0 message = message . " -- " %if b_IP bytes < 8 %start pdate printstring("Short ICMP message from ") print inet address(b_IP header_source); newline stats_ICMP errors in = stats_ICMP errors in + 1 release buffer(b) -> out %finish stats_ICMP in = stats_ICMP in + 1 %if b_ICMP header_type = ICMP echo %start ! Send echo reply %if b_flags & broadcast flag = 0 %start ! Don't reply to broadcasts b_ICMP header_type = ICMP echo reply b_ICMP header_checksum = 0 c = calculate checksum(b_ICMP header, b_IP bytes) b_ICMP header_checksum <- \c stats_ICMP out = stats_ICMP out + 1 !! printstring("Sending echo reply to ") !! print inet address(b_IP peer); newline b_protocol = IP ICMP protocol b_next queue == nil IP outbound(b) -> out %finish %else %if b_ICMP header_type = ICMP echo reply message = message . "echo reply" tell network operator(message) %else %if b_ICMP header_type = ICMP timestamp ! Send timestamp reply %if b_flags & broadcast flag = 0 %start ! Don't reply to broadcasts x = b_ICMP header_originate timestamp !N! net order long(x) b_ICMP header_type = ICMP timestamp reply b_ICMP header_receive timestamp = generate timestamp !N! net order long(b_ICMP header_receive timestamp) b_ICMP header_transmit timestamp = b_ICMP header_receive timestamp b_ICMP header_checksum = 0 c = calculate checksum(b_ICMP header, b_IP bytes) b_ICMP header_checksum <- \c stats_ICMP out = stats_ICMP out + 1 !! printstring("Sending timestamp reply to ") !! print inet address(b_IP peer); newline b_protocol = IP ICMP protocol b_next queue == nil IP outbound(b) -> out %finish %else %if b_ICMP header_type = ICMP timestamp reply !N! net order long(b_ICMP header_originate timestamp) !N! net order long(b_ICMP header_receive timestamp) !N! net order long(b_ICMP header_transmit timestamp) message = message . "timestamp reply: " . %c convert timestamp(b_ICMP header_originate timestamp) . ", " . %c convert timestamp(b_ICMP header_receive timestamp) . ", " . %c convert timestamp(b_ICMP header_transmit timestamp) tell network operator(message) %finish release buffer(b) out: !L! lights and A(\ICMP light) %end ! ICMP outbound (user requests) %recordformat ICMP request fm(%integer code, target) %externalroutine ICMP outbound(%record(buffer fm)%name b) %record(ICMP request fm)%name request %integer c !L! lights or B(ICMP light) request == record(addr(b_data start)) !! printstring("ICMP outbound for ") !! print inet address(request_target); newline b_ICMP header == record(addr(b_data(32))) b_ICMP header = 0 b_IP peer = request_target %if request_code = ICMP ping request %start b_ICMP header_type = ICMP echo b_ICMP header_code = 0 ICMP echo sequence = ICMP echo sequence + 1 b_ICMP header_sequence number = ICMP echo sequence c = calculate checksum(b_ICMP header, 8) b_ICMP header_checksum <- \c b_data bytes = 0; b_IP bytes = 8; b_protocol = IP ICMP protocol b_next queue == nil IP outbound(b) stats_ICMP out = stats_ICMP out + 1 %else %if request_code = ICMP timestamp request b_ICMP header_type = ICMP timestamp b_ICMP header_code = 0 ICMP echo sequence = ICMP echo sequence + 1 b_ICMP header_sequence number = ICMP echo sequence b_ICMP header_originate timestamp = generate timestamp !N! net order long(b_ICMP header_originate timestamp) c = calculate checksum(b_ICMP header, 20) b_ICMP header_checksum <- \c b_data bytes = 0; b_IP bytes = 20; b_protocol = IP ICMP protocol b_next queue == nil IP outbound(b) stats_ICMP out = stats_ICMP out + 1 %else !! printstring("Unknown ICMP request code ") !! phex(request_code); newline stats_ICMP errors out = stats_ICMP errors out + 1 release buffer(b) %finish !L! lights and B(\ICMP light) %end %end %of %file