Coder Social home page Coder Social logo

smrt's Introduction

smrt

A utility to configure your TP-Link Easy Smart Switch on Linux or Mac OS X. This tool is written in Python.

Supposedly supported switches:

  • TL-SG105E (tested)
  • TL-SG108E (tested)
  • TL-SG108PE
  • TL-SG1016DE (tested)
  • TL-SG1024DE

Discover switches

Simple discovery

$ ./discovery.py

Multiple interfaces

If more than one interface, error message gives the list:

Error: more than 1 interface. Use -i or --interface to specify the name
Interfaces:
    'enp3s0'
    'virbr0'
    'virbr0-nic'

Default output

Give the right interface:

$ ./discovery.py -i enp3s0

Output (found 2 switches):

192.168.9.36
ba.ff.ee.ff.ac.ee
(1, 'type', 'TL-SG108E')
(2, 'hostname', 'sg108ev4')
(3, 'mac', '01:01:01:01:01:01')
(7, 'firmware', '1.0.0 Build 20181120 Rel.40749')
(8, 'hardware', 'TL-SG108E 4.0')
(9, 'dhcp', False)
(4, 'ip_addr', IPv4Address('192.168.9.202'))
(5, 'ip_mask', IPv4Address('255.255.255.0'))
(6, 'gateway', IPv4Address('192.168.9.1'))
(13, 'auto_save', True)
----------------
(1, 'type', 'TL-SG108E')
(2, 'hostname', 'sg108ev1')
(3, 'mac', '02:02:02:02:02:02')
(7, 'firmware', '1.1.2 Build 20141017 Rel.50749')
(8, 'hardware', 'TL-SG108E 1.0')
(9, 'dhcp', False)
(4, 'ip_addr', IPv4Address('192.168.9.203'))
(5, 'ip_mask', IPv4Address('255.255.255.0'))
(6, 'gateway', IPv4Address('192.168.9.1'))

Command output with -c

With switch -c or --command, output gives the syntax for using smrt with right arguments

$ ./discovery.py -i enp3s0 -c
./smrt.py --username admin --password admin -i enp3s0 --switch-mac 01:01:01:01:01:01
./smrt.py --username admin --password admin -i enp3s0 --switch-mac 02:02:02:02:02:02

Alias

After discovery, setting an shell alias reduces command size

$ alias smrt='python ~/smrt/smrt.py --switch-mac 60:E3:27:83:25:3F  -i eth0 --username admin --password admin'

smrt.py

without command gives list of command

$ ./smrt.py --username admin --password admin --interface==eth0 --switch-mac 01:01:01:01:01:01
Actions: type hostname mac ip_addr ip_mask gateway firmware hardware dhcp num_ports v4 username password save get_token_id igmp_snooping ports trunk mtu_vlan vlan_enabled vlan pvid vlan_filler qos1 qos2 mirror stats loop_prev

vlan

$ smrt vlan # use alias

(8704, 'vlan_enabled', '01')
(8705, 'vlan', [1, '1,2,3,4,5,6,7,8', '', 'Default_VLAN'])
(8705, 'vlan', [90, '1,2,3,4,5,6,7,8', '', 'LAN'])
(8705, 'vlan', [100, '1,2,3', '1', 'vlan_test_1'])
(8707, 'vlan_filler', ' ')

pvid

$ smrt pvid
(8706, 'pvid', (1, 90))
(8706, 'pvid', (2, 90))
(8706, 'pvid', (3, 90))
(8706, 'pvid', (4, 90))
(8706, 'pvid', (5, 90))
(8706, 'pvid', (6, 90))
(8706, 'pvid', (7, 90))
(8706, 'pvid', (8, 90))
(8707, 'vlan_filler', ' ')

stats

$ smrt stats
(16384, 'stats', (1, 1, 6, 48, 0, 6356, 14))
(16384, 'stats', (2, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (3, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (4, 1, 5, 6404, 0, 0, 14))
(16384, 'stats', (5, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (6, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (7, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (8, 1, 0, 0, 0, 0, 0))

smrt ports

$ smrt ports
(4096, 'ports', '01:01:00:01:06:00:00')
(4096, 'ports', '02:01:00:01:00:00:00')
(4096, 'ports', '03:01:00:01:00:00:00')
(4096, 'ports', '04:01:00:01:05:00:00')
(4096, 'ports', '05:01:00:01:00:00:00')
(4096, 'ports', '06:01:00:01:00:00:00')
(4096, 'ports', '07:01:00:01:00:00:00')
(4096, 'ports', '08:01:00:01:00:00:00')

Set VLAN settings

Syntax

smrt.py shows parameters and can change them for VLANs if --vlan is present

Specific VLAN parameters:

  • --vlan: vlan number (1-4093)
  • --vlan_name: acceptable vlan name for TP-Link switch
  • --vlan_member: comma separated list without space of member ports. Ex: 1,2,4
  • --vlan_tagged: comma separated list without space of tagged ports. Ex: 1,2
  • --vlan_pvid: set pvid to --vlan for given ports

Example 1 : add new vlan 120

$ smrt vlan
(8704, 'vlan_enabled', '01')
(8705, 'vlan', [1, '1,2,3,4,5,6,7,8', '', 'Default_VLAN'])
(8705, 'vlan', [90, '1,2,3,4,5,6,7,8', '', 'LAN'])
(8705, 'vlan', [100, '1,2,3', '1', 'vlan_test_1'])
(8707, 'vlan_filler', ' ')
$ smrt vlan --vlan 120 --vlan_name "vlan_test_2" --vlan_member 1,4,5,6 --vlan_tagged 1
(8704, 'vlan_enabled', '01')
(8705, 'vlan', [1, '1,2,3,4,5,6,7,8', '', 'Default_VLAN'])
(8705, 'vlan', [90, '1,2,3,4,5,6,7,8', '', 'LAN'])
(8705, 'vlan', [100, '1,2,3', '1', 'vlan_test_1'])
(8705, 'vlan', [120, '1,4,5,6', '1', 'vlan_test_2'])
(8707, 'vlan_filler', ' ')

Example 2 : change to pvid 120 for ports 5 and 6

Note : vlan must exist (see example 1) before this command.

$ smrt pvid
(8706, 'pvid', (1, 90))
(8706, 'pvid', (2, 90))
(8706, 'pvid', (3, 90))
(8706, 'pvid', (4, 90))
(8706, 'pvid', (5, 90))
(8706, 'pvid', (6, 90))
(8706, 'pvid', (7, 90))
(8706, 'pvid', (8, 90))
(8707, 'vlan_filler', ' ')
$ smrt vlan --vlan 120 --vlan_pvid 5,6
(8706, 'pvid', (1, 90))
(8706, 'pvid', (2, 90))
(8706, 'pvid', (3, 90))
(8706, 'pvid', (4, 90))
(8706, 'pvid', (5, 120))
(8706, 'pvid', (6, 120))
(8706, 'pvid', (7, 90))
(8706, 'pvid', (8, 90))
(8707, 'vlan_filler', ' ')

Exemple 3 : remove vlan 120

$ smrt vlan --vlan 120 --delete
(8704, 'vlan_enabled', '01')
(8705, 'vlan', [1, '1,2,3,4,5,6,7,8', '', 'Default_VLAN'])
(8705, 'vlan', [90, '1,2,3,4,5,6,7,8', '', 'LAN'])
(8705, 'vlan', [100, '1,2,3', '1', 'vlan_test_1'])
(8707, 'vlan_filler', ' ')

Note that, for PVID, corresponding ports are reinitialized to vlan 1:

$ smrt pvid
(8706, 'pvid', (1, 90))
(8706, 'pvid', (2, 90))
(8706, 'pvid', (3, 90))
(8706, 'pvid', (4, 90))
(8706, 'pvid', (5, 1))
(8706, 'pvid', (6, 1))
(8706, 'pvid', (7, 90))
(8706, 'pvid', (8, 90))
(8707, 'vlan_filler', ' ')

Exemple 4 : add new vlan and pvid

$ smrt vlan --vlan 130 --vlan_name "vlan_test_3" --vlan_member 1,4,5,6 --vlan_tagged 1 --vlan_pvid 4,5,6
(8704, 'vlan_enabled', '01')
(8705, 'vlan', [1, '1,2,3,4,5,6,7,8', '', 'Default_VLAN'])
(8705, 'vlan', [90, '1,2,3,4,5,6,7,8', '', 'LAN'])
(8705, 'vlan', [100, '1,2,3', '1', 'vlan_test_1'])
(8705, 'vlan', [130, '1,4,5,6', '1', 'vlan_test_3'])
(8707, 'vlan_filler', ' ')
(8706, 'pvid', (1, 90))
(8706, 'pvid', (2, 90))
(8706, 'pvid', (3, 90))
(8706, 'pvid', (4, 130))
(8706, 'pvid', (5, 130))
(8706, 'pvid', (6, 130))
(8706, 'pvid', (7, 90))
(8706, 'pvid', (8, 90))
(8707, 'vlan_filler', ' ')

smrt's People

Contributors

ngardiner avatar philippechataignon avatar pklaus avatar rgl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

smrt's Issues

Insufficient validation of responses

This code uses a UDP request-response pattern, but the response is not validated to be one that matches the request. The code should be checking:

  • sequence number in response matches the request
  • the host_mac in response matches the request
  • responses are not duplicates (can happen if machine has >1 NIC on the same network - eg ethernet + wifi)

Inconsistent results - sometimes none?

Running
smrt stats -i en12 -l debug --switch-mac b4:b0:24:3a:f1:3b --username admin --password removed

Sometimes it works, sometimes no results are returned. Examples of each below

DEBUG:network:Sending Packet: 0101b4b0243af13b4865ee186f5a00d6000000000028000000000f5e0000000040000000ffff0000
DEBUG:network:Sending Header:  {'version': 1, 'op_code': 1, 'switch_mac': b'\xb4\xb0$:\xf1;', 'host_mac': b'He\xee\x18oZ', 'sequence_id': 214, 'error_code': 0, 'check_length': 40, 'fragment_offset': 0, 'flag': 0, 'token_id': 3934, 'checksum': 0}
DEBUG:network:Sending Payload: [(16384, b'')]

DEBUG:network:Receive Packet: 0104b4b0243af13b4865ee186f5a00d5000000000024000000000f5e00000000ffff0000
DEBUG:network:Received Header:  {'version': 1, 'op_code': 4, 'switch_mac': b'\xb4\xb0$:\xf1;', 'host_mac': b'He\xee\x18oZ', 'sequence_id': 213, 'error_code': 0, 'check_length': 36, 'fragment_offset': 0, 'flag': 0, 'token_id': 3934, 'checksum': 0}
DEBUG:network:Received Payload: []

===

DEBUG:network:Sending Packet: 0101b4b0243af13b4865ee186f5a031f000000000028000000004b180000000040000000ffff0000
DEBUG:network:Sending Header:  {'version': 1, 'op_code': 1, 'switch_mac': b'\xb4\xb0$:\xf1;', 'host_mac': b'He\xee\x18oZ', 'sequence_id': 799, 'error_code': 0, 'check_length': 40, 'fragment_offset': 0, 'flag': 0, 'token_id': 19224, 'checksum': 0}
DEBUG:network:Sending Payload: [(16384, b'')]
DEBUG:network:Receive Packet: 0102b4b0243af13b4865ee186f5a031f000000000097000000004b18000000004000001301010509ca533800000000181f828c000000004000001302010000e2f7a300000000008b4f390000000040000013030100001060fc0000000000004cd400000000400000130401060137af3d0000000000b2b8d8000000004000001305010618d604d5000000000accd9a400000001ffff0000
DEBUG:network:Received Header:  {'version': 1, 'op_code': 2, 'switch_mac': b'\xb4\xb0$:\xf1;', 'host_mac': b'He\xee\x18oZ', 'sequence_id': 799, 'error_code': 0, 'check_length': 151, 'fragment_offset': 0, 'flag': 0, 'token_id': 19224, 'checksum': 0}
DEBUG:network:Received Payload: [(16384, 'stats', (1, 1, 5, 164254520, 0, 404718220, 0)), (16384, 'stats', (2, 1, 0, 14874531, 0, 9129785, 0)), (16384, 'stats', (3, 1, 0, 1073404, 0, 19668, 0)), (16384, 'stats', (4, 1, 6, 20426557, 0, 11712728, 0)), (16384, 'stats', (5, 1, 6, 416679125, 0, 181197220, 1))]
(16384, 'stats', (1, 1, 5, 164254520, 0, 404718220, 0))
(16384, 'stats', (2, 1, 0, 14874531, 0, 9129785, 0))
(16384, 'stats', (3, 1, 0, 1073404, 0, 19668, 0))
(16384, 'stats', (4, 1, 6, 20426557, 0, 11712728, 0))
(16384, 'stats', (5, 1, 6, 416679125, 0, 181197220, 1))

Traffic counters show negative number - signed/unsigned int?

smrt stats:

(16384, 'stats', (1, 1, 0, 19074485, 0, 42713806, 0))
(16384, 'stats', (2, 1, 6, 37201512, 0, 81464339, 7))
(16384, 'stats', (3, 1, 0, 65589148, 0, 22155383, 0))
(16384, 'stats', (4, 1, 0, 259060699, 0, 154787269, 0))
(16384, 'stats', (5, 1, 6, -966287098, 0, 1453967463, 0))
(16384, 'stats', (6, 1, 0, 1167324174, 0, -1551372182, 13))
(16384, 'stats', (7, 1, 0, 0, 0, 0, 0))
(16384, 'stats', (8, 1, 6, 364339421, 0, 676728603, 0))

vs

image

Cannot run discovery.py on mac (wifi or eth) - Can't assign requested address

Should discovery work on wifi?

❯ python3 ./discovery.py -i en0
Traceback (most recent call last):
  File "/Users/simonroberts/src/github/philippechataignon/smrt/./discovery.py", line 47, in <module>
    main()
  File "/Users/simonroberts/src/github/philippechataignon/smrt/./discovery.py", line 33, in main
    switches = discover_switches(args.interface)
  File "/Users/simonroberts/src/github/philippechataignon/smrt/./discovery.py", line 14, in discover_switches
    net = Network(interface)
  File "/Users/simonroberts/src/github/philippechataignon/smrt/network.py", line 64, in __init__
    self.rs.bind((Network.BROADCAST_ADDR, Network.UDP_RECEIVE_FROM_PORT))
OSError: [Errno 49] Can't assign requested address

System is

❯ uname -a
Darwin simonmac.roberts 22.2.0 Darwin Kernel Version 22.2.0: Fri Nov 11 02:08:47 PST 2022; root:xnu-8792.61.2~4/RELEASE_X86_64 x86_64

Ventura 13.1 (22C65)

I guess I don't know how this works - was assuming it was either via web-scraping, or some magic API. Will try on a real linux box.

Publish code as a library I can "pip install"

This would make the code usable by other projects. Unless there's an alternative I haven't found yet?

❯ pip install https://github.com/philippechataignon/smrt/archive/refs/tags/v1.0.tar.gz
Collecting https://github.com/philippechataignon/smrt/archive/refs/tags/v1.0.tar.gz
  Downloading https://github.com/philippechataignon/smrt/archive/refs/tags/v1.0.tar.gz
     - 7.1 kB 16.7 MB/s 0:00:00
ERROR: https://github.com/philippechataignon/smrt/archive/refs/tags/v1.0.tar.gz does not appear to be a Python project: neither 'setup.py' nor 'pyproject.toml' found.

Add ability to decode raw data results into meaningful key:value

At the moment commands like "smrt stats" return a bunch of numbers without any idea what they mean.

(16384, 'stats', (1, 1, 5, 67622004, 0, 166630038, 0))
(16384, 'stats', (2, 1, 0, 14874531, 0, 9129785, 0))
(16384, 'stats', (3, 1, 0, 1073404, 0, 19668, 0))
(16384, 'stats', (4, 1, 6, 8108486, 0, 4382321, 0))
(16384, 'stats', (5, 1, 6, 170911760, 0, 76011246, 1))

It would be nice if there was a version/variant that attempted to decode these into a semantic response. This response in the upstream repo points to a bunch of useful data in PHP? pklaus#4

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.