if it' icmpwe want it if ip_header protocol ="icmp"calculate where our icmp packet starts offset ip_header ihl buf raw_buffer[offset:offset sizeof(icmp)create our icmp structure icmp_header icmp(bufprint "icmp -type% code% (icmp_header typeicmp_header codethis simple piece of code creates an icmp structure underneath our existing ip structure when the main packet-receiving loop determines that we have received an icmp packet we calculate the offset in the raw packet where the icmp body lives and then create our buffer and print out the type and code fields the length calculation is based on the ip header ihl fieldwhich indicates the number of -bit words ( -byte chunkscontained in the ip header so by multiplying this field by we know the size of the ip header and thus when the next network layer -icmp in this case -begins if we quickly run this code with our typical ping testour output should now be slightly differentas shown belowprotocolicmp - icmp -type code this indicates that the ping (icmp echoresponses are being correctly received and decoded we are now ready to implement the last bit of logic to send out the udp datagramsand to interpret their results now let' add the use of the netaddr module so that we can cover an entire subnet with our host discovery scan save your sniffer_with_icmp py script as scanner py and add the following codeimport threading import time from netaddr import ipnetwork,ipaddress --snip-host to listen on host subnet to target subnet / magic string we'll check icmp responses for magic_message "pythonrules!this sprays out the udp datagrams def udp_sender(subnet,magic_message)time sleep( sender socket socket(socket af_inetsocket sock_dgramfor ip in ipnetwork(subnet)trysender sendto(magic_message,("%sip, )exceptpass --snip-start sending packets threading thread(target=udp_sender,args=(subnet,magic_message) start(