Changeset 5651 for umpa/trunk

Show
Ignore:
Timestamp:
06/20/10 15:29:20 (3 years ago)
Author:
kosma
Message:

Merged revisions 5591-5606,5613,5625,5645-5646 via svnmerge from
http://svn.umitproject.org/svnroot/umit/umpa/branches/link-layer-integration

........

r5591 | kosma | 2010-06-05 00:38:07 +0200 (So, 05 čen 2010) | 3 lines


Initial version of SocketL2 - Linux and FreeBSD supported. With tests.
L2 tests fail under BSD. L3 support not touched.

........

r5592 | kosma | 2010-06-05 01:03:33 +0200 (So, 05 čen 2010) | 1 line


obliterating re module at getxsick's request :*

........

r5593 | kosma | 2010-06-05 01:15:34 +0200 (So, 05 čen 2010) | 1 line


platform check: convert find to startswith

........

r5594 | kosma | 2010-06-05 01:16:59 +0200 (So, 05 čen 2010) | 1 line


platform check: detect MS Windows via os.name

........

r5595 | kosma | 2010-06-05 12:39:43 +0200 (So, 05 čen 2010) | 1 line


added a _Socket superclass

........

r5596 | kosma | 2010-06-05 13:16:45 +0200 (So, 05 čen 2010) | 2 lines


moved 'get packet destination' to class Packet, with tests

........

r5597 | kosma | 2010-06-05 18:23:57 +0200 (So, 05 čen 2010) | 2 lines


Port L3 code to new style. Add BSD endianness quirk support w/test.

........

r5598 | kosma | 2010-06-05 19:32:07 +0200 (So, 05 čen 2010) | 2 lines


Load fcntl module conditionally - it's not present under Win32.

........

r5599 | kosma | 2010-06-05 21:28:44 +0200 (So, 05 čen 2010) | 1 line


fix a typo preventing L3 sockets from working under OpenBSD

........

r5600 | kosma | 2010-06-05 22:15:52 +0200 (So, 05 čen 2010) | 1 line


Fixed L2 send (bpf) under OpenBSD.

........

r5601 | kosma | 2010-06-05 22:39:46 +0200 (So, 05 čen 2010) | 1 line


minor documentation issue

........

r5602 | kosma | 2010-06-05 23:42:41 +0200 (So, 05 čen 2010) | 1 line


example for SocketL2 usage

........

r5603 | kosma | 2010-06-05 23:46:17 +0200 (So, 05 čen 2010) | 2 lines


Set svn:executable property on examples, install scripts and setup.py.

........

r5604 | kosma | 2010-06-05 23:58:42 +0200 (So, 05 čen 2010) | 1 line


set svn:ignore on generated documentation dirs

........

r5605 | kosma | 2010-06-06 00:09:36 +0200 (Ne, 06 čen 2010) | 6 lines


README file update.


  • New library description from the trac site.
  • Added myself to Authors section (hope I won't get killed for that ;).
  • Formatting cleanups, rephrasing, etc.

........

r5606 | kosma | 2010-06-06 00:21:49 +0200 (Ne, 06 čen 2010) | 1 line


apply changes to cloned README in docs/

........

r5613 | getxsick | 2010-06-16 19:41:53 +0200 (St, 16 čen 2010) | 2 lines


rename UMPA repository to umpa

........

r5625 | getxsick | 2010-06-18 14:48:59 +0200 (Pá, 18 čen 2010) | 2 lines


rename umpa/branch to umpa/branches (even if i prefer branch/)

........

r5645 | kosma | 2010-06-19 18:00:18 +0200 (So, 19 čen 2010) | 1 line


revert a too-hasty documentation change

........

r5646 | kosma | 2010-06-19 19:14:44 +0200 (So, 19 čen 2010) | 1 line


information on L3 sockets under xp sp2

........

Location:
umpa/trunk
Files:
22 modified
1 copied

Legend:

Unmodified
Added
Removed
  • umpa/trunk

    • Property svnmerge-integrated changed from /umpa/branches/link-layer-integration:1-5590 to /umpa/branches/link-layer-integration:1-5650
  • umpa/trunk/README

    r5193 r5651  
    33============================================ 
    44 
    5 Copyright (C) 2008 Adriano Monteiro Marques <py.adriano at gmail dot com> 
     5Copyright (C) 2008-2010 Adriano Monteiro Marques <py.adriano at gmail dot com> 
    66 
    7 Author: Bartosz SKOWRON <getxsick at gmail dot com> 
     7Authors: Bartosz SKOWRON <getxsick at gmail dot com> 
    88 
    99All rights reserved, see COPYING for details. 
     
    2727============ 
    2828 
    29 UMPA is a packets manipulation library. 
     29UMPA is a packet generation and manipulation library. It aims to provide 
     30an easy-to-use system to manipulate packets on every layer of the OSI model. 
     31UMPA supports many sophisticated features, including: 
    3032 
    31 UMPA is developed in the Python programming language. 
     33  * auto-generating packets - defaults are provided for most fields 
     34  * high-level editing of header fields - no knowledge of bit-level 
     35    representation needed 
     36  * auto-filling - checksum/length fields are generated automatically 
     37  * interaction system - reacting and responding to network events 
     38  * sniffing and sending packets - easy communication with the real world  
    3239 
    33 Packet manipulation library aims to provide easy to use system 
    34 to manipulate packets of every OSI model layers. 
    35  
    36 Many features are supported like: auto-generating packets, high-level 
    37 editing header fields, auto-filling, interaction system, sniffing 
    38 and creating objet's of packets. 
    3940The goal of the project is to get a powerful, easy to use and intelligent 
    40 tool for pro and newbies. 
    41  
    42 Check docs/* for additional informations. 
     41packet manipulation tool suitable both for beginners and experienced users. 
     42UMPA has a wide range of uses, including network diagnostics, auditing, 
     43stress testing and network stack debugging.  
    4344 
    4445 
     
    4647============= 
    4748 
    48 On the Web: 
    49  
    50 http://www.umpa.umitproject.org 
     49On the Web: http://www.umpa.umitproject.org 
    5150 
    5251This page also points to support resources and informations about UMPA 
     
    6463  * [1] Python programming language 
    6564  * [2] libpcap (for sniffing) 
    66   * [3] libpcap's python wrapper (see INSTALL for more) 
     65  * [3] libpcap's python wrapper (see INSTALL for details) 
    6766 
    6867 
     
    7372library, sending patches, testing it and giving ideas: 
    7473 
    75    * Adriano Monteiro Marques 
    76    * Francesco Piccinno 
    77    * Luís António Bastião Silva 
    78    * Guilherme Henrique Polo Gonçalves 
    79    * João Paulo de Souza Medeiros 
     74  * Adriano Monteiro Marques 
     75  * Francesco Piccinno 
     76  * Luís António Bastião Silva 
     77  * Guilherme Henrique Polo Gonçalves 
     78  * João Paulo de Souza Medeiros 
    8079 
    8180 
     
    8988========== 
    9089 
    91   * [0] UMPA website - http://www.umpa.umitproject.org 
    92   * [1] Python official website - http://www.python.org 
    93   * [2] Umit Project - http://www.umitproject.org 
     90  * [0] UMPA website - http://umpa.umitproject.org/ 
     91  * [1] Umit Project - http://www.umitproject.org/ 
     92  * [2] Python official website - http://www.python.org/ 
  • umpa/trunk/docs

    • Property svn:ignore set to
      doctrees
  • umpa/trunk/docs/README

    r5187 r5651  
    33============================================ 
    44 
    5 Copyright (C) 2008 Adriano Monteiro Marques <py.adriano at gmail dot com> 
     5Copyright (C) 2008-2010 Adriano Monteiro Marques <py.adriano at gmail dot com> 
    66 
    7 Author: Bartosz SKOWRON <getxsick at gmail dot com> 
     7Authors: Bartosz SKOWRON <getxsick at gmail dot com> 
    88 
    99All rights reserved, see COPYING for details. 
     
    2727============ 
    2828 
    29 UMPA is a packets manipulation library. 
     29UMPA is a packet generation and manipulation library. It aims to provide 
     30an easy-to-use system to manipulate packets on every layer of the OSI model. 
     31UMPA supports many sophisticated features, including: 
    3032 
    31 UMPA is developed in the Python programming language. 
     33  * auto-generating packets - defaults are provided for most fields 
     34  * high-level editing of header fields - no knowledge of bit-level 
     35    representation needed 
     36  * auto-filling - checksum/length fields are generated automatically 
     37  * interaction system - reacting and responding to network events 
     38  * sniffing and sending packets - easy communication with the real world  
    3239 
    33 Packet manipulation library aims to provide easy to use system 
    34 to manipulate packets of every OSI model layers. 
    35  
    36 Many features are supported like: auto-generating packets, high-level 
    37 editing header fields, auto-filling, interaction system, sniffing 
    38 and creating objet's of packets. 
    3940The goal of the project is to get a powerful, easy to use and intelligent 
    40 tool for pro and newbies. 
    41  
    42 Check docs/* for additional informations. 
     41packet manipulation tool suitable both for beginners and experienced users. 
     42UMPA has a wide range of uses, including network diagnostics, auditing, 
     43stress testing and network stack debugging.  
    4344 
    4445 
     
    4647============= 
    4748 
    48 On the Web: 
    49  
    50 http://www.umpa.umitproject.org 
     49On the Web: http://www.umpa.umitproject.org 
    5150 
    5251This page also points to support resources and informations about UMPA 
     
    6463  * [1] Python programming language 
    6564  * [2] libpcap (for sniffing) 
    66   * [3] libpcap's python wrapper (see INSTALL for more) 
     65  * [3] libpcap's python wrapper (see INSTALL for details) 
    6766 
    6867 
     
    7372library, sending patches, testing it and giving ideas: 
    7473 
    75    * Adriano Monteiro Marques 
    76    * Francesco Piccinno 
    77    * Luís António Bastião Silva 
    78    * Guilherme Henrique Polo Gonçalves 
    79    * João Paulo de Souza Medeiros 
     74  * Adriano Monteiro Marques 
     75  * Francesco Piccinno 
     76  * Luís António Bastião Silva 
     77  * Guilherme Henrique Polo Gonçalves 
     78  * João Paulo de Souza Medeiros 
    8079 
    8180 
     
    8988========== 
    9089 
    91   * [0] UMPA website - http://www.umpa.umitproject.org 
    92   * [1] Python official website - http://www.python.org 
    93   * [2] Umit Project - http://www.umitproject.org 
     90  * [0] UMPA website - http://umpa.umitproject.org/ 
     91  * [1] Umit Project - http://www.umitproject.org/ 
     92  * [2] Python official website - http://www.python.org/ 
  • umpa/trunk/docs/tutorials

    • Property svn:ignore set to
      *
  • umpa/trunk/docs/tutorials-src/01-YourFirstPackets.rst

    r5190 r5651  
    346346pass more than one packet at the same time). 
    347347 
     348Raw IP sockets under Windows 
     349---------------------------- 
     350 
     351If you plan to use raw sockets under Windows XP SP2 or later, be aware of 
     352the restrictions imposed by the Windows' networking stack. They generally boil 
     353down to two things: 
     354 
     355 1. TCP data cannot be sent over raw sockets. 
     356 2. The IP source address for any outgoing UDP datagram must exist on a network 
     357    interface. 
     358 
     359The detailed description of those restrictions can be found at the following URL: 
     360http://msdn.microsoft.com/en-us/library/ms740548%28VS.85%29.aspx. 
     361If you find them to be too limiting, consider using Layer 2 sockets (``SocketL2`` 
     362class) instead. 
    348363 
    349364UDP protocol 
  • umpa/trunk/examples/models.py

    • Property svn:executable set to *
  • umpa/trunk/examples/nostrict.py

    • Property svn:executable set to *
  • umpa/trunk/examples/payload.py

    • Property svn:executable set to *
  • umpa/trunk/examples/sniff.py

    • Property svn:executable set to *
  • umpa/trunk/examples/tcp.py

    • Property svn:executable set to *
  • umpa/trunk/examples/udp.py

    • Property svn:executable set to *
  • umpa/trunk/install_scripts/clean.sh

    • Property svn:executable set to *
  • umpa/trunk/install_scripts/create_docs.sh

    • Property svn:executable set to *
  • umpa/trunk/install_scripts/create_packages.sh

    • Property svn:executable set to *
  • umpa/trunk/setup.py

    • Property svn:executable set to *
  • umpa/trunk/tests/a_unit/test_packets.py

    r5170 r5651  
    2222import sys 
    2323from umit.umpa import Packet 
    24 from umit.umpa.protocols import IP, TCP, UDP, Payload 
     24from umit.umpa.protocols import Ethernet, IP, TCP, UDP, Payload 
    2525from umit.umpa.protocols import _consts 
    26 from umit.umpa.utils.exceptions import UMPAException, UMPAStrictException 
     26from umit.umpa.utils.exceptions import UMPAException, UMPAStrictException, \ 
     27                                       UMPAAttributeException 
    2728from umit.umpa._packets import StrictWarning 
    2829 
     
    9798        for i in xrange(len(order)): 
    9899            assert isinstance(p.protos[i], order[i]) 
     100 
     101    def test_get_destination(self): 
     102        p = Packet(Ethernet(dst='00:11:22:33:44:55'), 
     103                   IP(dst='1.2.3.4'), 
     104                   UDP(dstport=1234), 
     105                   Payload('UMPA')) 
     106         
     107        py.test.raises(UMPAException, p._get_destination, 1); 
     108        assert p._get_destination(2) == '00:11:22:33:44:55' 
     109        assert p._get_destination(3) == '1.2.3.4' 
     110        py.test.raises(UMPAAttributeException, p._get_destination, 4); 
     111        py.test.raises(UMPAAttributeException, p._get_destination, 5); 
     112        py.test.raises(UMPAException, p._get_destination, 6); 
    99113 
    100114class TestUMPAPacketsOutput(object): 
  • umpa/trunk/tests/a_unit/test_sockets.py

    r5170 r5651  
    22# -*- coding: utf-8 -*- 
    33 
    4 # Copyright (C) 2009 Adriano Monteiro Marques. 
     4# Copyright (C) 2009-2010 Adriano Monteiro Marques. 
    55# 
    6 # Author: Bartosz SKOWRON <getxsick at gmail dot com> 
     6# Authors: Bartosz SKOWRON <getxsick at gmail dot com> 
     7#          Kosma Moczek <kosma at kosma dot pl> 
    78# 
    89# This library is free software; you can redistribute it and/or modify  
     
    2324import py.test 
    2425 
    25 from umit.umpa import Socket, Packet 
    26 from umit.umpa.protocols import IP, TCP 
     26from umit.umpa import Socket, SocketL2, Packet 
     27import umit.umpa.sniffing 
     28from umit.umpa.protocols import Ethernet, IP, TCP, UDP, Payload 
    2729from umit.umpa.utils.exceptions import UMPAException, UMPANotPermittedException 
    28  
     30from tests.utils import SendPacket, SendPacketL2 
    2931 
    3032class TestUMPASockets(object): 
     
    3537    def test_sent_size(self): 
    3638        if os.name == 'posix' and os.geteuid() != 0: 
    37             py.test.skip('root-priviliges are needed') 
     39            py.test.skip('root-privileges are needed') 
    3840 
    3941        p1 = Packet(IP(), TCP()) 
     
    4244        s = Socket() 
    4345        size = s.send(p1, p2) 
     46        assert size == [40, 40] 
    4447 
    45         assert size == [40, 40] 
     48    def test_send_size_L2(self): 
     49        if os.name == 'posix' and os.geteuid() != 0: 
     50            py.test.skip('root-privileges are needed') 
     51 
     52        p1 = Packet(Ethernet(src='00:11:22:33:44:55', dst='00:11:22:33:44:55'), 
     53                    IP(src="127.0.0.1", dst="127.0.0.1"), 
     54                    TCP(srcport=1234, dstport=4321), 
     55                    Payload('xyz')) 
     56        p2 = Packet(Ethernet(src='00:11:22:33:44:55', dst='00:11:22:33:44:55'), 
     57                    IP(src="127.0.0.1", dst="127.0.0.1"), 
     58                    TCP(srcport=1234, dstport=4321), 
     59                    Payload('xyz')) 
     60 
     61        s = SocketL2(iface='lo') 
     62        size = s.send(p1, p2) 
     63 
     64        assert size == [57, 57] 
     65 
     66    def test_send_sniff_tcp(self): 
     67        if os.name == 'posix' and os.geteuid() != 0: 
     68            py.test.skip('root-privileges are needed') 
     69 
     70        p = Packet(Ethernet(src='00:11:22:33:44:55', dst='00:11:22:33:44:55'), 
     71                   IP(src="127.0.0.1", dst="127.0.0.1"), 
     72                   UDP(srcport=1234, dstport=4321), 
     73                   Payload('xyz')) 
     74 
     75        th = SendPacketL2(p, iface='lo') 
     76        th.start() 
     77        result = umit.umpa.sniffing.sniff(1, device='lo', filter="src port 1234") 
     78        th.join() 
     79 
     80        assert len(result) == 1 
     81        assert result[0].ethernet.src == '00:11:22:33:44:55' 
     82        assert result[0].ip.src == '127.0.0.1' 
     83        assert result[0].udp.srcport == 1234 
     84        assert result[0].udp.dstport == 4321 
     85 
     86    def test_send_sniff_tcp_L2(self): 
     87        if os.name == 'posix' and os.geteuid() != 0: 
     88            py.test.skip('root-privileges are needed') 
     89 
     90        p = Packet(Ethernet(src='00:11:22:33:44:55', dst='00:11:22:33:44:55'), 
     91                   IP(src="127.0.0.1", dst="127.0.0.1"), 
     92                   TCP(srcport=1234, dstport=4321), 
     93                   Payload('xyz')) 
     94 
     95        th = SendPacketL2(p, iface='lo') 
     96        th.start() 
     97        result = umit.umpa.sniffing.sniff(1, device='lo', filter="src port 1234") 
     98        th.join() 
     99 
     100        assert len(result) == 1 
     101        assert result[0].ethernet.src == '00:11:22:33:44:55' 
     102        assert result[0].ip.src == '127.0.0.1' 
     103        assert result[0].tcp.srcport == 1234 
     104        assert result[0].tcp.dstport == 4321 
     105 
     106    def test_ntohs_quirk(self): 
     107        raw1 = "ABCDEFGH" 
     108        raw2 = umit.umpa._sockets._ntohs_quirk(raw1) 
     109 
     110        assert raw2 == "ABDCEFHG" 
  • umpa/trunk/tests/utils.py

    r5170 r5651  
    3535            time.sleep(2) 
    3636            s.send(self._packet) 
     37 
     38class SendPacketL2(threading.Thread): 
     39    def __init__(self, packet, amount=1, iface=None): 
     40        super(SendPacketL2, self).__init__() 
     41        self._packet = packet 
     42        self._amount = amount 
     43        self._iface  = iface 
     44    def run(self): 
     45        s = umit.umpa.SocketL2(iface=self._iface) 
     46        for i in xrange(self._amount): 
     47            time.sleep(2) 
     48            s.send(self._packet) 
  • umpa/trunk/umit/umpa/__init__.py

    r5170 r5651  
    4141from umit.umpa._config import config 
    4242from umit.umpa._packets import Packet 
    43 from umit.umpa._sockets import Socket 
     43from umit.umpa._sockets import Socket, SocketL2 
    4444 
    4545# UMPA handles with the local directory $HOME/.umpa 
  • umpa/trunk/umit/umpa/_packets.py

    r5170 r5651  
    162162                last_proto.__dict__['payload'] = proto 
    163163            self.protos.append(proto) 
     164 
     165    def _get_destination(self, layer): 
     166        """ 
     167        Get packet's destination address. 
     168 
     169        @type layer: C{int} 
     170        @param layer: Protocol layer. 
     171 
     172        @return: destination address from the selected layer. 
     173        """ 
     174 
     175        for proto in self.protos: 
     176            if proto.layer == layer: 
     177                break 
     178 
     179        if not proto: 
     180            raise UMPAException("The packet does not contain a layer %d protocol." % level) 
     181 
     182        return proto.dst 
    164183 
    165184    def get_raw(self): 
  • umpa/trunk/umit/umpa/_sockets.py

    r5413 r5651  
    22# -*- coding: utf-8 -*- 
    33 
    4 # Copyright (C) 2008-2009 Adriano Monteiro Marques. 
    5 # 
    6 # Author: Bartosz SKOWRON <getxsick at gmail dot com> 
     4# Copyright (C) 2008-2010 Adriano Monteiro Marques. 
     5# 
     6# Authors: Bartosz SKOWRON <getxsick at gmail dot com> 
     7#          Kosma Moczek <kosma at kosma dot pl> 
    78# 
    89# This library is free software; you can redistribute it and/or modify  
     
    2122 
    2223""" 
    23 Socket connection management. 
    24  
    25 It contains Socket class which should be used instead of 
    26 socket.socket() directly from the standard library. 
    27  
    28 But it's correctly to use socket module directly if needed. 
     24Raw sockets support. 
     25 
     26Contains Socket classes which can be used to send raw packets in 
     27a platform-independent manner. The standard Python socket module can be used 
     28instead if advanced functionalities are needed. 
    2929""" 
    3030 
    3131import socket 
     32import struct 
     33import sys 
     34import os 
     35from errno import EBUSY 
    3236 
    3337from umit.umpa.utils.exceptions import UMPAException, UMPANotPermittedException 
    3438 
    35 class Socket(object): 
    36     """ 
    37     This class handles with sockets. 
    38  
    39     To send built packets your need to create a socket. 
    40     You can use socket module from Python Standard Library directly 
    41     but it's recommended to use this class instead. 
    42  
    43     That is because there are some other features, 
    44     and for some security issues. 
     39# constants from various header files not available under Python 
     40ETH_P_ALL = 3                     # from linux/if_ether.h 
     41BIOCSETIF = 2149597804            # from net/bpf.h 
     42 
     43# Detect socket programming model. This greatly simplifies socket code. 
     44if sys.platform == 'linux2': 
     45    _l2model = 'AF_PACKET' 
     46    _l3model = 'AF_INET' 
     47    _l3quirk = None 
     48elif sys.platform.startswith('freebsd') or \ 
     49     sys.platform.startswith('netbsd') or \ 
     50     sys.platform.startswith('darwin'): 
     51    _l2model = 'bpf' 
     52    _l3model = 'AF_INET' 
     53    _l3quirk = 'ntohs' 
     54elif sys.platform.startswith('openbsd'): 
     55    _l2model = 'bpf' 
     56    _l3model = 'AF_INET' 
     57    _l3quirk = None 
     58elif os.name == 'nt': 
     59    _l2model = 'NDIS' 
     60    _l3model = 'AF_INET' 
     61    _l3quirk = 'windows' 
     62else: 
     63    _l2model = None 
     64    _l3model = None 
     65    _l3quirk = None 
     66 
     67# load additional modules conditionally depending on programming models 
     68if _l2model == 'bpf': 
     69    from fcntl import ioctl 
     70 
     71def send(*packets, **kwargs): 
     72    """ 
     73    Send arbitrary packets. 
     74 
     75    The function creates sockets of proper level as needed. The 'iface' 
     76    named argument must be supplied for L2 (link-layer) sockets. 
     77 
     78    @type packets: C{Packet} 
     79    @param packets: list of umit.umpa.Packet objects to send. 
     80 
     81    @returns: List of return values (byte counts) from the send() function. 
     82    """ 
     83 
     84    sent_bytes = [] 
     85    for packet in packets: 
     86        # create appropriate socket based on packet's lowermost layer 
     87        if packet.protos[0].layer == 2: 
     88            sock = SocketL2(iface=kwargs.get('iface')) 
     89        else: 
     90            sock = SocketL3() 
     91        sent_bytes.extend(sock.send(packet)) 
     92    return sent_bytes 
     93 
     94class _Socket(object): 
     95    """ 
     96    Raw socket superclass. 
     97 
     98    This is an abstract class. 
     99    """ 
     100 
     101    def __init__(self, **kwargs): 
     102        raise NotImplementedError("this is an abstract class") 
     103 
     104class SocketL2(_Socket): 
     105    """ 
     106    Level 2 (link-layer) socket class. 
     107 
     108    Supported platforms: Linux (AF_PACKET), BSD (bpf). 
     109    """ 
     110 
     111    def __init__(self, iface=None): 
     112        """ 
     113        Create a new SocketL2 instance. 
     114 
     115        Requires root/administrator rights and/or CAP_NET_RAW capability. 
     116 
     117        @type iface: C{str} 
     118        @param iface: Interface to use for sending the packets. 
     119        """ 
     120        if iface is None: 
     121            # TODO: port interface detection from the link-layer branch 
     122            raise NotImplementedError("You need to specify iface") 
     123 
     124        if _l2model == 'AF_PACKET': 
     125            try: 
     126                self._sock = socket.socket(socket.AF_PACKET, 
     127                        socket.SOCK_RAW, 
     128                        ETH_P_ALL) 
     129            except socket.error, msg: 
     130                raise UMPANotPermittedException(msg) 
     131 
     132            self._sock.bind((iface, ETH_P_ALL)) 
     133            self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**20) 
     134        elif _l2model == 'bpf': 
     135            # Loop over /dev/bpf* devices, looking for a free one. 
     136            self._sock = None 
     137            suffix = 0 
     138            while self._sock is None: 
     139                try: 
     140                    self._sock = open('/dev/bpf'+str(suffix), 'wb') 
     141                except IOError, error: 
     142                    if error.errno == EBUSY: 
     143                        suffix = suffix + 1 
     144                    else: 
     145                        raise UMPAException(str(error)) 
     146 
     147            ioctl(self._sock, BIOCSETIF, iface) 
     148        else: 
     149            raise NotImplementedError("L2 sockets unsupported on your platform") 
     150 
     151    def send(self, *packets): 
     152        """ 
     153        Send packets through the socket. 
     154 
     155        @type packets: C{Packet} 
     156        @param packets: List of umit.umpa.Packet objects to send. 
     157 
     158        @returns: List of return values (byte counts) from the send() function. 
     159        """ 
     160 
     161        sent_bytes = [] 
     162        for packet in packets: 
     163            if _l2model == 'AF_PACKET': 
     164                sent_bytes.append(self._sock.send(packet.get_raw())) 
     165            elif _l2model == 'bpf': 
     166                sent_bytes.append(self._sock.write(packet.get_raw())) 
     167            else: 
     168                raise NotImplementedError("L2 send unsupported on your platform") 
     169        return sent_bytes 
     170 
     171class SocketL3(_Socket): 
     172    """ 
     173    Level 3 (network layer) socket class. 
     174 
     175    Supported platforms: Linux, BSD, Windows (AF_INET). 
     176 
     177    Note: If you plan to use raw sockets under Windows XP SP2 or later, be aware 
     178    of the restrictions imposed by the Windows’ networking stack. They generally 
     179    boil down to two things: 
     180 
     181    1. TCP data cannot be sent over raw sockets. 
     182    2. The IP source address for any outgoing UDP datagram must exist on 
     183       a network interface. 
     184 
     185    The detailed description of those restrictions can be found at the following URL: 
     186    http://msdn.microsoft.com/en-us/library/ms740548%28VS.85%29.aspx. If you find 
     187    them to be too limiting, consider using Layer 2 sockets (SocketL2 class) instead. 
    45188    """ 
    46189 
    47190    def __init__(self): 
    48191        """ 
    49         Create a new Socket(). 
    50         """ 
    51  
    52         # to create socket object we need root priviligies. 
    53         # if non-root EUID, then exception is raised 
    54         # use umit.umpa.utils.security.super_priviliges() to avoid exception 
    55         # when a new Socket object is created 
    56         try: 
    57             self._sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, 
    58                                                             socket.IPPROTO_RAW) 
    59         except socket.error, msg: 
    60             raise UMPANotPermittedException(msg) 
    61  
    62         # to build own headers of IP 
    63         self._sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 
     192        Create a new SocketL3 instance. 
     193 
     194        Requires root/administrator rights and/or CAP_NET_RAW capability. 
     195        """ 
     196 
     197        if _l3model == 'AF_INET': 
     198            try: 
     199                self._sock = socket.socket(socket.AF_INET, 
     200                                           socket.SOCK_RAW, 
     201                                           socket.IPPROTO_RAW) 
     202            except socket.error, msg: 
     203                raise UMPANotPermittedException(msg) 
     204 
     205            # tell the kernel we are including our own IP header 
     206            self._sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 
     207        else: 
     208            raise NotImplementedError('L3 sockets unsupported on your platform') 
    64209 
    65210    def send(self, *packets): 
    66211        """ 
    67         Send packets in to the network. 
     212        Send packets through the socket. 
    68213 
    69214        @type packets: C{Packet} 
    70         @param packets: packets which were built by umit.umpa.Packet objects. 
    71         """ 
    72  
    73         sent_bits = [] 
     215        @param packets: List of umit.umpa.Packet objects to send. 
     216 
     217        @returns: List of return values (byte counts) from the send() function. 
     218        """ 
     219 
     220        sent_bytes = [] 
    74221        for packet in packets: 
    75             # XXX try to use similar mechanism as is for SocketL2 
    76             # to pick up correct interface, using bind() and send() 
    77             # then there is no need to pick out a destination address 
    78             dst_addr = self._get_address(packet) 
    79             # if dst_addr is a tuple, convert it to a string; works only for IPv4 
    80             if type(dst_addr) is tuple: 
    81                 dst_addr = ".".join(str(y) for y in dst_addr) 
    82             sent_bits.append(self._sock.sendto(packet.get_raw(), 
    83                                                             (dst_addr, 0))) 
    84         return sent_bits 
    85  
    86     def _get_address(self, packet): 
    87         """ 
    88         Pick out the destination address from 3rd layer. 
    89  
    90         @return: destination address from 3rd layer of OSI model. 
    91         """ 
    92         for proto in packet.protos: 
    93             if proto.layer == 3:    # XXX: if we included more than one protocol 
    94                 break               #   of layer 3 we got IP from the first one 
    95  
    96         if not proto: 
    97             raise UMPAException("There is not prototocol from 3rd layer.") 
    98  
    99         return proto.dst 
     222            if _l3model == 'AF_INET': 
     223                # get destination address and convert it to IPv4 notation 
     224                # TODO: move this to utils.net 
     225                dst_addr = packet._get_destination(layer=3) 
     226                if type(dst_addr) is tuple: 
     227                    dst_addr = ".".join(str(y) for y in dst_addr) 
     228 
     229                raw = packet.get_raw() 
     230 
     231                if _l3quirk == 'ntohs': 
     232                    raw = _ntohs_quirk(raw) 
     233 
     234                sent_bytes.append(self._sock.sendto(raw, (dst_addr, 0))) 
     235            else: 
     236                raise NotImplementedError("L3 send unsupported on your platform") 
     237        return sent_bytes 
     238 
     239def _ntohs_quirk(raw): 
     240    """ 
     241    FreeBSD raw socket endianness quirk support. 
     242 
     243    Some BSD flavors, notably FreeBSD, have a weirdness in their raw IP sockets 
     244    in that the 'total length' and 'fragment offset' fields must be supplied in 
     245    host byte order. See ip(4) manpage on affected systems. 
     246 
     247    This function corrects the endianness of a packet, making it suitable to be 
     248    sent on such systems. 
     249 
     250    @type raw: C{str} 
     251    @param raw: Raw IP header 
     252 
     253    @returns: Raw IP header data with 'total length' and 'fragment offset' fields 
     254              converted to host byte order. 
     255    """ 
     256 
     257    vhds, tl, id, fo = struct.unpack("!HHHH", raw[0:8]) 
     258    tl = socket.ntohs(tl) 
     259    fo = socket.ntohs(fo) 
     260    raw = struct.pack("!HHHH", vhds, tl, id, fo) + raw[8:] 
     261 
     262    return raw 
     263 
     264# XXX API compatibility hack for Milestone 0.3 release 
     265Socket = SocketL3