title: Python struct.error: bad char in struct format
body: <p>first of all I would like to know what this python sentence does:</p>
  
  <pre><code>struct.unpack("!%sH" % (len(data) / 2), data))
  </code></pre>
  
  <p>And secondly, I have to make an ICMP request message using python, and the thing is that I already got some code the teacher gave me to help:</p>
  
  <pre><code>def step4(code, server, port):
      s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
  
      CHARMAP = nonprintable_to_dots()
  
      packet = create_packet(int(code))
  
      s.sendto(packet, (server, port))
  
      while True:
          msg = s.recv(1600)
  
          if not msg:
              break
  
          ihl = (ord(msg[0]) &amp; 0x0F) * 4
          icmp = msg[ihl:]
  
          hexdump(icmp, True)
  
          if cksum(icmp[:]) != 0:
              print("wrong ckecksum!!")
  
  def nonprintable_to_dots():
      return str.join('', [c if c in printable[:-5] else '.' for c in map(chr, range(256))])
  
  def hexdump(frame, with_time=False):
      def to_chr(bytes):
          retval = bytes.translate(CHARMAP)
          return retval[:8] + ' ' + retval[8:]
  
      def to_hex(bytes):
          retval = str.join(' ', ["%02X" % ord(x) for x in bytes])
          return retval[:23] + ' ' + retval[23:]
  
      if with_time:
          print('--' + time.strftime("%H:%M:%s"))
  
      for i in range(0, len(frame), 16):
          line = frame[i:i + 16]
          print('%04X  %-49s |%-17s|' % (i, to_hex(line), to_chr(line)))
  
      print
  
  def cksum(data):
  
      def sum16(data):
          "sum all the the 16-bit words in data"
          if len(data) % 2:
              data += '\0'
  
          return sum(struct.unpack("!%sH" % (len(data) / 2), data))
  
      retval = sum16(data)                       # sum
      retval = sum16(struct.pack('!L', retval))  # one's complement sum
      retval = (retval &amp; 0xFFFF) ^ 0xFFFF        # one's complement
  
      return retval
  </code></pre>
  
  <p>The thing is that theoretically all this code is right, so I only should do the "create_packet" function, which I include here:</p>
  
  <pre><code>def create_packet(code):
      ICMP_REQUEST = 8
      checksum = 0
      identifier = 7
      sequence_number = 7
  
      message_header = struct.pack("!BBHHH", ICMP_REQUEST, 0, checksum, identifier, sequence_number)
  
      message_payload = struct.pack("!I", code)
  
      checksum = cksum(message_header + message_payload)
  
      message_header = struct.pack("!BBHHH", ICMP_REQUEST, 0, checksum, identifier, sequence_number)
  
      return message_header + message_payload
  </code></pre>
  
  <p>Whenever I execute the script, I always get this error:</p>
  
  <pre><code>Traceback (most recent call last):
      File "gymkhana.py", line 256, in &lt;module&gt;
          main()                                                                                                                
      File "gymkhana.py", line 19, in main
          step4(identifier, server, ginkana_port)
      File "gymkhana.py", line 181, in step4
          packet = create_packet(int(code))
      File "gymkhana.py", line 211, in create_packet
          checksum = cksum(message_header + message_payload)
      File "gymkhana.py", line 248, in cksum
          retval = sum16(data)                       # sum
      File "gymkhana.py", line 246, in sum16
          return sum(struct.unpack("!%sH" % (len(data) / 2), data))                                                           
  struct.error: bad char in struct format
  </code></pre>