jungo-image.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2008 (C) Jose Vasconcellos <[email protected]>
  4. #
  5. # A script that can communicate with jungo-based routers
  6. # (such as MI424-WR, USR8200 and WRV54G) to backup the installed
  7. # firmware and replace the boot loader.
  8. #
  9. # Tested with Python 2.5 on Linux and Windows
  10. #
  11. """Usage: %s [options] <IP_address> [redboot.bin]
  12. Valid options:
  13. \t-h | --help: usage statement
  14. \t-d | --no-dump: don't create a flash dump
  15. \t-f | --file: use <filename> to store dump contents
  16. \t-u | --user: provide username (default admin)
  17. \t-p | --pass: provide password (default password1)
  18. \t-P | --proto: set transfer protocol (default http)
  19. \t --port: set port for http (default 8080)
  20. \t-s | --server: IP address of tftp server
  21. \t-w | --write: initiate loading of redboot (default no modification to flash)
  22. \t-q | --quiet: don't display unnecessary information
  23. \t-v | --verbose: display progress information
  24. \t-V | --version: display version information
  25. """
  26. import os
  27. import sys
  28. import getopt
  29. import getpass
  30. import telnetlib
  31. import string
  32. import binascii
  33. import socket
  34. import thread
  35. import SocketServer
  36. import SimpleHTTPServer
  37. server = ""
  38. HOST = "192.168.1.1"
  39. PORT = 8080
  40. user = "admin"
  41. #password = getpass.getpass()
  42. password = "password1"
  43. proto = "http"
  44. imagefile = "redboot.bin"
  45. dumpfile = ""
  46. verbose = 1
  47. no_dump = 0
  48. dumplen = 0x10000
  49. write_image = 0
  50. flashsize=4*1024*1024
  51. #device="br0"
  52. device="ixp0"
  53. ####################
  54. def start_server():
  55. httpd = SocketServer.TCPServer((server,PORT),SimpleHTTPServer.SimpleHTTPRequestHandler)
  56. thread.start_new_thread(httpd.serve_forever,())
  57. ####################
  58. def get_flash_size():
  59. global flashsize
  60. tn.write("cat /proc/mtd\n")
  61. # wait for prompt
  62. buf = tn.read_until("Returned 0", 3)
  63. if buf:
  64. i = buf.find('mtd0:')
  65. if i > 0:
  66. flashsize = int(buf[i+6:].split()[0],16)
  67. else:
  68. print "Can't find mtd0!"
  69. else:
  70. print "Can't access /proc/mtd!"
  71. def image_dump(tn, dumpfile):
  72. if not dumpfile:
  73. tn.write("ver\n");
  74. buf = tn.read_until("Returned 0")
  75. i = buf.find("Platform:")
  76. if i < 0:
  77. platform="jungo"
  78. else:
  79. line=buf[i+9:]
  80. i=line.find('\n')
  81. platform=line[:i].split()[-1]
  82. tn.write("ifconfig -v %s\n" % device);
  83. buf = tn.read_until("Returned 0")
  84. i = buf.find("mac = 0")
  85. if i > 0:
  86. i += 6
  87. else:
  88. print "No MAC address found! (use -f option)"
  89. sys.exit(1)
  90. dumpfile = "%s-%s.bin" % (platform, buf[i:i+17].replace(':',''))
  91. else:
  92. tn.write("\n")
  93. print "Dumping flash contents (%dMB) to %s" % (flashsize/1048576, dumpfile)
  94. f = open(dumpfile, "wb")
  95. t=flashsize/dumplen
  96. for addr in range(t):
  97. if verbose:
  98. sys.stdout.write('\r%d%%'%(100*addr/t))
  99. sys.stdout.flush()
  100. tn.write("flash_dump -r 0x%x -l %d -4\n" % (addr*dumplen, dumplen))
  101. tn.read_until("\n")
  102. count = addr*dumplen
  103. while 1:
  104. buf = tn.read_until("\n")
  105. if buf.strip() == "Returned 0":
  106. break
  107. s = buf.split()
  108. if s and s[0][-1] == ':':
  109. a=int(s[0][:-1],16)
  110. if a != count:
  111. print "Format error: %x != %x"%(a,count)
  112. sys.exit(2)
  113. count += 16
  114. f.write(binascii.a2b_hex(string.join(s[1:],'')))
  115. tn.read_until(">",1)
  116. f.close()
  117. if verbose:
  118. print ""
  119. def telnet_option(sock,cmd,option):
  120. #print "Option: %d %d" % (ord(cmd), ord(option))
  121. if cmd == telnetlib.DO:
  122. c=telnetlib.WILL
  123. elif cmd == telnetlib.WILL:
  124. c=telnetlib.DO
  125. sock.sendall(telnetlib.IAC + c + option)
  126. def telnet_timeout():
  127. print "Fatal error: telnet timeout!"
  128. sys.exit(1)
  129. def usage():
  130. print __doc__ % os.path.basename(sys.argv[0])
  131. ####################
  132. try:
  133. opts, args = getopt.getopt(sys.argv[1:], "hdf:u:qp:P:s:vVw", \
  134. ["help", "dump", "file=", "user=", "pass=", "port=", "proto=",
  135. "quiet=", "server=", "verbose", "version", "write"])
  136. except getopt.GetoptError:
  137. # print help information and exit:
  138. usage()
  139. sys.exit(1)
  140. for o, a in opts:
  141. if o in ("-h", "--help"):
  142. usage()
  143. sys.exit(1)
  144. elif o in ("-V", "--version"):
  145. print "%s: 0.8" % sys.argv[0]
  146. sys.exit(1)
  147. elif o in ("-d", "--no-dump"):
  148. no_dump = 1
  149. elif o in ("-f", "--file"):
  150. dumpfile = a
  151. elif o in ("-s", "--server"):
  152. server = a
  153. elif o in ("-u", "--user"):
  154. user = a
  155. elif o in ("-p", "--pass"):
  156. password = a
  157. elif o in ("-P", "--proto"):
  158. proto = a
  159. elif o == "--port":
  160. PORT = int(a)
  161. elif o in ("-w", "--write"):
  162. write_image = 1
  163. elif o in ("-q", "--quiet"):
  164. verbose = 0
  165. elif o in ("-v", "--verbose"):
  166. verbose = 1
  167. # make sure we have enough arguments
  168. if len(args) > 0:
  169. HOST = args[0]
  170. if len(args) == 2:
  171. imagefile = args[1]
  172. ####################
  173. # create a telnet session to the router
  174. try:
  175. tn = telnetlib.Telnet(HOST)
  176. except socket.error, msg:
  177. print "Unable to establish telnet session to %s: %s" % (HOST, msg)
  178. sys.exit(1)
  179. tn.set_option_negotiation_callback(telnet_option)
  180. buf = tn.read_until("Username: ", 3)
  181. if not buf:
  182. telnet_timeout()
  183. tn.write(user+"\n")
  184. if password:
  185. buf = tn.read_until("Password: ", 3)
  186. if not buf:
  187. telnet_timeout()
  188. tn.write(password+"\n")
  189. # wait for prompt
  190. buf = tn.read_until("> ", 3)
  191. if not buf:
  192. telnet_timeout()
  193. get_flash_size()
  194. if not no_dump:
  195. image_dump(tn, dumpfile)
  196. if write_image:
  197. if not os.access(imagefile, os.R_OK):
  198. print "File access error: %s" % (imagefile)
  199. sys.exit(3)
  200. splitpath = os.path.split(imagefile)
  201. # make sure we're in the directory where the image is located
  202. if splitpath[0]:
  203. os.chdir(splitpath[0])
  204. # write image file image
  205. if not server:
  206. server = tn.get_socket().getsockname()[0]
  207. if proto == "http":
  208. cmd = "load -u %s://%s:%d/%s -r 0\n" % (proto, server, PORT, splitpath[1])
  209. else:
  210. cmd = "load -u %s://%s/%s -r 0\n" % (proto, server, splitpath[1])
  211. if proto == "http":
  212. start_server()
  213. if verbose:
  214. print "Unlocking flash..."
  215. tn.write("unlock 0 0x%x\n" % flashsize)
  216. buf = tn.read_until("Returned 0")
  217. if verbose:
  218. print "Writing new image..."
  219. print cmd,
  220. tn.write(cmd)
  221. buf = tn.read_until("Returned 0",10)
  222. tn.write("exit\n")
  223. tn.close()