免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3588 | 回复: 0

ping written in python [复制链接]

论坛徽章:
0
发表于 2005-09-10 13:18 |显示全部楼层
从研读ping.py开始学习python
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""ping.py
ping.py uses the ICMP protocol's mandatory ECHO_REQUEST
datagram to elicit an ICMP ECHO_RESPONSE from a
host or gateway.
Copyright (C) 2004 - Lars Strand
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
Must be running as root, or write a suid-wrapper. Since newer *nix
variants, the kernel ignores the set[ug]id flags on #! scripts for
security reasons
RFC792, echo/reply message:
0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Identifier          |        Sequence Number        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Data ...
+-+-+-+-+-
TODO:
- do not create socket inside 'while' (but if not: ipv6 won't work)
- add support for broadcast/multicast
- add support for own payload string
CHANGELOG:
DONE --> bugfix from Filip Van Raemdonck mechanix debian org
DONE --> add more support for modules (raise instead of sys.exit)
DONE --> locale func names
DONE --> package def
DONE --> some code cleanup
"""
import sys
import os
import struct
import array
import time
import select
import binascii
import math
import getopt
import string
import socket
# total size of data (payload)
ICMP_DATA_STR = 56   
# initial values of header variables
ICMP_TYPE = 8
ICMP_TYPE_IP6 = 128
ICMP_CODE = 0
ICMP_CHECKSUM = 0
ICMP_ID = 0
ICMP_SEQ_NR = 0
# Package definitions.
__program__   = 'ping'
__version__   = '0.5a'
__date__      = '2004/15/12'
__author__    = 'Lars Strand '
__licence__   = 'GPL'
__copyright__ = 'Copyright (C) 2004 Lars Strand'
def _construct(id, size, ipv6):
   """Constructs a ICMP echo packet of variable size
   """
   # size must be big enough to contain time sent
   if size  len(load):
       rest = load
       size -= len(load)
   # pad the rest of payload
   rest += size * "X"
   # pack
   data = struct.pack("d", time.time()) + rest
   packet = header + data          # ping packet without checksum
   checksum = _in_cksum(packet)    # make checksum
   # construct header with correct checksum
   if ipv6:
       header = struct.pack('BbHHh', ICMP_TYPE_IP6, ICMP_CODE, checksum,
                            ICMP_ID, ICMP_SEQ_NR+id)
   else:
       header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, checksum, ICMP_ID,
                            ICMP_SEQ_NR+id)
   # ping packet *with* checksum
   packet = header + data
   # a perfectly formatted ICMP echo packet
   return packet
def _in_cksum(packet):
   """THE RFC792 states: 'The 16 bit one's complement of
   the one's complement sum of all 16 bit words in the header.'
   Generates a checksum of a (ICMP) packet. Based on in_chksum found
   in ping.c on FreeBSD.
   """
   # add byte if not dividable by 2
   if len(packet) & 1:               
       packet = packet + ''
   # split into 16-bit word and insert into a binary array
   words = array.array('h', packet)
   sum = 0
   # perform ones complement arithmetic on 16-bit words
   for word in words:
       sum += (word & 0xffff)
   hi = sum >> 16
   lo = sum & 0xffff
   sum = hi + lo
   sum = sum + (sum >> 16)
   
   return (~sum) & 0xffff # return ones complement
def pingNode(alive=0, timeout=1.0, ipv6=0, number=sys.maxint, node=None,
            flood=0, size=ICMP_DATA_STR):
   """Pings a node based on input given to the function.
   """
   # if no node, exit
   if not node:
       _error("")
   # if not a valid host, exit
   if ipv6:
       if socket.has_ipv6:
           try:
               info, port = socket.getaddrinfo(node, None)
               host = info[4][0]
               # do not print ipv6 twice if ipv6 address given as node
               if host == node:
                   noPrintIPv6adr = 1
           except:
               _error("cannot resolve %s: Unknow host" % node)
       else:
           _error("No support for IPv6 on this plattform")
   else:    # IPv4
       try:
           host = socket.gethostbyname(node)
       except:
           _error("cannot resolve %s: Unknow host" % node)
   # trying to ping a network?
   if not ipv6:
       if int(string.split(host, ".")[-1]) == 0:
           _error("no support for network ping")
   # do some sanity check
   if number == 0:
       _error("invalid count of packets to transmit: '%s'" % str(a))
   if alive:
       number = 1
   # Send the ping(s)
   start = 1; mint = 999; maxt = 0.0; avg = 0.0
   lost = 0; tsum = 0.0; tsumsq = 0.0
   # tell the user what we do
   if not alive:
       if ipv6:
           # do not print the ipv6 twice if ip adress given as node
           # (it can be to long in term window)
           if noPrintIPv6adr == 1:
               # add 40 (header) + 8 (icmp header) + payload
               print "PING %s : %d data bytes (40+8+%d)" % (str(node),
                                                            40+8+size, size)
           else:
               # add 40 (header) + 8 (icmp header) + payload
               print "PING %s (%s): %d data bytes (40+8+%d)" % (str(node),
                                                                str(host), 40+8+size, size)
       else:
           # add 20 (header) + 8 (icmp header) + payload
           print "PING %s (%s): %d data bytes (20+8+%d)" % (str(node), str(host),
                                                            20+8+size, size)
        
   # trap ctrl-d and ctrl-c
   try:
        
       # send the number of ping packets as given
       while start  0:  # do not print stats if 0 packet sent
       start -= 1              # since while is '= 2:
       node = sys.argv[-1:][0]   # host to be pinged
       if node[0] == '-' or node == '-h' or node == '--help' :   
           _usage()
   else:
       _error("No arguments given")
   if args:
       _error("illegal option -- %s" % str(args))
        
   # default variables
   alive = 0; timeout = 1.0; ipv6 = 0; count = sys.maxint;
   flood = 0; size = ICMP_DATA_STR
   # run through arguments and set variables
   for o, a in opts:
       if o == "-h" or o == "--help":    # display help and exit
           _usage()
           sys.exit(0)
       if o == "-t" or o == "--timeout": # timeout before "lost"
           try:
               timeout = float(a)
           except:
               _error("invalid timout: '%s'" % str(a))
       if o == "-6" or o == "--ipv6":    # ping ipv6
           ipv6 = 1
       if o == "-c" or o == "--count":   # how many pings?
           try:
               count = int(a)
           except:
               _error("invalid count of packets to transmit: '%s'" % str(a))
       if o == "-f" or o == "--flood":   # no delay between ping send
           flood = 1
       if o == "-s" or o == "--packetsize":  # set the ping payload size
           try:
               size = int(a)
           except:
               _error("invalid packet size: '%s'" % str(a))
       # just send one packet and say "it's alive"
       if o == "-a" or o == "--alive":   
           alive = 1
   # here we send
   pingNode(alive=alive, timeout=timeout, ipv6=ipv6, number=count,
            node=node, flood=flood, size=size)
   # if we made it this far, do a clean exit
   sys.exit(0)
### end


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/9868/showart_46950.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP