Wednesday, May 10, 2017

It's my Python experience. IGMP generator. Version 0.11 (MIT License).

Hi, my dear friends!

This is a code of the next version of the program with name "IGMP generator". Do you remember my first experience with Python? It's my second Python experience.
I wrote this code after the 12-th of June 2015 year, when I created my first Python program (IGMP generator version 0.1).

I apologize for the strange syntax highlighting and ugly formatting.

#! /usr/bin/env python

# ******************************************************************************
# Program name: igmp_generator
# Description: IGMP packet generator for IPv4
# Version: 0.11 (Hydrocyclone-2)
# Author: Vasiliy V. Bodrov aka Bodro (mailto:mobile.ipbsoftware@gmail.com)
# Date: 12.06.2015
# Programming language: Python
# Commenting language: English
# ******************************************************************************
# The MIT License (MIT)
#
# Copyright (c) 2015 IPB Software (Vasiliy V. Bodrov aka Bodro)
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
# THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ******************************************************************************

# ******************************************************************************
# Import
# ******************************************************************************

import getopt, sys
from struct import *
from socket import socket, inet_aton, htons, AF_PACKET, SOCK_RAW

# ******************************************************************************
# Global variable
# ******************************************************************************

# Self variable
version_num_str = '0.11'
version_name = 'Hydrocyclone-2'

# Common variable
common_interface = "eth0"

# Layer 2
l2_header = 0x00;

l2_src_addr1 = 0x02 
l2_src_addr2 = 0x01
l2_src_addr3 = 0x02
l2_src_addr4 = 0x03
l2_src_addr5 = 0x04
l2_src_addr6 = 0x05

l2_dst_addr1 = 0x01
l2_dst_addr2 = 0x02
l2_dst_addr3 = 0x03
l2_dst_addr4 = 0x04
l2_dst_addr5 = 0x05
l2_dst_addr6 = 0x06

l2_ether_type = 0x0800

# Layer 3 (IP)
l3_ip_v4_header = 0x00

l3_ip_v4_source = '192.168.0.1'
l3_ip_v4_dest = '224.0.0.22'

l3_ip_v4_ihl = 5
l3_ip_v4_ver = 4
l3_ip_v4_tos = 0
l3_ip_v4_tot_len = 0
l3_ip_v4_id = 54321
l3_ip_v4_frag_off = 0
l3_ip_v4_ttl = 1
l3_ip_v4_proto = 2
l3_ip_v4_check = 0

l3_ip_v4_saddr = 0x00
l3_ip_v4_daddr = 0x00
l3_ip_v4_ihl_ver = 0x00

# Layer 3 (IGMP)
l3_igmp_data = 0x00

l3_igmp_v3_t22 = 0x00

l3_igmp_v3_t22_prefix = 0x00

l3_igmp_v3_t22_group_record1 = 0x00

l3_igmp_v3_t22_group_record1_src_addr1 = 0x00000000
l3_igmp_v3_t22_group_record1_src_addr2 = 0x00000000
l3_igmp_v3_t22_group_record1_src_addr3 = 0x00000000
l3_igmp_v3_t22_group_record1_src_addr4 = 0x00000000
l3_igmp_v3_t22_group_record1_src_addr5 = 0x00000000

l3_igmp_v3_t22_type = 0x22
l3_igmp_v3_t22_reserved = 0x00
l3_igmp_v3_t22_check = 0x0000
l3_igmp_v3_t22_reserved = 0x0000
l3_igmp_v3_t22_num_of_grp_rec = 0x0001;

l3_igmp_v3_t22_group_record1_rec_type = 0x00
l3_igmp_v3_t22_group_record1_aux_data_len = 0x00
l3_igmp_v3_t22_group_record1_num_of_src = 0x0001
l3_igmp_v3_t22_group_record1_milticast_addr1 = 0xE0
l3_igmp_v3_t22_group_record1_milticast_addr2 = 0x01
l3_igmp_v3_t22_group_record1_milticast_addr3 = 0x01
l3_igmp_v3_t22_group_record1_milticast_addr4 = 0x01
l3_igmp_v3_t22_group_record1_aux_data = 0x00

l3_igmp_v3_t22_group_record1_src_addr1_1 = 0xC0
l3_igmp_v3_t22_group_record1_src_addr1_2 = 0xA8
l3_igmp_v3_t22_group_record1_src_addr1_3 = 0x01
l3_igmp_v3_t22_group_record1_src_addr1_4 = 0x01

l3_igmp_v3_t22_group_record1_src_addr2_1 = 0xC0
l3_igmp_v3_t22_group_record1_src_addr2_2 = 0xA8
l3_igmp_v3_t22_group_record1_src_addr2_3 = 0x01
l3_igmp_v3_t22_group_record1_src_addr2_4 = 0x02

l3_igmp_v3_t22_group_record1_src_addr3_1 = 0xC0
l3_igmp_v3_t22_group_record1_src_addr3_2 = 0xA8
l3_igmp_v3_t22_group_record1_src_addr3_3 = 0x01
l3_igmp_v3_t22_group_record1_src_addr3_4 = 0x03

l3_igmp_v3_t22_group_record1_src_addr4_1 = 0xC0
l3_igmp_v3_t22_group_record1_src_addr4_2 = 0xA8
l3_igmp_v3_t22_group_record1_src_addr4_3 = 0x01
l3_igmp_v3_t22_group_record1_src_addr4_4 = 0x04

l3_igmp_v3_t22_group_record1_src_addr5_1 = 0xC0
l3_igmp_v3_t22_group_record1_src_addr5_2 = 0xA8
l3_igmp_v3_t22_group_record1_src_addr5_3 = 0x01
l3_igmp_v3_t22_group_record1_src_addr5_4 = 0x05

# ******************************************************************************
# Code
# ******************************************************************************

# ------------------------------------------------------------------------------
# Function: version
# Description: show version info
# ------------------------------------------------------------------------------
def version():
    print("Program: " + sys.argv[0])
    print("version " + version_num_str + ' (' + version_name + ')')
    print("IGMP packet generator for IPv4")
    print("Note: This version support only IGMPv3 (over IPv4) and packet type 0x22 (Membership Report Message)")
    print("Limits: Max group: 1. Max source in group: 5.");

# ------------------------------------------------------------------------------
# Function: authors
# Description: show authors
# ------------------------------------------------------------------------------
def authors():
    version()
    print("Author: Vasiliy V. Bodrov aka Bodro (mailto:mobile.ipbsoftware@gmail.com)");
    
# ------------------------------------------------------------------------------
# Function: license
# Description: show license
# ------------------------------------------------------------------------------
def license():
    version()
    print("")
    print("The MIT License (MIT)")
    print("")
    print("Copyright (c) 2015 IPB Software (Vasiliy V. Bodrov aka Bodro)")
    print("")
    print("Permission is hereby granted, free of charge, to any person obtaining a")
    print("copy of this software and associated documentation files (the \"Software\"),")
    print("Software is furnished to do so, subject to the following conditions:")
    print("")
    print("The above copyright notice and this permission notice shall be included")
    print("in all copies or substantial portions of the Software.")
    print("")
    print("THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS")
    print("OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF")
    print("MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.")
    print("IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY")
    print("CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT")
    print("OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR")
    print("THE USE OR OTHER DEALINGS IN THE SOFTWARE.")

# ------------------------------------------------------------------------------
# Function: usage
# Description:
# ------------------------------------------------------------------------------
def usage():
    print("Use --help or -h for help")
    print("Example: " + sys.argv[0] + " --help")

# ------------------------------------------------------------------------------
# Function: help
# Description:
# ------------------------------------------------------------------------------
def help():
    version();
    print("");
    print(sys.argv[0] + " [OPTIONS]");
    print("");
    print("-h,\t--help\t\t\t\t- show this help and exit");
    print("-v,\t--version\t\t\t- show version and exit");
    print("-a,\t--authors\t\t\t- show authors and exit");
    print("-l,\t--license\t\t\t- show license and exit");
    print("-i,\t--interface=INTERFACE\t\t- network interface (default: " + common_interface + ")");
    print("\t--ip-src=IP\t\t\t- source IP-address (default: " + l3_ip_v4_source + ")");
    print("\t--ip-dst=IP\t\t\t- destination IP-address (default: " + l3_ip_v4_dest + ")");
    print("\t--mac-src=MAC\t\t\t- source MAC-address (default: " + format(l2_src_addr1, '02x') + ":" + format(l2_src_addr2, '02x') + ":" + format(l2_src_addr3, '02x') + ":" + format(l2_src_addr4, '02x') + ":" + format(l2_src_addr5, '02x') + ":" + format(l2_src_addr6, '02x') + ")");
    print("\t--mac-dst=MAC\t\t\t- destination MAC-address (default: " + format(l2_dst_addr1, '02x') + ":" + format(l2_dst_addr2, '02x') + ":" + format(l2_dst_addr3, '02x') + ":" + format(l2_dst_addr4, '02x') + ":" + format(l2_dst_addr5, '02x') + ":" + format(l2_dst_addr6, '02x') + ")");
    print("\t--ttl=NUM\t\t\t- time to live (default: " + format(l3_ip_v4_ttl, 'd') + ")");
    print("\t--gr1-rec-type=NUM\t\t- record type (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_rec_type, 'd') + ")");
    print("\t--gr1-mult-addr=IP\t\t- multicast (group) address (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_milticast_addr1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_milticast_addr2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_milticast_addr3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_milticast_addr4, 'd') + ")");
    print("\t--gr1-num-of-src=NUM\t\t- number of sources (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_num_of_src, 'd') + ")");
    print("\t--gr1-src-addr1=IP\t\t- source address 1 (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_src_addr1_1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr1_2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr1_3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr1_4, 'd')  + ")");
    print("\t--gr1-src-addr2=IP\t\t- source address 2 (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_src_addr2_1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr2_2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr2_3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr2_4, 'd') + ")");
    print("\t--gr1-src-addr3=IP\t\t- source address 3 (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_src_addr3_1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr3_2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr3_3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr3_4, 'd') + ")");
    print("\t--gr1-src-addr4=IP\t\t- source address 4 (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_src_addr4_1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr4_2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr4_3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr4_4, 'd') + ")");
    print("\t--gr1-src-addr5=IP\t\t- source address 5 (group record 1) (default: " + format(l3_igmp_v3_t22_group_record1_src_addr5_1, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr5_2, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr5_3, 'd') + "." + format(l3_igmp_v3_t22_group_record1_src_addr5_4, 'd') + ")");
    print("");
    print("Record type:");
    print("");
    print("0 - Unknown (0x00)");
    print("1 - Mode Is Include (0x01)");
    print("2 - Mode Is Exclude (0x02)");
    print("3 - Change To Include Mode (0x03)");
    print("4 - Change To Exclude Mode (0x04)");
    print("5 - Allow New Sources (0x05)");
    print("6 - Block Old Sources (0x06)");
    print("");
    print("Example: " + "\n\t# " + sys.argv[0] + " \\\n\t\t\
--interface=eth0 \\\n\t\t\
--ip-src=\"200.100.1.1\" \\\n\t\t\
--ip-dst=\"224.0.0.22\" \\\n\t\t\
--mac-src=\"23:A1:01:02:02:05\" \\\n\t\t\
--mac-dst=\"F0:FA:00:05:07:FF\" \\\n\t\t\
--gr1-rec-type=\"2\" \\\n\t\t\
--gr1-mult-addr=\"225.1.2.3\" \\\n\t\t\
--gr1-num-of-src=5 \\\n\t\t\
--gr1-src-addr1=\"127.0.0.1\" \\\n\t\t\
--gr1-src-addr2=\"127.0.0.2\" \\\n\t\t\
--gr1-src-addr3=\"127.0.0.3\" \\\n\t\t\
--gr1-src-addr4=\"127.0.0.4\" \\\n\t\t\
--gr1-src-addr5=\"127.0.0.5\" \\\n\t\t\
--ttl=1")

# ------------------------------------------------------------------------------
# Function: checksum
# Description: calculate checksum
# ------------------------------------------------------------------------------
def checksum(msg):
    s = 0x0000
     
    for i in range(0, len(msg), 2):
        w = ord(msg[i]) + (ord(msg[i + 1]) << 8)
        s = s + w
     
    s = (s >> 16) + (s & 0xFFFF);
    s = s + (s >> 16);
     
    s = ~s & 0xFFFF
     
    return s
    
# ------------------------------------------------------------------------------
# Function: data_send
# Description:
# ------------------------------------------------------------------------------
def data_send():
    global version_num_str
    global version_name

    global common_interface

    global l2_header

    global l2_src_addr1
    global l2_src_addr2
    global l2_src_addr3
    global l2_src_addr4
    global l2_src_addr5
    global l2_src_addr6

    global l2_dst_addr1
    global l2_dst_addr2
    global l2_dst_addr3
    global l2_dst_addr4
    global l2_dst_addr5
    global l2_dst_addr6

    global l2_ether_type

    global l3_ip_v4_header

    global l3_ip_v4_source
    global l3_ip_v4_dest

    global l3_ip_v4_ihl
    global l3_ip_v4_ver
    global l3_ip_v4_tos
    global l3_ip_v4_tot_len
    global l3_ip_v4_id
    global l3_ip_v4_frag_off
    global l3_ip_v4_ttl
    global l3_ip_v4_proto
    global l3_ip_v4_check

    global l3_ip_v4_saddr
    global l3_ip_v4_daddr
    global l3_ip_v4_ihl_ver

    global l3_igmp_data

    global l3_igmp_v3_t22

    global l3_igmp_v3_t22_prefix

    global l3_igmp_v3_t22_group_record1

    global l3_igmp_v3_t22_group_record1_src_addr1
    global l3_igmp_v3_t22_group_record1_src_addr2
    global l3_igmp_v3_t22_group_record1_src_addr3
    global l3_igmp_v3_t22_group_record1_src_addr4
    global l3_igmp_v3_t22_group_record1_src_addr5

    global l3_igmp_v3_t22_type
    global l3_igmp_v3_t22_reserved
    global l3_igmp_v3_t22_check
    global l3_igmp_v3_t22_reserved
    global l3_igmp_v3_t22_num_of_grp_rec

    global l3_igmp_v3_t22_group_record1_rec_type
    global l3_igmp_v3_t22_group_record1_aux_data_len
    global l3_igmp_v3_t22_group_record1_num_of_src
    global l3_igmp_v3_t22_group_record1_milticast_addr1
    global l3_igmp_v3_t22_group_record1_milticast_addr2
    global l3_igmp_v3_t22_group_record1_milticast_addr3
    global l3_igmp_v3_t22_group_record1_milticast_addr4
    global l3_igmp_v3_t22_group_record1_aux_data

    global l3_igmp_v3_t22_group_record1_src_addr1_1
    global l3_igmp_v3_t22_group_record1_src_addr1_2
    global l3_igmp_v3_t22_group_record1_src_addr1_3
    global l3_igmp_v3_t22_group_record1_src_addr1_4

    global l3_igmp_v3_t22_group_record1_src_addr2_1
    global l3_igmp_v3_t22_group_record1_src_addr2_2
    global l3_igmp_v3_t22_group_record1_src_addr2_3
    global l3_igmp_v3_t22_group_record1_src_addr2_4

    global l3_igmp_v3_t22_group_record1_src_addr3_1
    global l3_igmp_v3_t22_group_record1_src_addr3_2
    global l3_igmp_v3_t22_group_record1_src_addr3_3
    global l3_igmp_v3_t22_group_record1_src_addr3_4

    global l3_igmp_v3_t22_group_record1_src_addr4_1
    global l3_igmp_v3_t22_group_record1_src_addr4_2
    global l3_igmp_v3_t22_group_record1_src_addr4_3
    global l3_igmp_v3_t22_group_record1_src_addr4_4

    global l3_igmp_v3_t22_group_record1_src_addr5_1
    global l3_igmp_v3_t22_group_record1_src_addr5_2
    global l3_igmp_v3_t22_group_record1_src_addr5_3
    global l3_igmp_v3_t22_group_record1_src_addr5_4

    l3_ip_v4_saddr = inet_aton(l3_ip_v4_source)
    l3_ip_v4_daddr = inet_aton(l3_ip_v4_dest)
    l3_ip_v4_ihl_ver = (l3_ip_v4_ver << 4) + l3_ip_v4_ihl

    l2_header = pack('!BBBBBBBBBBBBH',\
                 l2_dst_addr1,\
                 l2_dst_addr2,\
                 l2_dst_addr3,\
                 l2_dst_addr4,
                 l2_dst_addr5,
                 l2_dst_addr6,
                 l2_src_addr1,
                 l2_src_addr2,
                 l2_src_addr3,
                 l2_src_addr4,
                 l2_src_addr5,
                 l2_src_addr6,
                 l2_ether_type)

    l3_ip_v4_header = pack('!BBHHHBBH4s4s',\
                 l3_ip_v4_ihl_ver,\
                 l3_ip_v4_tos,\
                 l3_ip_v4_tot_len,\
                 l3_ip_v4_id,\
                 l3_ip_v4_frag_off,\
                 l3_ip_v4_ttl,\
                 l3_ip_v4_proto,\
                 l3_ip_v4_check,\
                 l3_ip_v4_saddr,\
                 l3_ip_v4_daddr)

    l3_igmp_v3_t22_prefix = pack('!BBHHH',\
                 l3_igmp_v3_t22_type,\
                 l3_igmp_v3_t22_reserved,\
                 l3_igmp_v3_t22_check,\
                 l3_igmp_v3_t22_reserved,\
                 l3_igmp_v3_t22_num_of_grp_rec)

    l3_igmp_v3_t22_group_record1_src_addr1 = pack('!BBBB',\
                l3_igmp_v3_t22_group_record1_src_addr1_1,\
                l3_igmp_v3_t22_group_record1_src_addr1_2,\
                l3_igmp_v3_t22_group_record1_src_addr1_3,\
                l3_igmp_v3_t22_group_record1_src_addr1_4)

    l3_igmp_v3_t22_group_record1_src_addr2 = pack('!BBBB',\
                l3_igmp_v3_t22_group_record1_src_addr2_1,\
                l3_igmp_v3_t22_group_record1_src_addr2_2,\
                l3_igmp_v3_t22_group_record1_src_addr2_3,\
                l3_igmp_v3_t22_group_record1_src_addr2_4)

    l3_igmp_v3_t22_group_record1_src_addr3 = pack('!BBBB',\
                l3_igmp_v3_t22_group_record1_src_addr3_1,\
                l3_igmp_v3_t22_group_record1_src_addr3_2,\
                l3_igmp_v3_t22_group_record1_src_addr3_3,\
                l3_igmp_v3_t22_group_record1_src_addr3_4)

    l3_igmp_v3_t22_group_record1_src_addr4 = pack('!BBBB',\
                l3_igmp_v3_t22_group_record1_src_addr4_1,\
                l3_igmp_v3_t22_group_record1_src_addr4_2,\
                l3_igmp_v3_t22_group_record1_src_addr4_3,\
                l3_igmp_v3_t22_group_record1_src_addr4_4)

    l3_igmp_v3_t22_group_record1_src_addr5 = pack('!BBBB',\
                l3_igmp_v3_t22_group_record1_src_addr5_1,\
                l3_igmp_v3_t22_group_record1_src_addr5_2,\
                l3_igmp_v3_t22_group_record1_src_addr5_3,\
                l3_igmp_v3_t22_group_record1_src_addr5_4)

    l3_igmp_v3_t22_group_record1 = pack('!BBHBBBB',\
                l3_igmp_v3_t22_group_record1_rec_type,\
                l3_igmp_v3_t22_group_record1_aux_data_len,\
                l3_igmp_v3_t22_group_record1_num_of_src,\
                l3_igmp_v3_t22_group_record1_milticast_addr1,\
                l3_igmp_v3_t22_group_record1_milticast_addr2,\
                l3_igmp_v3_t22_group_record1_milticast_addr3,\
                l3_igmp_v3_t22_group_record1_milticast_addr4)

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 1):
        l3_igmp_v3_t22_group_record1 = l3_igmp_v3_t22_group_record1 + l3_igmp_v3_t22_group_record1_src_addr1

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 2):
        l3_igmp_v3_t22_group_record1 = l3_igmp_v3_t22_group_record1 + l3_igmp_v3_t22_group_record1_src_addr2

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 3):
        l3_igmp_v3_t22_group_record1 = l3_igmp_v3_t22_group_record1 + l3_igmp_v3_t22_group_record1_src_addr3

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 4):
        l3_igmp_v3_t22_group_record1 = l3_igmp_v3_t22_group_record1 + l3_igmp_v3_t22_group_record1_src_addr4

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 5):
        l3_igmp_v3_t22_group_record1 = l3_igmp_v3_t22_group_record1 + l3_igmp_v3_t22_group_record1_src_addr5

    if(l3_igmp_v3_t22_group_record1_num_of_src >= 6):
        print("Support only 5 source addresses")

    l3_igmp_v3_t22 = l3_igmp_v3_t22_prefix + l3_igmp_v3_t22_group_record1

    l3_igmp_data = l3_igmp_v3_t22

    # IGMP checksum calculate
    
    l3_igmp_v3_t22_check = htons(checksum(l3_igmp_v3_t22))
    
    l3_igmp_v3_t22_prefix = pack('!BBHHH',\
                 l3_igmp_v3_t22_type,\
                 l3_igmp_v3_t22_reserved,\
                 l3_igmp_v3_t22_check,\
                 l3_igmp_v3_t22_reserved,\
                 l3_igmp_v3_t22_num_of_grp_rec)
                 
    l3_igmp_v3_t22 = l3_igmp_v3_t22_prefix + l3_igmp_v3_t22_group_record1

    l3_igmp_data = l3_igmp_v3_t22
    
    s = socket(AF_PACKET, SOCK_RAW)

    s.bind((common_interface, 0))

    s.send(l2_header + l3_ip_v4_header + l3_igmp_data)

# ------------------------------------------------------------------------------
# Function: main
# Description:
# ------------------------------------------------------------------------------
def main():
    global common_interface

    global l3_ip_v4_source
    global l3_ip_v4_dest

    global l3_ip_v4_ttl

    global l2_src_addr1 
    global l2_src_addr2
    global l2_src_addr3
    global l2_src_addr4
    global l2_src_addr5
    global l2_src_addr6

    global l2_dst_addr1
    global l2_dst_addr2
    global l2_dst_addr3
    global l2_dst_addr4
    global l2_dst_addr5
    global l2_dst_addr6

    global l3_igmp_v3_t22_group_record1_rec_type

    global l3_igmp_v3_t22_group_record1_milticast_addr1
    global l3_igmp_v3_t22_group_record1_milticast_addr2
    global l3_igmp_v3_t22_group_record1_milticast_addr3
    global l3_igmp_v3_t22_group_record1_milticast_addr4

    global l3_igmp_v3_t22_group_record1_num_of_src

    global l3_igmp_v3_t22_group_record1_src_addr1_1
    global l3_igmp_v3_t22_group_record1_src_addr1_2
    global l3_igmp_v3_t22_group_record1_src_addr1_3
    global l3_igmp_v3_t22_group_record1_src_addr1_4

    global l3_igmp_v3_t22_group_record1_src_addr2_1
    global l3_igmp_v3_t22_group_record1_src_addr2_2
    global l3_igmp_v3_t22_group_record1_src_addr2_3
    global l3_igmp_v3_t22_group_record1_src_addr2_4

    global l3_igmp_v3_t22_group_record1_src_addr3_1
    global l3_igmp_v3_t22_group_record1_src_addr3_2
    global l3_igmp_v3_t22_group_record1_src_addr3_3
    global l3_igmp_v3_t22_group_record1_src_addr3_4

    global l3_igmp_v3_t22_group_record1_src_addr4_1
    global l3_igmp_v3_t22_group_record1_src_addr4_2
    global l3_igmp_v3_t22_group_record1_src_addr4_3
    global l3_igmp_v3_t22_group_record1_src_addr4_4

    global l3_igmp_v3_t22_group_record1_src_addr5_1
    global l3_igmp_v3_t22_group_record1_src_addr5_2
    global l3_igmp_v3_t22_group_record1_src_addr5_3
    global l3_igmp_v3_t22_group_record1_src_addr5_4

    try:
        opts, args = getopt.getopt(sys.argv[1:], "hvali:",\
              ["help",\
              "version",\
              "authors",\
              "license",\
              "interface=",\
              "ip-src=",\
              "ip-dst=",\
              "mac-src=",\
              "mac-dst=",\
              "ttl=",\
              "gr1-rec-type=",\
              "gr1-mult-addr=",\
              "gr1-num-of-src=",\
              "gr1-src-addr1=",\
              "gr1-src-addr2=",\
              "gr1-src-addr3=",\
              "gr1-src-addr4=",\
              "gr1-src-addr5="] )
    except getopt.GetoptError as err:
        print(err) # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

    for o, a in opts:
        if o == "-v":
            version()
            sys.exit()
        elif o in ("-a", "--authors"):
            authors()
            sys.exit()
        elif o in ("-h", "--help"):
            help()
            sys.exit()
        elif o in ("-v", "--version"):
            version()
            sys.exit()
        elif o in ("-l", "--license"):
            license()
            sys.exit()
        elif o in ("-i", "--interface"):
            common_interface = a
        elif o in ("--ip-src"):
            l3_ip_v4_source = a
        elif o in ("--ip-dst"):
            l3_ip_v4_dest = a
        elif o in ("--mac-src"):
            mac_src = a.split(':')

            l2_src_addr1 = int(mac_src[0], 16)
            l2_src_addr2 = int(mac_src[1], 16)
            l2_src_addr3 = int(mac_src[2], 16)
            l2_src_addr4 = int(mac_src[3], 16)
            l2_src_addr5 = int(mac_src[4], 16)
            l2_src_addr6 = int(mac_src[5], 16)
        elif o in ("--mac-dst"):
            mac_dst = a.split(":")

            l2_dst_addr1 = int(mac_dst[0], 16)
            l2_dst_addr2 = int(mac_dst[1], 16)
            l2_dst_addr3 = int(mac_dst[2], 16)
            l2_dst_addr4 = int(mac_dst[3], 16)
            l2_dst_addr5 = int(mac_dst[4], 16)
            l2_dst_addr6 = int(mac_dst[5], 16)
        elif o in ("--ttl"):
            l3_ip_v4_ttl = int(a, 10)
        elif o in ("--gr1-rec-type"):
            l3_igmp_v3_t22_group_record1_rec_type = int(a, 16)
        elif o in ("--gr1-mult-addr"):
            gr1_milticast_address = a.split(".")

            l3_igmp_v3_t22_group_record1_milticast_addr1 = int(gr1_milticast_address[0], 10)
            l3_igmp_v3_t22_group_record1_milticast_addr2 = int(gr1_milticast_address[1], 10)
            l3_igmp_v3_t22_group_record1_milticast_addr3 = int(gr1_milticast_address[2], 10)
            l3_igmp_v3_t22_group_record1_milticast_addr4 = int(gr1_milticast_address[3], 10)
        elif o in ("--gr1-num-of-src"):
            if(int(a, 10) > 5):
                print("Support only 5 source addresses")
                sys.exit()

            l3_igmp_v3_t22_group_record1_num_of_src = int(a, 10)
        elif o in ("--gr1-src-addr1"):
            gr1_source_address1 = a.split(".")

            l3_igmp_v3_t22_group_record1_src_addr1_1 = int(gr1_source_address1[0], 10)
            l3_igmp_v3_t22_group_record1_src_addr1_2 = int(gr1_source_address1[1], 10)
            l3_igmp_v3_t22_group_record1_src_addr1_3 = int(gr1_source_address1[2], 10)
            l3_igmp_v3_t22_group_record1_src_addr1_4 = int(gr1_source_address1[3], 10)
        elif o in ("--gr1-src-addr2"):
            gr1_source_address2 = a.split(".")

            l3_igmp_v3_t22_group_record1_src_addr2_1 = int(gr1_source_address2[0], 10)
            l3_igmp_v3_t22_group_record1_src_addr2_2 = int(gr1_source_address2[1], 10)
            l3_igmp_v3_t22_group_record1_src_addr2_3 = int(gr1_source_address2[2], 10)
            l3_igmp_v3_t22_group_record1_src_addr2_4 = int(gr1_source_address2[3], 10)
        elif o in ("--gr1-src-addr3"):
            gr1_source_address3 = a.split(".")

            l3_igmp_v3_t22_group_record1_src_addr3_1 = int(gr1_source_address3[0], 10)
            l3_igmp_v3_t22_group_record1_src_addr3_2 = int(gr1_source_address3[1], 10)
            l3_igmp_v3_t22_group_record1_src_addr3_3 = int(gr1_source_address3[2], 10)
            l3_igmp_v3_t22_group_record1_src_addr3_4 = int(gr1_source_address3[3], 10)
        elif o in ("--gr1-src-addr4"):
            gr1_source_address4 = a.split(".")

            l3_igmp_v3_t22_group_record1_src_addr4_1 = int(gr1_source_address4[0], 10)
            l3_igmp_v3_t22_group_record1_src_addr4_2 = int(gr1_source_address4[1], 10)
            l3_igmp_v3_t22_group_record1_src_addr4_3 = int(gr1_source_address4[2], 10)
            l3_igmp_v3_t22_group_record1_src_addr4_4 = int(gr1_source_address4[3], 10)
        elif o in ("--gr1-src-addr5"):
            gr1_source_address5 = a.split(".")

            l3_igmp_v3_t22_group_record1_src_addr5_1 = int(gr1_source_address5[0], 10)
            l3_igmp_v3_t22_group_record1_src_addr5_2 = int(gr1_source_address5[1], 10)
            l3_igmp_v3_t22_group_record1_src_addr5_3 = int(gr1_source_address5[2], 10)
            l3_igmp_v3_t22_group_record1_src_addr5_4 = int(gr1_source_address5[3], 10)

        else:
            assert False, "unhandled option"

    data_send()    
    
# ------------------------------------------------------------------------------
# Run
# ------------------------------------------------------------------------------
main()

# ******************************************************************************
# End of file
# ******************************************************************************

I try to run program with --help option:
bodro@vbodrov-pc:~/workspace/develop/igmp_generator/igmp_generator_0.11$ ./igmp_generator.py --help
Program: ./igmp_generator.py
version 0.11 (Hydrocyclone-2)
IGMP packet generator for IPv4
Note: This version support only IGMPv3 (over IPv4) and packet type 0x22 (Membership Report Message)
Limits: Max group: 1. Max source in group: 5.

./igmp_generator.py [OPTIONS]

-h,     --help                          - show this help and exit
-v,     --version                       - show version and exit
-a,     --authors                       - show authors and exit
-l,     --license                       - show license and exit
-i,     --interface=INTERFACE           - network interface (default: eth0)
        --ip-src=IP                     - source IP-address (default: 192.168.0.1)
        --ip-dst=IP                     - destination IP-address (default: 224.0.0.22)
        --mac-src=MAC                   - source MAC-address (default: 02:01:02:03:04:05)
        --mac-dst=MAC                   - destination MAC-address (default: 01:02:03:04:05:06)
        --ttl=NUM                       - time to live (default: 1)
        --gr1-rec-type=NUM              - record type (group record 1) (default: 0)
        --gr1-mult-addr=IP              - multicast (group) address (group record 1) (default: 224.1.1.1)
        --gr1-num-of-src=NUM            - number of sources (group record 1) (default: 1)
        --gr1-src-addr1=IP              - source address 1 (group record 1) (default: 192.168.1.1)
        --gr1-src-addr2=IP              - source address 2 (group record 1) (default: 192.168.1.2)
        --gr1-src-addr3=IP              - source address 3 (group record 1) (default: 192.168.1.3)
        --gr1-src-addr4=IP              - source address 4 (group record 1) (default: 192.168.1.4)
        --gr1-src-addr5=IP              - source address 5 (group record 1) (default: 192.168.1.5)

Record type:

0 - Unknown (0x00)
1 - Mode Is Include (0x01)
2 - Mode Is Exclude (0x02)
3 - Change To Include Mode (0x03)
4 - Change To Exclude Mode (0x04)
5 - Allow New Sources (0x05)
6 - Block Old Sources (0x06)

Example: 
        # ./igmp_generator.py \
                --interface=eth0 \
                --ip-src="200.100.1.1" \
                --ip-dst="224.0.0.22" \
                --mac-src="23:A1:01:02:02:05" \
                --mac-dst="F0:FA:00:05:07:FF" \
                --gr1-rec-type="2" \
                --gr1-mult-addr="225.1.2.3" \
                --gr1-num-of-src=5 \
                --gr1-src-addr1="127.0.0.1" \
                --gr1-src-addr2="127.0.0.2" \
                --gr1-src-addr3="127.0.0.3" \
                --gr1-src-addr4="127.0.0.4" \
                --gr1-src-addr5="127.0.0.5" \
                --ttl=1
bodro@vbodrov-pc:~/workspace/develop/igmp_generator/igmp_generator_0.11$

I try to run program with --license option:
bodro@vbodrov-pc:~/workspace/develop/igmp_generator/igmp_generator_0.11$ ./igmp_generator.py --license
Program: ./igmp_generator.py
version 0.11 (Hydrocyclone-2)
IGMP packet generator for IPv4
Note: This version support only IGMPv3 (over IPv4) and packet type 0x22 (Membership Report Message)
Limits: Max group: 1. Max source in group: 5.

The MIT License (MIT)

Copyright (c) 2015 IPB Software (Vasiliy V. Bodrov aka Bodro)

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
bodro@vbodrov-pc:~/workspace/develop/igmp_generator/igmp_generator_0.11$

You must know that IGMP generator both versions is my first Python programs. Be lenient :)

See ya! :)

Best regards,
Vasiliy V. Bodrov aka Bodro,
the 10-th of May, 2017 year.

No comments:

Post a Comment

How to reverse singly linked list in C (trivial way)

There is a beautiful morning. It's snowing. And I decided to write one more article. Today it will be just simple article where I would...