Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is the hexadecimal output of an IPv6 TCP packet captured with tcpdump:

 6000 0000 0018 0620 0000 0000
 0000 0000 0000 0000 0000 0001 0000 0000
 0000 0000 0000 0000 0000 0002 *0026 0026
 0000 0001 0000 0002 {5}412 0065 0034 0000*
 6162 6364    

The packet itself is between the *s above. The {5} represents the packet length in 32-bit words (so it's 5 words long -- 20 bytes). I need to extract tcp header from this info using a bash/awk script, so the script needs to find the length byte and use it to know how much further to read. How can I do that in bash or awk?

share|improve this question
up vote 1 down vote accepted

This is more of a job for Perl or Python, but you can do it with pure bash. Warning: untested.

ipv6_packet='6000 … 6364'
ipv6_packet=${ipv6_packet,,?}               # normalize hexadecimal digits to lowercase, just in case
ipv6_packet=${ipv6_packet//[!0-9a-f]/}      # remove whitespace and everything else that isn't a hex digit
tcp_packet=${ipv6_packet:80}                # all but the first 40 bytes (IPv6 header)
((tcp_data_offset=0x${tcp_packet:24:1}*4))  # data offset (25th nybble), converted from words to bytes
tcp_header=${tcp_packet:0:$tcp_data_offset} # that's the TCP header (still in hexdump form)

Or for short:

ipv6_packet=${ipv6_packet,,?}; ipv6_packet=${ipv6_packet//[!0-9a-f]/}
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.