├── .gitignore
├── LICENSE
├── README.md
├── ansible
├── README.md
└── plugins
│ └── modules
│ └── switch_port.py
├── powershell
└── MikrotikPSwitchOS
│ ├── MikrotikPSwitchOS.psd1
│ ├── MikrotikPSwitchOS.psm1
│ ├── README.md
│ ├── private
│ ├── Convert-MikrotikLinkSpeed.ps1
│ ├── Convert-MikrotikLinks.ps1
│ ├── Convert-MikrotikPoE.ps1
│ ├── Convert-MikrotikPoEHexCodes.ps1
│ ├── Convert-MikrotikSFP.ps1
│ ├── Convert-MikrotikVLAN.ps1
│ ├── Convert-MikrotikVLANConfig.ps1
│ ├── Convert-MikrotikVLANHexCodes.ps1
│ ├── ConvertFrom-ArrayToHex.ps1
│ ├── ConvertFrom-HexToArray.ps1
│ ├── ConvertFrom-HexToBinary.ps1
│ ├── ConvertFrom-HexToInt.ps1
│ ├── ConvertFrom-HexToString.ps1
│ ├── ConvertFrom-IntToHex.ps1
│ ├── ConvertFrom-MikrotikToJson.ps1
│ └── ConvertFrom-StringToHex.ps1
│ └── public
│ ├── Get-MikrotikLinks.ps1
│ ├── Get-MikrotikPoE.ps1
│ ├── Get-MikrotikSFP.ps1
│ ├── Get-MikrotikTotalPorts.ps1
│ ├── Get-MikrotikVLANConfig.ps1
│ ├── Get-MikrotikVLANs.ps1
│ ├── Invoke-MikrotikRestMethod.ps1
│ ├── Set-MikrotikSwitchPort.ps1
│ └── Set-MikrotikVLAN.ps1
└── python
└── mikrotik_switch_api.py
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ollie-galbraith/mikrotik_switch_api/0cac203a28973cca23e3a13e2d49a78c1a89b462/.gitignore
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 ollie-galbraith
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mikrotik SwitchOS API
2 |
3 | ### Built With
4 | ![PowerShell][powershell-badge]
5 | ![Python][python-badge]
6 | ![Ansible][ansible-badge]
7 |
8 | For a project that I'm working on I needed to have access to programatically and automatically update my SwitchOS config on the fly. After a little bit of digging it turns out that the backend of SwitchOS uses a fairly basic (but non-human readable) API (with some accompanying JavaScript).
9 |
10 | After lots of clicking buttons, changing text, and playing around with Firefox Debug panel, I have reverse engineered the API from hex and binary to integers and strings. At least I reverse engineered the main pages haha.
11 |
12 | This is a repo containing a Powershell Module and basic Python/Ansible code to make the correct calls to the API.
13 |
14 | ## Usage
15 |
16 | #### Powershell
17 | Refer to the [Powershell README.md](/powershell/MikrotikPSwitchOS/README.md)
18 |
19 | #### Python
20 | The Python code is a simple port of the Powershell, and has the same structure/function. I am still learning to get around Python, so please forgive any "non-pythonic" code that there might be, or the lack of a proper package.
21 |
22 | #### Ansible
23 | Refer to the [Ansible README.md](/ansible/README.md)
24 |
25 | ## FAQ
26 |
27 | #### How does the API work
28 |
29 | While I dont know the ins and outs of the inner workings of the API, there is enough information from the JSON-like responses depending on the request that its easy enough to reverse engineer.
30 |
31 | It is mostly hex numbers and bitmasks, which need to be converted to be able to read them as a human. Thanks to this [forum post](https://forum.mikrotik.com/viewtopic.php?t=172802) for the basic information to get going
32 |
33 | ## To Note
34 | This is a side project for me, and I have only manaaged to test the code on three switch models
35 | - [CRS328-24P-4S+RM](https://mikrotik.com/product/crs328_24p_4s_rm)
36 | - [CRS309-1G-8S+IN](https://mikrotik.com/product/crs309_1g_8s_in)
37 | - [CSS326-24G-2S+RM](https://mikrotik.com/product/CSS326-24G-2SplusRM)
38 |
39 | There are bound to be some bugs with the code.
40 | There is a possiblity that if an incorrect config is sent to the switch, it can corrupt and only be saved with a hard reboot. So please practice backups.
41 |
42 | [ansible-badge]: https://shields.io/badge/ansible-20232A?style=for-the-badge&logo=ansible&logoColor=ff5750
43 | [python-badge]: https://shields.io/badge/python-20232A?style=for-the-badge&logo=python&logoColor=61DAFB
44 | [powershell-badge]: https://shields.io/badge/powershell-20232A?style=for-the-badge&logo=powershell&logoColor=61DAFB
45 | [powershell-url]: https://learn.microsoft.com/en-us/powershell/
46 |
--------------------------------------------------------------------------------
/ansible/README.md:
--------------------------------------------------------------------------------
1 | # Ansible
2 |
3 | I wrote this small wrapper for Ansible so I could idempotentaly make changes to a Mikrotik Switch via Ansible
4 |
5 | ## Parameters
6 |
7 | | Parameter | Comments |
8 | | :-------- | :------- |
9 | | `auto_neg`
boolen | Enables or disables Auto-Negotiation for the switch port
`Choices:`
`false`
`true` |
10 | | `command_type`
string | Tells Ansible whether to run a "get" command or a "set" command
`Choices:`
`get (default)`
`set` |
11 | | `enabled`
boolen | Enables or disables the switch port
`Choices:`
`false`
`true` |
12 | | `output_only`
string | Returns the specified parameter
`Choices:`
`port_name`
`enabled`
`auto_neg` |
13 | | `port_name`
string | Name of the port |
14 | | `port_number`
integer | The port number to run the API call against |
15 | | `switch_password`
string | Password to give access to the switch |
16 | | `switch_url`
string | URL that the switch is accessed from |
17 | | `switch_username`
string | Username to give access to the switch |
18 |
--------------------------------------------------------------------------------
/ansible/plugins/modules/switch_port.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | from ansible.module_utils.basic import *
4 | import re
5 | import json
6 | import requests
7 | from requests.auth import HTTPDigestAuth
8 |
9 | def send_Mikrotik_Rest_Method(url, method, query, username, password, body=None):
10 | headers = {
11 | "Accept": "*/*",
12 | "Accept-Language": "en-US,en;q=0.5",
13 | "Accept-Encoding": "gzip, deflate",
14 | "Content-Type": "text/plain",
15 | "Origin": f"{url}",
16 | "Referer": f"{url}/index.html"
17 | }
18 |
19 | url = f"{url}/{query}"
20 |
21 | request_params = dict(
22 | method = method,
23 | url = url,
24 | headers = headers,
25 | auth = HTTPDigestAuth(username=username, password=password)
26 | )
27 |
28 | if body != None:
29 | request_params['data'] = body
30 |
31 | response = requests.request(**request_params)
32 | return response.text
33 |
34 | def convert_Mikrotik_Json(input_object):
35 | json_dump = input_object
36 |
37 | word_regex = r"(\w+)"
38 | single_quote_regex = r"(\')"
39 | double_double_quote_regex = r'\"{2}(\w+)\"{2}'
40 |
41 | json_dump = re.sub(word_regex, r'"\1"', json_dump)
42 | json_dump = re.sub(single_quote_regex, r'"', json_dump)
43 | json_dump = re.sub(double_double_quote_regex, r'"\1"', json_dump)
44 | json_dump = re.sub('],}','}]', json_dump)
45 |
46 | json_output = json.loads(json_dump)
47 |
48 | return json_output
49 |
50 | def convert_Mikrotik_Array_Hex(array, padding=8):
51 | binary_string = str('')
52 | array.reverse()
53 | for item in array:
54 | if item == True:
55 | bin = '1'
56 | elif item == False:
57 | bin = '0'
58 | binary_string += bin
59 |
60 | padding = padding + 2
61 | hex_output = f"{int(binary_string, 2):#0{padding}x}"
62 | return hex_output
63 |
64 | def convert_Mikrotik_Link_Speed(hex_string):
65 | SwOS_link_speeds = {
66 | '0x01': 0.1,
67 | '0x02': 1.0,
68 | '0x07': 0.0,
69 | '0x04': 0.0,
70 | '0x03': 10.0
71 | }
72 |
73 | for speeds in SwOS_link_speeds:
74 | if speeds == hex_string:
75 | return SwOS_link_speeds[speeds]
76 |
77 | def convert_Mikrotik_Hex_Array(hex_string, pad_length):
78 | output = []
79 | binary = f'{int(hex_string, 16):0>{pad_length}b}'
80 | for element in binary:
81 | if element == '1':
82 | output.append(True)
83 | else:
84 | output.append(False)
85 | output.reverse()
86 | return output
87 |
88 | def get_Mikrotik_Switch_Port(url, username, password, port_number=None, port_name=None, output_only=None):
89 | query = 'link.b'
90 | method = 'GET'
91 | response = send_Mikrotik_Rest_Method(url=url, query=query, method=method, username=username, password=password)
92 | links = convert_Mikrotik_Json(input_object=response)
93 |
94 | total_ports = int(links['prt'], 16)
95 | port_instance = 0
96 | output = []
97 |
98 | enabled_ports = convert_Mikrotik_Hex_Array(hex_string=links['en'], pad_length=total_ports)
99 | link_active = convert_Mikrotik_Hex_Array(hex_string=links['lnk'] , pad_length=total_ports)
100 | auto_neg_ports = convert_Mikrotik_Hex_Array(hex_string=links['an'], pad_length=total_ports)
101 | duplex_ports = convert_Mikrotik_Hex_Array(hex_string=links['dpx'], pad_length=total_ports)
102 |
103 | while port_instance < total_ports:
104 | object = {
105 | 'enabled': enabled_ports[port_instance],
106 | 'port_number': port_instance + 1,
107 | 'port_name': bytes.fromhex(links['nm'][port_instance]).decode('utf-8'),
108 | 'link_speed': convert_Mikrotik_Link_Speed(hex_string=links['spd'][port_instance]),
109 | 'link_active': link_active[port_instance],
110 | 'auto_neg': auto_neg_ports[port_instance],
111 | 'full_duplex': duplex_ports[port_instance],
112 | }
113 | port_instance += 1
114 | output.append(object)
115 |
116 | output_options = (
117 | 'port_name',
118 | 'enabled',
119 | 'auto_neg'
120 | )
121 |
122 | result = []
123 | if output_only in output_options:
124 | for item in output:
125 | result.append(item[output_only])
126 | else:
127 | if port_number != None:
128 | result = output[port_number - 1]
129 | elif port_name != None:
130 | for ports in output:
131 | if ports['port_name'] == port_name:
132 | result.append(ports)
133 | else:
134 | result = output
135 |
136 | return result
137 |
138 | def set_Mikrotik_Switch_Port(url, username, password, port_number, port_name=None, enabled=True, auto_neg=True):
139 | query = 'link.b'
140 | response = send_Mikrotik_Rest_Method(url=url, query=query, method='GET', username=username, password=password)
141 | mikrotik_config = convert_Mikrotik_Json(input_object=response)
142 |
143 | new_mikrotik_config = ''
144 | name_count = 1
145 | speed_count = 1
146 |
147 | get_Mikrotik_Link_params = dict(
148 | url = url,
149 | username = username,
150 | password = password
151 | )
152 |
153 | port_names = get_Mikrotik_Switch_Port(**get_Mikrotik_Link_params, output_only='port_name')
154 | port_enabled = get_Mikrotik_Switch_Port(**get_Mikrotik_Link_params, output_only='enabled')
155 | port_auto_neg = get_Mikrotik_Switch_Port(**get_Mikrotik_Link_params, output_only='auto_neg')
156 |
157 | array_port_number = port_number - 1
158 | #print(mikrotik_config)
159 | if port_name != None:
160 | new_port_name = port_name
161 | if new_port_name not in port_names:
162 | new_port_name_hex = new_port_name.encode('utf-8').hex()
163 | mikrotik_config['nm'][array_port_number] = new_port_name_hex
164 |
165 | if port_enabled[array_port_number] != enabled:
166 | new_port_enabled = list(port_enabled)
167 | new_port_enabled[array_port_number] = enabled
168 |
169 | new_port_enabled_hex = convert_Mikrotik_Array_Hex(array=new_port_enabled)
170 | mikrotik_config['en'] = new_port_enabled_hex
171 |
172 | if port_auto_neg[array_port_number] != auto_neg:
173 | new_port_auto_neg = list(port_auto_neg)
174 | new_port_auto_neg[array_port_number] = auto_neg
175 |
176 | new_port_auto_neg_hex = convert_Mikrotik_Array_Hex(array=new_port_auto_neg)
177 | mikrotik_config['an'] = new_port_auto_neg_hex
178 |
179 | new_mikrotik_config += f"{{en:{mikrotik_config['en']},nm:["
180 | for name_hex in mikrotik_config['nm']:
181 | if name_count <= (len(mikrotik_config['nm']) - 1):
182 | new_mikrotik_config += f"'{name_hex}',"
183 | name_count += 1
184 | else:
185 | new_mikrotik_config += f"'{name_hex}'"
186 | new_mikrotik_config += f"],an:{mikrotik_config['an']},spdc:["
187 | for speed_hex in mikrotik_config['spdc']:
188 | if speed_count <= (len(mikrotik_config['spdc']) - 1):
189 | new_mikrotik_config += f"'{speed_hex}',"
190 | speed_count += 1
191 | else:
192 | new_mikrotik_config += f"'{speed_hex}'"
193 | new_mikrotik_config += f"],dpxc:{mikrotik_config['dpxc']},fctc:{mikrotik_config['fctc']},fctr:{mikrotik_config['fctr']}}}"
194 |
195 | send_Mikrotik_Rest_Method(url=url, query=query, method='POST', username=username, password=password, body=new_mikrotik_config)
196 |
197 | def ports():
198 | module_args = dict(
199 | switch_url=dict(type='str', required=True),
200 | switch_username=dict(type='str', required=True),
201 | switch_password=dict(type='str', required=True, no_log=True),
202 | command_type=dict(
203 | type='str',
204 | required=False,
205 | choices = ['get','set'],
206 | default='get'),
207 | port_name=dict(type='str', required=False),
208 | port_number=dict(type='int', required=False),
209 | enabled=dict(type='bool', required=False),
210 | auto_neg=dict(type='bool', required=False),
211 | output_only=dict(
212 | type='str',
213 | required=False,
214 | choices = ['port_name','enabled','auto_neg'])
215 | )
216 |
217 | result = dict(
218 | changed = False,
219 | original_message = '',
220 | ports = ''
221 | )
222 |
223 | module = AnsibleModule(
224 | argument_spec = module_args,
225 | supports_check_mode = True
226 | )
227 |
228 | if module.check_mode:
229 | module.exit_json(**result)
230 |
231 | get_mikrotik_switch_port_params = dict(
232 | url = module.params['switch_url'],
233 | username = module.params['switch_username'],
234 | password = module.params['switch_password']
235 | )
236 |
237 | set_mikrotik_switch_port_params = dict(get_mikrotik_switch_port_params)
238 |
239 | if module.params['port_number'] is not None and module.params['command_type'] == 'set':
240 | get_mikrotik_switch_port_params['port_number'] = module.params['port_number']
241 | original_config = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
242 |
243 | set_mikrotik_switch_port_params['port_number'] = module.params['port_number']
244 |
245 | if module.params['port_name'] is not None:
246 | set_mikrotik_switch_port_params['port_name'] = module.params['port_name']
247 | result['prev_port_name'] = original_config['port_name']
248 |
249 | if module.params['enabled'] is not None:
250 | set_mikrotik_switch_port_params['enabled'] = module.params['enabled']
251 | result['prev_port_enabled_state'] = original_config['enabled']
252 |
253 | if module.params['auto_neg'] is not None:
254 | set_mikrotik_switch_port_params['auto_neg'] = module.params['auto_neg']
255 | result['prev_port_auto_neg_state'] = original_config['auto_neg']
256 |
257 | set_Mikrotik_Switch_Port(**set_mikrotik_switch_port_params)
258 | output = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
259 | result['changed'] = True
260 |
261 |
262 | elif module.params['port_number'] is not None and module.params['command_type'] == 'get':
263 | get_mikrotik_switch_port_params['port_number'] = module.params['port_number']
264 | output = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
265 |
266 | elif module.params['port_name'] is not None:
267 | get_mikrotik_switch_port_params['port_name'] = module.params['port_name']
268 | output = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
269 |
270 | elif module.params['output_only'] is not None:
271 | get_mikrotik_switch_port_params['output_only'] = module.params['output_only']
272 | output = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
273 |
274 | else:
275 | output = get_Mikrotik_Switch_Port(**get_mikrotik_switch_port_params)
276 |
277 | result['ports'] = output
278 | module.exit_json(**result)
279 |
280 | def main():
281 | ports()
282 |
283 | if __name__ == '__main__':
284 | main()
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/MikrotikPSwitchOS.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'MikrotikPSwitchOS'
3 | #
4 | # Generated by: Oliver Galbraith
5 | #
6 | # Generated on: 03/05/2023
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'MikrotikPSwitchOS.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '1.0.1.5'
16 |
17 | # Supported PSEditions
18 | # CompatiblePSEditions = @()
19 |
20 | # ID used to uniquely identify this module
21 | GUID = '9a053f09-191c-43d9-af9b-27f1ab9a1bd4'
22 |
23 | # Author of this module
24 | Author = 'Oliver Galbraith'
25 |
26 | # Company or vendor of this module
27 | CompanyName = 'Oliver Galbraith'
28 |
29 | # Copyright statement for this module
30 | Copyright = '(c) 2023 Oliver Galbraith. All rights reserved.'
31 |
32 | # Description of the functionality provided by this module
33 | Description = 'Hooks into the API behind Mikrotik SwitchOS to allow for automating switch processes through PowerShell'
34 |
35 | # Minimum version of the Windows PowerShell engine required by this module
36 | # PowerShellVersion = ''
37 |
38 | # Name of the Windows PowerShell host required by this module
39 | # PowerShellHostName = ''
40 |
41 | # Minimum version of the Windows PowerShell host required by this module
42 | # PowerShellHostVersion = ''
43 |
44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
45 | # DotNetFrameworkVersion = ''
46 |
47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
48 | # CLRVersion = ''
49 |
50 | # Processor architecture (None, X86, Amd64) required by this module
51 | # ProcessorArchitecture = ''
52 |
53 | # Modules that must be imported into the global environment prior to importing this module
54 | #RequiredModules = @()
55 |
56 | # Assemblies that must be loaded prior to importing this module
57 | # RequiredAssemblies = @()
58 |
59 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
60 | # ScriptsToProcess = @()
61 |
62 | # Type files (.ps1xml) to be loaded when importing this module
63 | # TypesToProcess = @()
64 |
65 | # Format files (.ps1xml) to be loaded when importing this module
66 | #FormatsToProcess = @()
67 |
68 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
69 | # NestedModules = @()
70 |
71 | # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
72 | FunctionsToExport = @('*')
73 |
74 | # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
75 | CmdletsToExport = @()
76 |
77 | # Variables to export from this module
78 | VariablesToExport = '*'
79 |
80 | # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
81 | AliasesToExport = @()
82 |
83 | # DSC resources to export from this module
84 | # DscResourcesToExport = @()
85 |
86 | # List of all modules packaged with this module
87 | # ModuleList = @()
88 |
89 | # List of all files packaged with this module
90 | # FileList = @()
91 |
92 | # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
93 | PrivateData = @{
94 |
95 | PSData = @{
96 |
97 | #ExternalModuleDependencies = @()
98 |
99 | # Tags applied to this module. These help with module discovery in online galleries.
100 | # Tags = @()
101 |
102 | # A URL to the license for this module.
103 | # LicenseUri = ''
104 |
105 | # A URL to the main website for this project.
106 | # ProjectUri = ''
107 |
108 | # A URL to an icon representing this module.
109 | # IconUri = ''
110 |
111 | # ReleaseNotes of this module
112 | # ReleaseNotes = ''
113 |
114 | } # End of PSData hashtable
115 |
116 | } # End of PrivateData hashtable
117 |
118 | # HelpInfo URI of this module
119 | # HelpInfoURI = ''
120 |
121 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
122 | # DefaultCommandPrefix = ''
123 |
124 | }
125 |
126 |
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/MikrotikPSwitchOS.psm1:
--------------------------------------------------------------------------------
1 | Get-ChildItem -Path $PSScriptRoot -Include *.ps1 -Recurse | ForEach-Object {. $_.FullName}
2 | $ExportedFunctions = Get-ChildItem -Path "$PSScriptRoot\Public\" | ForEach-Object {$_.Name -replace ".ps1"}
3 | Export-ModuleMember -Function $ExportedFunctions
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/README.md:
--------------------------------------------------------------------------------
1 |
2 | # PowerShell
3 |
4 | This is where this project started. I knew that eventually this would have to run with something like Python, however I'm still fairly new to Python, so I thought I would proof of concept everything in Powershell first.
5 |
6 |
7 |
8 | ## Installation
9 |
10 | To install, simply download the module files and install to your choice of paths in ```$env:PSModulePath```
11 |
12 | ```powershell
13 | Copy-Item -Destination
14 | Import-Module MikrotikPSwitchOS
15 | ```
16 |
17 | ## Usage/Examples
18 |
19 | #### Get-MikrotikLinks
20 | ```powershell
21 | PS C:\> $Credential = Get-Credential
22 | PS C:\> $URL = 'http://mikrotik-switch.url.com'
23 |
24 | PS C:\> Get-MikrotikLinks -Credential $Credential -URL $URL
25 |
26 | Enabled PortNumber PortType PortName LinkSpeed LinkActive AutoNeg FullDuplex
27 | ------- ---------- -------- -------- --------- ---------- ------- ----------
28 | True 1 rj45 Router 1 True True True
29 | True 2 rj45 Port2 1 True True True
30 | True 3 rj45 Port3 1 True True True
31 | True 4 rj45 Port4 1 True True True
32 | True 5 rj45 Port5 0 False True False
33 | True 6 rj45 Port6 0 False True False
34 | True 7 rj45 Port7 0 False True False
35 | ...
36 | ```
37 |
38 | #### Get-MikrotikSFP
39 | ```powershell
40 | PS C:\> $Credential = Get-Credential
41 | PS C:\> $URL = 'http://mikrotik-switch.url.com'
42 |
43 | PS C:\> Get-MikrotikSFP -Credential $Credential -URL $URL
44 |
45 | PortNumber PortName Vendor PartNumber Serial Type Temp Voltage
46 | ---------- -------- ------ ---------- ------ ---- ---- -------
47 | 25 SFP1 MikroTik S+RJ10 HCR01V1VFSK 1m copper 83 3.272
48 | 26 SFP2 Ubiquiti Inc. UC-DAC-SFP+ AH22018007220 1m copper 0 0
49 | 27 SFP3 0 0
50 | 28 SFP4 0 0
51 | ```
52 |
53 | #### Get-MikrotikVLANs
54 | ```powershell
55 | PS C:\> $Credential = Get-Credential
56 | PS C:\> $URL = 'http://mikrotik-switch.url.com'
57 |
58 | PS C:\> Get-MikrotikVLANs -Credential $Credential -URL $URL
59 |
60 | PortNumber PortName VLANMode VLANReceive VLANID ForceVLANID
61 | ---------- -------- -------- ----------- ------ -----------
62 | 1 Router Optional Any 1 False
63 | 2 Port2 Optional Any 88 False
64 | 3 Port3 Optional Any 88 False
65 | 4 Port4 Optional Any 88 False
66 | 5 Port5 Optional Any 88 False
67 | 6 Port6 Optional Any 88 False
68 | 7 Port7 Optional Any 88 False
69 | ```
70 |
71 | #### Set-MikroTikSwitchPort
72 | ```powershell
73 | PS C:\> $Credential = Get-Credential
74 | PS C:\> $URL = 'http://mikrotik-switch.url.com'
75 |
76 | PS C:\> Get-MikrotikLinks -Credential $Credential -URL $URL
77 |
78 | Enabled PortNumber PortType PortName LinkSpeed LinkActive AutoNeg FullDuplex
79 | ------- ---------- -------- -------- --------- ---------- ------- ----------
80 | True 1 rj45 Router 1 True True True
81 | True 2 rj45 Port2 1 True True True
82 | True 3 rj45 Port3 1 True True True
83 | True 4 rj45 Port4 1 True True True
84 | True 5 rj45 Port5 0 False True False
85 | True 6 rj45 Port6 0 False True False
86 | True 7 rj45 Port7 0 False True False
87 | ...
88 |
89 | PS C:\> Set-MikrotikSwitchPort -PortNumber 6 -PortName Testing -Enabled $false -Credential $Credential -URL $URL
90 | PS C:\> Get-MikrotikLinks -Credential $Credential -URL $URL
91 |
92 | Enabled PortNumber PortType PortName LinkSpeed LinkActive AutoNeg FullDuplex
93 | ------- ---------- -------- -------- --------- ---------- ------- ----------
94 | True 1 rj45 Router 1 True True True
95 | True 2 rj45 Port2 1 True True True
96 | True 3 rj45 Port3 1 True True True
97 | True 4 rj45 Port4 1 True True True
98 | True 5 rj45 Port5 0 False True False
99 | False 6 rj45 Testing 0 False True False
100 | True 7 rj45 Port7 0 False True False
101 | ...
102 | ```
103 |
104 | #### Set-MikroTikVLAN
105 | ```powershell
106 | PS C:\> $Credential = Get-Credential
107 | PS C:\> $URL = 'http://mikrotik-switch.url.com'
108 |
109 | PS C:\> Get-MikrotikVLANs -Credential $Credential -URL $URL
110 |
111 | PortNumber PortName VLANMode VLANReceive VLANID ForceVLANID
112 | ---------- -------- -------- ----------- ------ -----------
113 | 1 Router Optional Any 1 False
114 | 2 Port2 Optional Any 88 False
115 | 3 Port3 Optional Any 88 False
116 | 4 Port4 Optional Any 88 False
117 | 5 Port5 Optional Any 88 False
118 | 6 Port6 Optional Any 88 False
119 | 7 Port7 Optional Any 88 False
120 | ...
121 |
122 | PS C:\> Set-MikrotikVLAN -PortNumber 6 -VLANMode Disabled -VLANReceive 'Only Tagged' -VLANID 99 -Credential $Credential -URL $URL
123 | PS C:\> Get-MikrotikLinks -Credential $Credential -URL $URL
124 |
125 | PortNumber PortName VLANMode VLANReceive VLANID ForceVLANID
126 | ---------- -------- -------- ----------- ------ -----------
127 | 1 Router Optional Any 1 False
128 | 2 Port2 Optional Any 88 False
129 | 3 Port3 Optional Any 88 False
130 | 4 Port4 Optional Any 88 False
131 | 5 Port5 Optional Any 88 False
132 | 6 Port6 Disabled Only Tagged 99 False
133 | 7 Port7 Optional Any 88 False
134 | ...
135 | ```
136 |
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikLinkSpeed.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikLinkSpeed
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API output from hex to link speeds (in double)
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | $Hex
11 | )
12 |
13 | $SwOSLinkSpeeds = @{
14 | '0x01' = 0.1
15 | '0x02' = 1.0
16 | '0x07' = 0.0
17 | '0x04' = 0.0
18 | '0x03' = 10.0
19 | }
20 |
21 | ForEach($Speed in $SwOSLinkSpeeds.GetEnumerator())
22 | {
23 | If($Speed.Key -eq $Hex)
24 | {
25 | Return $Speed.Value
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikLinks.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikLinks
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API link page output from hex to boolean arrays/plain text
6 | #>
7 |
8 | param(
9 | [PSCustomObject]$InputObject,
10 | [Int]$TotalPorts
11 | )
12 |
13 | $Ports = $InputObject.nm.count
14 | $PortNumber = 0
15 |
16 | [array]$EnabledPorts = ConvertFrom-HexToArray -Hex $InputObject.en -ArrayLength $TotalPorts
17 | [array]$AutoNegPorts = ConvertFrom-HexToArray -Hex $InputObject.an -ArrayLength $TotalPorts
18 | [array]$DuplexPorts = ConvertFrom-HexToArray -Hex $InputObject.dpx -ArrayLength $TotalPorts
19 | [array]$LinkPorts = ConvertFrom-HexToArray -Hex $InputObject.lnk -ArrayLength $TotalPorts
20 |
21 | $TotalPorts = [uint32]$InputObject.prt
22 | $RJ45Ports = [uint32]$InputObject.sfpo
23 |
24 | [System.Collections.ArrayList]$Output = @()
25 | While($PortNumber -le ($Ports - 1))
26 | {
27 | [double]$LinkSpeed = "$(Convert-MikrotikLinkSpeed -Hex $InputObject.spd[$PortNumber])"
28 | If(($PortNumber -lt $RJ45Ports) -or ($LinkSpeed -le 0.1))
29 | {
30 | $Type = "rj45"
31 | }
32 | If(($PortNumber -ge $RJ45Ports) -and (($LinkSpeed -eq 0) -or ($LinkSpeed -gt 0.1)))
33 | {
34 | $Type = 'sfp'
35 | }
36 | $PortOptions = [pscustomObject]@{
37 | Enabled = $EnabledPorts[$PortNumber]
38 | PortNumber = $PortNumber + 1
39 | PortType = $Type
40 | PortName = "$(ConvertFrom-HexToString -Hex $InputObject.nm[$PortNumber])"
41 | LinkSpeed = $LinkSpeed
42 | LinkActive = $LinkPorts[$PortNumber]
43 | AutoNeg = $AutoNegPorts[$PortNumber]
44 | FullDuplex = $DuplexPorts[$PortNumber]
45 | }
46 | [void]$Output.Add($PortOptions)
47 | $PortNumber += 1
48 | }
49 | Return $Output
50 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikPoE.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikPoE
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API PoE page output from hex to boolean arrays/plain text
6 | #>
7 |
8 | param(
9 | [PSCustomObject]$InputObject,
10 | [PSCustomObject]$Links,
11 | [int]$TotalPorts
12 | )
13 |
14 | $Ports = $Links.count
15 | $PortNumber = 0
16 |
17 | [System.Collections.ArrayList]$Output = @()
18 | While($PortNumber -le ($Ports - 1))
19 | {
20 | $Current = "$(ConvertFrom-HexToInt -Hex $InputObject.curr[$PortNumber])"
21 | [double]$DecimalCurrent = $Current.Insert(($Current.Length -1), '.')
22 |
23 | $Voltage = "$(ConvertFrom-HexToInt -Hex $InputObject.volt[$PortNumber])"
24 | [double]$DecimalVoltage = $Voltage.Insert(($Voltage.Length -1), '.')
25 |
26 | $Power = "$(ConvertFrom-HexToInt -Hex $InputObject.pwr[$PortNumber])"
27 | [double]$DecimalPower = $Power.Insert(($Power.Length -1), '.')
28 |
29 | $PortOptions = [pscustomObject]@{
30 | PortNumber = $Links[$PortNumber].PortNumber
31 | PortName = $Links[$PortNumber].PortName
32 | PoEOut = "$(Convert-MikrotikPoeHexCodes -Type PoEOut -Hex $InputObject.poe[$PortNumber])"
33 | PoEPriority = ConvertFrom-HexToInt -Hex $InputObject.prio[$PortNumber]
34 | VoltageLevel = Convert-MikrotikPoeHexCodes -Type PoELevel -Hex $InputObject.lvl[$PortNumber]
35 | Status = Convert-MikrotikPoeHexCodes -Type PoEStatus -Hex $InputObject.poes[$PortNumber]
36 | Current = "$DecimalCurrent`mA"
37 | Voltage = "$DecimalVoltage`V"
38 | Power = "$DecimalPower`W"
39 | }
40 | [void]$Output.Add($PortOptions)
41 | $PortNumber += 1
42 | }
43 | Return $Output
44 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikPoEHexCodes.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikPoeHexCodes
2 | {
3 | param(
4 | [ValidateSet('PoEOut','PoELevel','PoEStatus')]
5 | [Parameter(Mandatory=$true)]
6 | $Type,
7 | [Parameter(Mandatory=$true, ParameterSetName='Hex')]
8 | $Hex,
9 | [Parameter(Mandatory=$true, ParameterSetName='String')]
10 | [String]$String
11 | )
12 |
13 | Switch($Type)
14 | {
15 | PoeOut
16 | {
17 | $Hashtable = @{
18 | '0x00' = 'Off'
19 | '0x01' = 'On'
20 | '0x02' = 'Auto'
21 | }
22 | }
23 | PoELevel
24 | {
25 | $Hashtable = @{
26 | '0x00' = 'Auto'
27 | '0x01' = 'Low'
28 | '0x02' = 'High'
29 | }
30 | }
31 | PoEStatus
32 | {
33 | $Hashtable = @{
34 | '0x00' = 'No PoE'
35 | '0x02' = 'Waiting for Load'
36 | '0x03' = 'Powered On'
37 | '0x05' = 'Short Circuit'
38 | }
39 | }
40 | }
41 | ForEach($Code in $Hashtable.GetEnumerator())
42 | {
43 | If($Hex -ne '')
44 | {
45 | If($Code.Key -eq $Hex)
46 | {
47 | Return $Code.Value
48 | }
49 | }
50 | If($String -ne '')
51 | {
52 | If($Code.Value -eq $String)
53 | {
54 | Return $Code.Key
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikSFP.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikSFP
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API SPF pages output from hex to boolean arrays/plain text
6 | #>
7 |
8 | param(
9 | [PSCustomObject]$InputObject,
10 | [PSCustomObject]$Links
11 | )
12 |
13 | $Ports = $Links.count
14 | $PortNumber = 0
15 |
16 | [System.Collections.ArrayList]$Output = @()
17 | While($PortNumber -le ($Ports - 1))
18 | {
19 | [int64]$Temp = "$([uint32]$InputObject.tmp[$PortNumber])"
20 | [double]$Voltage = "$((([uint32]$InputObject.vcc[$PortNumber]).ToString()).Insert(1,'.'))"
21 |
22 | If($Temp -gt 150)
23 | {
24 | $Temp = $null
25 | }
26 | If($Voltage -gt 5.0)
27 | {
28 | $Voltage = $null
29 | }
30 |
31 | $PortOptions = [pscustomObject]@{
32 | PortNumber = $Links[$PortNumber].PortNumber
33 | PortName = $Links[$PortNumber].PortName
34 | Vendor = "$(ConvertFrom-HexToString -Hex $InputObject.vnd[$PortNumber])"
35 | PartNumber = "$(ConvertFrom-HexToString -Hex $InputObject.pnr[$PortNumber])"
36 | Serial = "$(ConvertFrom-HexToString -Hex $InputObject.ser[$PortNumber])"
37 | Type = "$(ConvertFrom-HexToString -Hex $InputObject.typ[$PortNumber])"
38 | Temp = $Temp
39 | Voltage = $Voltage
40 | }
41 | [void]$Output.Add($PortOptions)
42 | $PortNumber += 1
43 | }
44 | Return $Output
45 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikVLAN.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikVLAN
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API VLAN page output from hex to boolean arrays/plain text
6 | #>
7 |
8 | param(
9 | [PSCustomObject]$InputObject,
10 | [PSCustomObject]$Links,
11 | [int]$TotalPorts
12 | )
13 |
14 | $Ports = $Links.count
15 | $PortNumber = 0
16 |
17 | [array]$ForceVLAN = ConvertFrom-HexToArray -Hex $InputObject.fvid -ArrayLength $TotalPorts
18 |
19 | [System.Collections.ArrayList]$Output = @()
20 | While($PortNumber -le ($Ports - 1))
21 | {
22 | $PortOptions = [pscustomObject]@{
23 | PortNumber = $Links[$PortNumber].PortNumber
24 | PortName = $Links[$PortNumber].PortName
25 | VLANMode = "$(Convert-MikrotikVLANHexCodes -Type VLANMode -Hex $InputObject.vlan[$PortNumber])"
26 | VLANReceive = "$(Convert-MikrotikVLANHexCodes -Type VLANReceive -Hex $InputObject.vlni[$PortNumber])"
27 | VLANID = ConvertFrom-HexToInt -Hex $InputObject.dvid[$PortNumber]
28 | ForceVLANID = $ForceVLAN[$PortNumber]
29 | }
30 | [void]$Output.Add($PortOptions)
31 | $PortNumber += 1
32 | }
33 | Return $Output
34 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikVLANConfig.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikVLANConfig
2 | {
3 | <#
4 | .Synopsis
5 | Converts the Mikrotik API VLANs page output from hex to boolean arrays/plain text
6 | #>
7 |
8 | param(
9 | [PSCustomObject]$InputObject,
10 | [Int]$TotalPorts
11 | )
12 |
13 | [System.Collections.ArrayList]$Output = @()
14 | $VLAN_Instance = 0
15 | ForEach($VLANItem in $InputObject)
16 | {
17 | #[array]$EnabledPorts = ConvertFrom-HexToArray -Hex $InputObject.en
18 | $Object = [pscustomobject]@{
19 | VLANID = [uint32]$InputObject.vid[$VLAN_Instance]
20 | PortIsolation = [uint32]$InputObject.piso[$VLAN_Instance]
21 | Learning = [uint32]$InputObject.lrn[$VLAN_Instance]
22 | Mirror = [uint32]$InputObject.mrr[$VLAN_Instance]
23 | IMGP_Snoop = [uint32]$InputObject.igmp[$VLAN_Instance]
24 | Members = ConvertFrom-HexToArray -Hex $InputObject.mbr[$VLAN_Instance] -ArrayLength $TotalPorts
25 | }
26 | [void]$Output.Add($Object)
27 |
28 | $VLAN_Instance += 1
29 | }
30 | Return $Output
31 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/Convert-MikrotikVLANHexCodes.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-MikrotikVLANHexCodes
2 | {
3 | param(
4 | [ValidateSet('VLANMode','VLANReceive')]
5 | [Parameter(Mandatory=$true)]
6 | $Type,
7 | [Parameter(Mandatory=$true, ParameterSetName='Hex')]
8 | $Hex,
9 | [Parameter(Mandatory=$true, ParameterSetName='String')]
10 | [String]$String
11 | )
12 |
13 | Switch($Type)
14 | {
15 | VLANMode
16 | {
17 | $Hashtable = @{
18 | '0x00' = 'Disabled'
19 | '0x01' = 'Optional'
20 | '0x02' = 'Enabled'
21 | '0x03' = 'Strict'
22 | }
23 | }
24 | VLANReceive
25 | {
26 | $Hashtable = @{
27 | '0x00' = 'Any'
28 | '0x01' = 'Only Tagged'
29 | '0x02' = 'Only Untagged'
30 | }
31 | }
32 | }
33 | ForEach($Code in $Hashtable.GetEnumerator())
34 | {
35 | If($Hex -ne '')
36 | {
37 | If($Code.Key -eq $Hex)
38 | {
39 | Return $Code.Value
40 | }
41 | }
42 | If($String -ne '')
43 | {
44 | If($Code.Value -eq $String)
45 | {
46 | Return $Code.Key
47 | }
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-ArrayToHex.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-ArrayToHex
2 | {
3 | <#
4 | .Synopsis
5 | Converts a boolean array to hex
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [Array]$Array
11 | )
12 |
13 | [string]$BinaryString = ''
14 | [array]::Reverse($Array)
15 | ForEach($Item in $Array)
16 | {
17 | If($Item -eq $true)
18 | {
19 | $Binary = '1'
20 | }
21 | ElseIf($Item -eq $false)
22 | {
23 | $Binary = '0'
24 | }
25 | $BinaryString += $Binary
26 | }
27 |
28 | $Hex = ("0x$(([Convert]::ToUInt32($BinaryString, 2)).ToString('X').PadLeft(8,'0'))").ToLower()
29 | Return $Hex
30 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-HexToArray.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-HexToArray
2 | {
3 | <#
4 | .Synopsis
5 | Converts a the Mikrotik hex to a boolean array
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [String]$Hex,
11 | [Parameter(Mandatory=$true)]
12 | [int]$ArrayLength
13 | )
14 |
15 | $Binary = ConvertFrom-HexToBinary -Hex $Hex -PadLength $ArrayLength
16 | $Output = @()
17 | [Array]$CharArray = ($Binary[-1..-$Binary.Length] -join '').ToCharArray()
18 | ForEach($Item in $CharArray)
19 | {
20 | $Result = $true
21 | If($Item -eq '0')
22 | {
23 | $Result = $false
24 | }
25 | [array]$Output += $Result
26 | }
27 | Return $Output
28 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-HexToBinary.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-HexToBinary
2 | {
3 | <#
4 | .Synopsis
5 | Converts a hex to binary
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | $Hex,
11 | [Parameter(Mandatory=$true)]
12 | [int]$PadLength
13 | )
14 |
15 | If($Hex -like "0x*")
16 | {
17 | $Hex = $Hex.Replace("0x",'')
18 | }
19 |
20 | [byte[]]$Bytes = ($Hex -split '(.{2})' -ne '' -replace '^', '0x')
21 |
22 | ForEach($Byte in $Bytes)
23 | {
24 | $Binary += "$([string]([Convert]::ToString($Byte, 2)).PadLeft(8,'0'))"
25 | }
26 | $Binary = $Binary.TrimStart('0')
27 | $Binary = $Binary.PadLeft($PadLength,'0')
28 | Return $Binary
29 | }
30 |
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-HexToInt.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-HexToInt
2 | {
3 | <#
4 | .Synopsis
5 | Converts hex to an base10 integer
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | $Hex
11 | )
12 |
13 | $Int = [uint32]$Hex
14 | Return $Int
15 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-HexToString.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-HexToString
2 | {
3 | <#
4 | .Synopsis
5 | Converts hex to a string
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | $Hex
11 | )
12 |
13 | If($Hex -like "0x*")
14 | {
15 | $Hex = $Hex.Replace("0x",'')
16 | }
17 |
18 | [string]$String = ''
19 | $Hex -split '(.{2})' -ne '' | ForEach-Object {
20 | $String += [char][byte]"0x$_"
21 | }
22 |
23 | Return $String
24 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-IntToHex.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-IntToHex
2 | {
3 | <#
4 | .Synopsis
5 | Converts a integer to hex
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [Int]$Int,
11 | [Parameter(Mandatory=$true)]
12 | [Int]$PadLength
13 | )
14 |
15 | [string]$Hex = '{0:X}' -f $Int
16 | $Padded = $Hex.PadLeft($PadLength, '0')
17 | $Hex = "0x$Padded"
18 | Return $Hex
19 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-MikrotikToJson.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-MikrotikToJson
2 | {
3 | <#
4 | .Synopsis
5 | Converts the non-standard JSON output from the Mikrotik API into parsable JSON to be imported into Powershell for later use
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [string]$InputObject
11 | )
12 |
13 | $JsonDump = $InputObject
14 |
15 | $WordRegex = '(\w+)'
16 | $SingleQuoteRegex = "(\')"
17 | $DoubleDoubleQuoteRegex = '\"{2}(\w+)\"{2}'
18 |
19 | $FixedJson = $JsonDump -replace $SingleQuoteRegex, '"'
20 | $FixedJson = $FixedJson -replace $WordRegex,'"$1"'
21 | $FixedJson = $FixedJson -replace $DoubleDoubleQuoteRegex, '"$1"'
22 |
23 | $FixedJson = $FixedJson -replace "],}","]}"
24 | If($FixedJson -like "*,")
25 | {
26 | }
27 | Try
28 | {
29 | $JsonObject = $FixedJson | ConvertFrom-Json
30 | }
31 | Catch
32 | {
33 | $FixedJson | Set-Clipboard
34 | Return "Failed JSON conversion sent to clipboard"
35 | }
36 | Return $JsonObject
37 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/private/ConvertFrom-StringToHex.ps1:
--------------------------------------------------------------------------------
1 | Function ConvertFrom-StringToHex
2 | {
3 | <#
4 | .Synopsis
5 | Converts a string to hex
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [AllowEmptyString()]
11 | [string]$String
12 | )
13 |
14 | $Hex = ''
15 | $CharArray = $String.ToCharArray()
16 | Foreach ($Char in $CharArray)
17 | {
18 | $Hex = $Hex + [System.String]::Format("{0:X2}", [System.Convert]::ToUInt32($Char))
19 | }
20 | Return $Hex
21 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikLinks.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikLinks
2 | {
3 | <#
4 | .Synopsis
5 | Calls the Mikrotik SwitchOS API to retrieve the information about the switch ports (links page http:///index.html#link)
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [PSCredential]$Credential,
11 | [Parameter(Mandatory=$false)]
12 | [URI]$URL,
13 | [Parameter(Mandatory=$false)]
14 | [ValidateSet('rj45','sfp')]
15 | [String]$Type
16 | )
17 |
18 | #Runs main rest method
19 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query link.b -Credential $Credential
20 |
21 | #Retrieves the total amount of ports on the switch, helps with calculating the link parameters
22 | $TotalPorts = Get-MikrotikTotalPorts -Credential $Credential -URL $URL
23 |
24 | #Uses the JSON retrieved from $Response, and converts it from hex/binary to human readable information
25 | $Output = Convert-MikrotikLinks -InputObject $Response -TotalPorts $TotalPorts
26 | If($Type -ne '')
27 | {
28 | Return $Output | Where-Object PortType -eq $Type
29 | }
30 | Else
31 | {
32 | Return $Output
33 | }
34 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikPoE.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikPoE
2 | {
3 | param(
4 | [Parameter(Mandatory=$true)]
5 | [PSCredential]$Credential,
6 | [Parameter(Mandatory=$false)]
7 | [URI]$URL
8 | )
9 |
10 | $Links = Get-MikrotikLinks -Credential $Credential -URL $URL
11 |
12 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Credential $Credential -Query poe.b
13 | $TotalPorts = Get-MikrotikTotalPorts -Credential $Credential -URL $URL
14 | $Output = Convert-MikrotikPoE -InputObject $Response -Links $Links -TotalPorts $TotalPorts
15 |
16 | Return $Output
17 | }
18 |
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikSFP.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikSFP
2 | {
3 | <#
4 | .Synopsis
5 | Calls the Mikrotik SwitchOS API to retrieve the information about the switch SFP ports (links page http:///index.htmll#sfp)
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [PSCredential]$Credential,
11 | [Parameter(Mandatory=$false)]
12 | [URI]$URL
13 | )
14 |
15 | $Links = Get-MikrotikLinks -Credential $Credential -URL $URL -Type sfp
16 |
17 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query sfp.b -Credential $Credential
18 | $Output = Convert-MikrotikSFP -InputObject $Response -Links $Links
19 | Return $Output
20 | }
21 |
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikTotalPorts.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikTotalPorts
2 | {
3 | <#
4 | .Synopsis
5 | Returns the total number of ports
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [PSCredential]$Credential,
11 | [Parameter(Mandatory=$false)]
12 | [URI]$URL
13 | )
14 |
15 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query link.b -Credential $Credential
16 | $Output = [uint32]$Response.prt
17 | Return $Output
18 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikVLANConfig.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikVLANConfig
2 | {
3 | <#
4 | .Synopsis
5 | Calls the Mikrotik SwitchOS API to retrieve the information about the VLANs configuration (links page http:///index.html#vlans)
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [PSCredential]$Credential,
11 | [Parameter(Mandatory=$false)]
12 | [URI]$URL
13 | )
14 |
15 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query vlan.b -Credential $Credential
16 |
17 | $Output = Convert-MikrotikVLANConfig -InputObject $Response
18 | Return $Output
19 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Get-MikrotikVLANs.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MikrotikVLANs
2 | {
3 | <#
4 | .Synopsis
5 | Calls the Mikrotik SwitchOS API to retrieve the information about the VLAN configuration (links page http:///index.html#vlan)
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$true)]
10 | [PSCredential]$Credential,
11 | [Parameter(Mandatory=$false)]
12 | [URI]$URL
13 | )
14 |
15 | $Links = Get-MikrotikLinks -Credential $Credential -URL $URL
16 |
17 | $Response = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query fwd.b -Credential $Credential
18 | $TotalPorts = Get-MikrotikTotalPorts -Credential $Credential -URL $URL
19 | $Output = Convert-MikrotikVLAN -InputObject $Response -Links $Links -TotalPorts $TotalPorts
20 | Return $Output
21 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Invoke-MikrotikRestMethod.ps1:
--------------------------------------------------------------------------------
1 | Function Invoke-MikrotikRestMethod
2 | {
3 | <#
4 | .Synopsis
5 | Sends a Rest Method request to the Mikrotik SwitchOS API
6 | #>
7 |
8 | param(
9 | [Parameter(Mandatory=$True)]
10 | [Microsoft.PowerShell.Commands.WebRequestMethod]$Method,
11 | [Parameter(Mandatory=$True)]
12 | [URI]$URI,
13 | [Parameter(Mandatory=$True)]
14 | [String]$Query,
15 | [Parameter(Mandatory=$true)]
16 | [PSCredential]$Credential,
17 | [Parameter(Mandatory=$False)]
18 | [String]$Body,
19 | [Parameter(Mandatory=$false)]
20 | [Switch]$NoConversion
21 | )
22 |
23 | Begin
24 | {
25 | $NetAssembly = [Reflection.Assembly]::GetAssembly([System.Net.Configuration.SettingsSection])
26 | If($NetAssembly)
27 | {
28 | $BindingFlags = [Reflection.BindingFlags] "Static,GetProperty,NonPublic"
29 | $SettingsType = $netAssembly.GetType("System.Net.Configuration.SettingsSectionInternal")
30 |
31 | $Instance = $SettingsType.InvokeMember("Section", $bindingFlags, $null, $null, @())
32 | If($Instance)
33 | {
34 | $BindingFlags = "NonPublic","Instance"
35 | $UseUnsafeHeaderParsingField = $SettingsType.GetField("useUnsafeHeaderParsing", $bindingFlags)
36 | If($UseUnsafeHeaderParsingField)
37 | {
38 | $UseUnsafeHeaderParsingField.SetValue($instance, $true)
39 | }
40 | }
41 | }
42 | }
43 |
44 | Process
45 | {
46 |
47 | [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
48 |
49 | $Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
50 | $Headers.Add("Accept", "*/*")
51 | $Headers.Add("Accept-Language", "en-US,en;q=0.5")
52 | $Headers.Add("Accept-Encoding", "gzip, deflate")
53 | $Headers.Add("Content-Type", "text/plain")
54 | $Headers.Add("Origin", "$URI")
55 | $Headers.Add("Referer", "$URI/index.html")
56 |
57 | $URI = "$URI" + $Query
58 |
59 | $InvokeParams = @{
60 | Uri = $URI
61 | Method = $Method
62 | Credential = $Credential
63 | Headers = $Headers
64 | }
65 |
66 | If($Method -eq 'POST')
67 | {
68 | If($Body -eq '')
69 | {
70 | Write-Error "Unable to send POST request with no body"
71 | Break
72 | }
73 | [void]$InvokeParams.Add('Body',$Body)
74 | }
75 |
76 | $Response = (Invoke-WebRequest @InvokeParams -ErrorAction SilentlyContinue).Content
77 | }
78 | End
79 | {
80 | #Allows for troubleshooting, it will spit out the plaintext response for the API, instead of the response converted to proper JSON
81 | If($NoConversion -eq $true)
82 | {
83 | $InitalObject = $Response
84 | }
85 | Else
86 | {
87 | $InitalObject = ConvertFrom-MikrotikToJson -InputObject $Response
88 | }
89 | Return $InitalObject
90 | }
91 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Set-MikrotikSwitchPort.ps1:
--------------------------------------------------------------------------------
1 | Function Set-MikrotikSwitchPort
2 | {
3 | <#
4 | .Synopsis
5 | Allows for changes to be made to a switch port via the Mikrotik SwitchOS API
6 | .Example
7 | Set-MikrotikSwitchPort -PortNumber 4 -PortName "NewPortName" -Enabled $true -Credential (Get-Credential) -Url http://
8 | #>
9 |
10 | param(
11 | [Parameter(Mandatory=$true)]
12 | [Int]$PortNumber,
13 | [Parameter(Mandatory=$false)]
14 | [String]$PortName,
15 | [Parameter(Mandatory=$false)]
16 | [Boolean]$Enabled = $true,
17 | [Parameter(Mandatory=$false)]
18 | [Boolean]$AutoNeg = $true,
19 | [Parameter(Mandatory=$true)]
20 | [PSCredential]$Credential,
21 | [Parameter(Mandatory=$false)]
22 | [URI]$URL,
23 | [Parameter(Mandatory=$false)]
24 | [Switch]$Force
25 | )
26 |
27 | $HardConfirm = $false
28 | $NewConfig = ''
29 | #Retrieves the current config for the switch
30 | $MikrotikConfig = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query link.b -Credential $Credential
31 |
32 | #Retrieves the current links
33 | $CurrentLinks = Get-MikrotikLinks -Credential $Credential -URL $URL
34 |
35 | $PortNameArray = $CurrentLinks | Select-Object -ExpandProperty PortName
36 | $PortEnabled = $CurrentLinks | Select-Object -ExpandProperty Enabled
37 | $PortAutoNeg = $CurrentLinks | Select-Object -ExpandProperty AutoNeg
38 |
39 | If($PortName -ne '')
40 | {
41 | $NewPortName = $PortName
42 |
43 | If($PortNameArray[$PortNumber - 1] -ne $NewPortName)
44 | {
45 | #Sets a new port name if the selected port (via -PortNumber) doesnt match the specified port name (-PortName)
46 | [string]$NewHexPortNameString = (ConvertFrom-StringToHex -String $NewPortName).ToLower()
47 | $MikrotikConfig.nm[$PortNumber - 1] = $NewHexPortNameString
48 |
49 | $HardConfirm = $true
50 | }
51 | }
52 |
53 | If($PortEnabled[$PortNumber - 1] -ne $Enabled)
54 | {
55 | $NewEnabledArray = $PortEnabled
56 | $NewEnabledArray[$PortNumber - 1] = $Enabled
57 |
58 | #Sets the port enabled state to -Enabled
59 | $NewEnabledHex = ConvertFrom-ArrayToHex -Array $NewEnabledArray
60 | $MikrotikConfig.en = $NewEnabledHex
61 |
62 | If($Enabled -eq $false)
63 | {
64 | $HardConfirm = $true
65 | }
66 | }
67 |
68 | If($PortAutoNeg[$PortNumber - 1] -ne $AutoNeg)
69 | {
70 | $NewAutoNegArray = $PortAutoNeg
71 | $NewAutoNegArray[$PortNumber - 1] = $AutoNeg
72 |
73 | #Sets the port auto-negotiation state to -AutoNeg
74 | $NewAutoNegHex = ConvertFrom-ArrayToHex -Array $NewAutoNegArray
75 | $MikrotikConfig.an = $NewAutoNegHex
76 |
77 | If($AutoNeg -eq $false)
78 | {
79 | $HardConfirm = $true
80 | }
81 | }
82 |
83 | #region Construct the new config to send to the switch
84 | $NameCount = 0
85 | $SpeedCount = 0
86 |
87 | $NewConfig = "{en:$($MikrotikConfig.en),nm:["
88 | ForEach($PortNameHex in $MikrotikConfig.nm)
89 | {
90 | If($NameCount -lt ($MikrotikConfig.nm.count - 1))
91 | {
92 | $NewConfig += "'$PortNameHex',"
93 | $NameCount += 1
94 | }
95 | Else
96 | {
97 | $NewConfig += "'$PortNameHex'"
98 | }
99 | }
100 | $NewConfig += "],an:$($MikrotikConfig.an),spdc:["
101 | ForEach($SpeedConfig in $MikrotikConfig.spdc)
102 | {
103 | If($SpeedCount -lt ($MikrotikConfig.spdc.count - 1))
104 | {
105 | $NewConfig += "'$SpeedConfig',"
106 | $SpeedCount += 1
107 | }
108 | Else
109 | {
110 | $NewConfig += "'$SpeedConfig'"
111 | }
112 | }
113 | $NewConfig += "],dpxc:$($MikrotikConfig.dpxc),fctc:$($MikrotikConfig.fctc),fctr:$($MikrotikConfig.fctr)}"
114 | #endregion
115 |
116 | <#
117 | Added this here as there is a chance that if the incorrect information is sent to the switch, it can corrupt the config and the switch has to be hard reset.
118 | From a fair bit of testing, most of the kinks have been ironed out, but rather safe than sorry
119 | #>
120 | If(($HardConfirm -eq $true) -and ($Force -ne $true))
121 | {
122 | $ConsoleWidth = $Host.UI.RawUI.BufferSize.Width
123 | $Exclaimation = '!' * $ConsoleWidth
124 | Write-Host "`n`rConfig that is going to be sent is" -ForegroundColor Yellow
125 | Write-Host $Exclaimation -ForegroundColor Yellow
126 | Write-Host "$NewConfig`n`r" -ForegroundColor White
127 | Write-Host "$Exclaimation`n`r" -ForegroundColor Yellow
128 |
129 | $HardConfirmContinue = Read-Host -Prompt 'Send New Config? Y/N'
130 |
131 | If($HardConfirmContinue -ne 'Y')
132 | {
133 | Write-Host "Breaking Out..."
134 | Break
135 | }
136 | ElseIf($HardConfirmContinue -eq 'Y')
137 | {
138 | Invoke-MikrotikRestMethod -Method Post -URI $URL -Credential $Credential -Query link.b -Body $NewConfig -NoConversion
139 | }
140 | }
141 | Else
142 | {
143 | Invoke-MikrotikRestMethod -Method Post -URI $URL -Credential $Credential -Query link.b -Body $NewConfig -NoConversion
144 | }
145 | }
--------------------------------------------------------------------------------
/powershell/MikrotikPSwitchOS/public/Set-MikrotikVLAN.ps1:
--------------------------------------------------------------------------------
1 | Function Set-MikrotikVLAN
2 | {
3 | <#
4 | .Synopsis
5 | Allows for changes to be made to a VLAN configuration via the Mikrotik SwitchOS API
6 | .Example
7 | Set-MikrotikVLAN-PortNumber 4 -VLANMode "Enabled" -VLANReceive "Only Untagged" -Credential (Get-Credential) -Url http://
8 | #>
9 |
10 | param(
11 | [Parameter(Mandatory=$true)]
12 | [Int]$PortNumber,
13 | [Parameter(Mandatory=$false)]
14 | [ValidateSet('Disabled','Optional','Enabled','Strict')]
15 | [string]$VLANMode,
16 | [Parameter(Mandatory=$false)]
17 | [ValidateSet('Any','Only Tagged','Only Untagged')]
18 | [string]$VLANReceive,
19 | [Parameter(Mandatory=$false)]
20 | [Int]$VLANID,
21 | [Parameter(Mandatory=$true)]
22 | [PSCredential]$Credential,
23 | [Parameter(Mandatory=$false)]
24 | [URI]$URL,
25 | [Parameter(Mandatory=$false)]
26 | [Switch]$Force
27 | )
28 |
29 | $HardConfirm = $false
30 | $NewConfig = ''
31 | #Retrieves the current config for the switch
32 | $MikrotikConfig = Invoke-MikrotikRestMethod -Method Get -URI $URL -Query fwd.b -Credential $Credential
33 |
34 | #Retrieves the current VLANs
35 | $CurrentVLANs = Get-MikrotikVLANs -Credential $Credential -URL $URL
36 |
37 | $VLANModeArray = $CurrentVLANs | Select-Object -ExpandProperty VLANMode
38 | $VLANReceiveArray = $CurrentVLANs | Select-Object -ExpandProperty VLANReceive
39 | $DefaultVLANArray = $CurrentVLANs | Select-Object -ExpandProperty VLANID
40 |
41 | If($VLANMode -ne '')
42 | {
43 | If($VLANModeArray[$PortNumber - 1] -ne $VLANMode)
44 | {
45 | #Sets a new VLAN mode if the selected port (via -PortNumber) doesnt match the specified VLAN mode (-VLANMode)
46 | $NewVLANMode = Convert-MikrotikVLANHexCodes -Type VLANMode -String $VLANMode
47 | $MikrotikConfig.vlan[$PortNumber - 1] = $NewVLANMode
48 |
49 | $HardConfirm = $true
50 | }
51 | }
52 | If($VLANReceive -ne '')
53 | {
54 | If($VLANReceiveArray[$PortNumber - 1] -ne $VLANReceive)
55 | {
56 | #Sets a new VLAN receive mode if the selected port (via -PortNumber) doesnt match the specified VLAN receive mode (-VLANReceive)
57 | $NewVLANReceive = Convert-MikrotikVLANReceive -String $VLANReceive
58 | $MikrotikConfig.vlni[$PortNumber - 1] = $NewVLANReceive
59 |
60 | $HardConfirm = $true
61 | }
62 | }
63 | If($VLANID -ne $null)
64 | {
65 | If($DefaultVLANArray[$PortNumber - 1] -ne $VLANID )
66 | {
67 | #Sets a new VLAN ID if the selected port (via -PortNumber) doesnt match the specified VLAN ID (-VLANID)
68 | $NewDefaultVLAN = ConvertFrom-IntToHex -Int $VLANID -PadLength 4
69 | $MikrotikConfig.dvid[$PortNumber - 1] = $NewDefaultVLAN
70 |
71 | $HardConfirm = $true
72 | }
73 | }
74 |
75 | $VLANModeCount = 0
76 | $VLANReceiveCount = 0
77 | $VLANIDCount = 0
78 |
79 | #region Construct the new config to send to the switch
80 | $NewConfig = "{vlan:["
81 | ForEach($PortVLANMode in $MikrotikConfig.vlan)
82 | {
83 | If($VLANModeCount -lt ($MikrotikConfig.vlan.count - 1))
84 | {
85 | $NewConfig += "$PortVLANMode,"
86 | $VLANModeCount += 1
87 | }
88 | Else
89 | {
90 | $NewConfig += "$PortVLANMode"
91 | }
92 | }
93 | $NewConfig += "],vlni:["
94 | ForEach($PortVLANReceive in $MikrotikConfig.vlni)
95 | {
96 | If($VLANReceiveCount -lt ($MikrotikConfig.vlni.count - 1))
97 | {
98 | $NewConfig += "$PortVLANReceive,"
99 | $VLANReceiveCount += 1
100 | }
101 | Else
102 | {
103 | $NewConfig += "$PortVLANReceive"
104 | }
105 |
106 | }
107 | $NewConfig += "],dvid:["
108 | ForEach($PortVLANDefault in $MikrotikConfig.dvid)
109 | {
110 | If($VLANIDCount -lt ($MikrotikConfig.dvid.count - 1))
111 | {
112 | $NewConfig += "$PortVLANDefault,"
113 | $VLANIDCount += 1
114 | }
115 | Else
116 | {
117 | $NewConfig += "$PortVLANDefault"
118 | }
119 |
120 | }
121 | $NewConfig += "]}"
122 | #endregion
123 |
124 | <#
125 | Added this here as there is a chance that if the incorrect information is sent to the switch, it can corrupt the config and the switch has to be hard reset.
126 | From a fair bit of testing, most of the kinks have been ironed out, but rather safe than sorry
127 | #>
128 | If(($HardConfirm -eq $true) -and ($Force -ne $true))
129 | {
130 | $ConsoleWidth = $Host.UI.RawUI.BufferSize.Width
131 | $Exclaimation = '!' * $ConsoleWidth
132 | Write-Host "`n`rConfig that is going to be sent is" -ForegroundColor Yellow
133 | Write-Host $Exclaimation -ForegroundColor Yellow
134 | Write-Host "$NewConfig`n`r" -ForegroundColor White
135 | Write-Host "$Exclaimation`n`r" -ForegroundColor Yellow
136 |
137 | $HardConfirmContinue = Read-Host -Prompt 'Send New Config? Y/N'
138 |
139 | If($HardConfirmContinue -ne 'Y')
140 | {
141 | Write-Host "Breaking Out..."
142 | Break
143 | }
144 | ElseIf($HardConfirmContinue -eq 'Y')
145 | {
146 | Invoke-MikrotikRestMethod -Method Post -URI $URL -Credential $Credential -Query fwd.b -Body $NewConfig -NoConversion
147 | }
148 | }
149 | Else
150 | {
151 | Invoke-MikrotikRestMethod -Method Post -URI $URL -Credential $Credential -Query fwd.b -Body $NewConfig -NoConversion
152 | }
153 | }
--------------------------------------------------------------------------------
/python/mikrotik_switch_api.py:
--------------------------------------------------------------------------------
1 | import re
2 | import json
3 | import requests
4 | from requests.auth import HTTPDigestAuth
5 |
6 | def send_Mikrotik_Rest_Method(url, method, query, username, password, body=None):
7 | headers = {
8 | "Accept": "*/*",
9 | "Accept-Language": "en-US,en;q=0.5",
10 | "Accept-Encoding": "gzip, deflate",
11 | "Content-Type": "text/plain",
12 | "Origin": f"{url}",
13 | "Referer": f"{url}/index.html"
14 | }
15 |
16 | url = f"{url}/{query}"
17 |
18 | request_params = dict(
19 | method = method,
20 | url = url,
21 | headers = headers,
22 | auth = HTTPDigestAuth(username=username, password=password)
23 | )
24 |
25 | if body != None:
26 | request_params['data'] = body
27 |
28 | response = requests.request(**request_params)
29 | return response.text
30 |
31 | def convert_Mikrotik_Json(input_object):
32 | json_dump = input_object
33 |
34 | word_regex = r"(\w+)"
35 | single_quote_regex = r"(\')"
36 | double_double_quote_regex = r'\"{2}(\w+)\"{2}'
37 |
38 | json_dump = re.sub(word_regex, r'"\1"', json_dump)
39 | json_dump = re.sub(single_quote_regex, r'"', json_dump)
40 | json_dump = re.sub(double_double_quote_regex, r'"\1"', json_dump)
41 | json_dump = re.sub('],}','}]', json_dump)
42 |
43 | json_output = json.loads(json_dump)
44 |
45 | return json_output
46 |
47 | def get_Mikrotik_Hosts(url, username, password):
48 | query = '!dhost.b'
49 | method = 'GET'
50 | response = send_Mikrotik_Rest_Method(url=url, query=query, method=method, username=username, password=password)
51 | hosts = convert_Mikrotik_Json(input_object=response)
52 | links = get_Mikrotik_Links(url=url, username=username, password=password)
53 |
54 | output = []
55 | for host in hosts:
56 | mac_address = re.sub(r'(.{2})(?!$)', r'\1:', host['adr'])
57 | vlan_id = int(host['vid'], 16)
58 | port_number = int(host['prt'], 16) + 1
59 | port_name = links[port_number - 1]['port_name']
60 |
61 | object = {
62 | 'mac_address':mac_address,
63 | 'vlan_id':vlan_id,
64 | 'port_name':port_name,
65 | 'port_number':port_number
66 | }
67 | output.append(object)
68 |
69 | return output
70 |
71 | def convert_Mikrotik_Link_Speed(hex_string):
72 | SwOS_link_speeds = {
73 | '0x01': 0.1,
74 | '0x02': 1.0,
75 | '0x07': 0.0,
76 | '0x04': 0.0,
77 | '0x03': 10.0
78 | }
79 |
80 | for speeds in SwOS_link_speeds:
81 | if speeds == hex_string:
82 | return SwOS_link_speeds[speeds]
83 |
84 | def convert_Mikrotik_Hex_Array(hex_string, pad_length):
85 | output = []
86 | binary = f'{int(hex_string, 16):0>{pad_length}b}'
87 | for element in binary:
88 | if element == '1':
89 | output.append(True)
90 | else:
91 | output.append(False)
92 | output.reverse()
93 | return output
94 |
95 | def convert_Mikrotik_Array_Hex(array, padding=8):
96 | binary_string = str('')
97 | array.reverse()
98 | for item in array:
99 | if item == True:
100 | bin = '1'
101 | elif item == False:
102 | bin = '0'
103 | binary_string += bin
104 |
105 | padding = padding + 2
106 | hex_output = f"{int(binary_string, 2):#0{padding}x}"
107 | return hex_output
108 |
109 | def convert_Mikrotik_Vlan_Mode(hex_string=None, string=None):
110 | vlan_modes = {
111 | '0x00': 'Disabled',
112 | '0x01': 'Optional',
113 | '0x02': 'Enabled',
114 | '0x03': 'Strict'
115 | }
116 |
117 | for key, value in vlan_modes.items():
118 | if hex_string != None and key == hex_string:
119 | return value
120 | if string != None and value == string:
121 | return key
122 |
123 | def convert_Mikrotik_Vlan_Receive(hex_string=None, string=None):
124 | vlan_receive = {
125 | '0x00': 'Any',
126 | '0x01': 'Only Tagged',
127 | '0x02': 'Only Untagged'
128 | }
129 |
130 | for key, value in vlan_receive.items():
131 | if hex_string != None and key == hex_string:
132 | return value
133 | if string != None and value == string:
134 | return key
135 |
136 | def get_Mikrotik_Links(url, username, password, port_number=None, port_name=None, output_only=None):
137 | query = 'link.b'
138 | method = 'GET'
139 | response = send_Mikrotik_Rest_Method(url=url, query=query, method=method, username=username, password=password)
140 | links = convert_Mikrotik_Json(input_object=response)
141 |
142 | total_ports = int(links['prt'], 16)
143 | port_instance = 0
144 | output = []
145 |
146 | enabled_ports = convert_Mikrotik_Hex_Array(hex_string=links['en'], pad_length=total_ports)
147 | link_active = convert_Mikrotik_Hex_Array(hex_string=links['lnk'] , pad_length=total_ports)
148 | auto_neg_ports = convert_Mikrotik_Hex_Array(hex_string=links['an'], pad_length=total_ports)
149 | duplex_ports = convert_Mikrotik_Hex_Array(hex_string=links['dpx'], pad_length=total_ports)
150 |
151 | while port_instance < total_ports:
152 | object = {
153 | 'enabled': enabled_ports[port_instance],
154 | 'port_number': port_instance + 1,
155 | 'port_name': bytes.fromhex(links['nm'][port_instance]).decode('utf-8'),
156 | 'link_speed': convert_Mikrotik_Link_Speed(hex_string=links['spd'][port_instance]),
157 | 'link_active': link_active[port_instance],
158 | 'auto_neg': auto_neg_ports[port_instance],
159 | 'full_duplex': duplex_ports[port_instance],
160 | }
161 | port_instance += 1
162 | output.append(object)
163 |
164 | output_options = (
165 | 'port_name',
166 | 'enabled',
167 | 'auto_neg'
168 | )
169 |
170 | result = []
171 | if output_only in output_options:
172 | for item in output:
173 | result.append(item[output_only])
174 | else:
175 | if port_number != None:
176 | result = output[port_number - 1]
177 | elif port_name != None:
178 | for ports in output:
179 | if ports['port_name'] == port_name:
180 | result.append(ports)
181 | else:
182 | result = output
183 |
184 | return result
185 |
186 | def get_Mikrotik_Vlan(url, username, password, port_number=None, port_name=None, vlan_id=None, output_only=None):
187 | query = 'fwd.b'
188 | method = 'GET'
189 | response = send_Mikrotik_Rest_Method(url=url, query=query, method=method, username=username, password=password)
190 | links = get_Mikrotik_Links(url=url, username=username, password=password)
191 | vlans = convert_Mikrotik_Json(input_object=response)
192 |
193 | total_ports = len(links)
194 | port_instance = 0
195 | output = []
196 |
197 | force_vlan = convert_Mikrotik_Hex_Array(hex_string=vlans['fvid'], pad_length=total_ports)
198 |
199 | while port_instance < total_ports:
200 | object = {
201 | 'port_number': port_instance + 1,
202 | 'port_name': links[port_instance]['port_name'],
203 | 'vlan_mode': convert_Mikrotik_Vlan_Mode(hex_string=vlans['vlan'][port_instance]),
204 | 'vlan_receive': convert_Mikrotik_Vlan_Receive(hex_string=vlans['vlni'][port_instance]),
205 | 'vlan_id': int(vlans['dvid'][port_instance], 16),
206 | 'force_vlan': force_vlan[port_instance],
207 | }
208 | port_instance += 1
209 | output.append(object)
210 |
211 | output_options = (
212 | 'vlan_mode',
213 | 'vlan_receive',
214 | 'vlan_id'
215 | )
216 |
217 | result = []
218 | if output_only in output_options:
219 | for item in output:
220 | result.append(item[output_only])
221 | else:
222 | if port_number != None:
223 | result = output[port_number - 1]
224 | elif port_name != None:
225 | for ports in output:
226 | if ports['port_name'] == port_name:
227 | result.append(ports)
228 | elif vlan_id != None:
229 | for ports in output:
230 | if ports['vlan_id'] == vlan_id:
231 | result.append(ports)
232 | else:
233 | result = output
234 |
235 | return result
236 |
237 | def get_Mikrotik_Vlan_Config(url, username, password):
238 | query = 'vlan.b'
239 | method = 'GET'
240 | response = send_Mikrotik_Rest_Method(url=url, query=query, method=method, username=username, password=password)
241 | vlans = convert_Mikrotik_Json(input_object=response)
242 |
243 | vlan_instance = 0
244 | output = []
245 |
246 | for vlan in vlans:
247 | object = {
248 | "vlan_id": int(vlans[vlan_instance]['vid'], 16),
249 | 'port_isolation': int(vlans[vlan_instance]['piso'], 16),
250 | 'learning': int(vlans[vlan_instance]['lrn'], 16),
251 | 'mirror': int(vlans[vlan_instance]['mrr'], 16),
252 | 'igmp_snoop': int(vlans[vlan_instance]['igmp'], 16),
253 | 'members': convert_Mikrotik_Hex_Array(hex_string=vlans[vlan_instance]['mbr'], pad_length=26)
254 | }
255 | vlan_instance += 1
256 | output.append(object)
257 |
258 | return output
259 |
260 | def set_Mikrotik_Switch_Port(url, username, password, port_number, port_name=None, enabled=True, auto_neg=True):
261 | query = 'link.b'
262 | response = send_Mikrotik_Rest_Method(url=url, query=query, method='GET', username=username, password=password)
263 | mikrotik_config = convert_Mikrotik_Json(input_object=response)
264 |
265 | new_mikrotik_config = ''
266 | name_count = 1
267 | speed_count = 1
268 |
269 | get_Mikrotik_Link_params = dict(
270 | url = url,
271 | username = username,
272 | password = password
273 | )
274 |
275 | port_names = get_Mikrotik_Links(**get_Mikrotik_Link_params, output_only='port_name')
276 | port_enabled = get_Mikrotik_Links(**get_Mikrotik_Link_params, output_only='enabled')
277 | port_auto_neg = get_Mikrotik_Links(**get_Mikrotik_Link_params, output_only='auto_neg')
278 |
279 | array_port_number = port_number - 1
280 | #print(mikrotik_config)
281 | if port_name != None:
282 | new_port_name = port_name
283 | if new_port_name not in port_names:
284 | new_port_name_hex = new_port_name.encode('utf-8').hex()
285 | mikrotik_config['nm'][array_port_number] = new_port_name_hex
286 |
287 | if port_enabled[array_port_number] != enabled:
288 | new_port_enabled = list(port_enabled)
289 | new_port_enabled[array_port_number] = enabled
290 |
291 | new_port_enabled_hex = convert_Mikrotik_Array_Hex(array=new_port_enabled)
292 | mikrotik_config['en'] = new_port_enabled_hex
293 |
294 | if port_auto_neg[array_port_number] != auto_neg:
295 | new_port_auto_neg = list(port_auto_neg)
296 | new_port_auto_neg[array_port_number] = auto_neg
297 |
298 | new_port_auto_neg_hex = convert_Mikrotik_Array_Hex(array=new_port_auto_neg)
299 | mikrotik_config['an'] = new_port_auto_neg_hex
300 |
301 | new_mikrotik_config += f"{{en:{mikrotik_config['en']},nm:["
302 | for name_hex in mikrotik_config['nm']:
303 | if name_count <= (len(mikrotik_config['nm']) - 1):
304 | new_mikrotik_config += f"'{name_hex}',"
305 | name_count += 1
306 | else:
307 | new_mikrotik_config += f"'{name_hex}'"
308 | new_mikrotik_config += f"],an:{mikrotik_config['an']},spdc:["
309 | for speed_hex in mikrotik_config['spdc']:
310 | if speed_count <= (len(mikrotik_config['spdc']) - 1):
311 | new_mikrotik_config += f"'{speed_hex}',"
312 | speed_count += 1
313 | else:
314 | new_mikrotik_config += f"'{speed_hex}'"
315 | new_mikrotik_config += f"],dpxc:{mikrotik_config['dpxc']},fctc:{mikrotik_config['fctc']},fctr:{mikrotik_config['fctr']}}}"
316 |
317 | send_Mikrotik_Rest_Method(url=url, query=query, method='POST', username=username, password=password, body=new_mikrotik_config)
318 |
319 | def set_Mikrotik_Vlan(url, username, password, port_number, vlan_mode=None, vlan_receive=None, vlan_id=None):
320 | query = 'fwd.b'
321 | response = send_Mikrotik_Rest_Method(url=url, query=query, method='GET', username=username, password=password)
322 | mikrotik_config = convert_Mikrotik_Json(input_object=response)
323 |
324 | get_Mikrotik_Vlan_params = dict(
325 | url = url,
326 | username = username,
327 | password = password
328 | )
329 |
330 | array_port_number = port_number - 1
331 |
332 | vlan_mode_count = 1
333 | vlan_receive_count = 1
334 | vlan_id_count = 1
335 |
336 | vlan_mode_data = get_Mikrotik_Vlan(**get_Mikrotik_Vlan_params, output_only='vlan_mode')[array_port_number]
337 | vlan_receive_data = get_Mikrotik_Vlan(**get_Mikrotik_Vlan_params, output_only='vlan_receive')[array_port_number]
338 | vlan_id_data = get_Mikrotik_Vlan(**get_Mikrotik_Vlan_params, output_only='vlan_id')[array_port_number]
339 |
340 | if vlan_mode != None:
341 | if vlan_mode_data != vlan_mode:
342 | new_vlan_mode = convert_Mikrotik_Vlan_Mode(string=vlan_mode)
343 |
344 | mikrotik_config['vlan'][array_port_number] = new_vlan_mode
345 | print(new_vlan_mode)
346 |
347 | if vlan_receive != None:
348 | if vlan_receive_data != vlan_receive:
349 | new_vlan_receive = convert_Mikrotik_Vlan_Receive(string=vlan_receive)
350 | mikrotik_config['vlni'][array_port_number] = new_vlan_receive
351 | print(new_vlan_receive)
352 |
353 | if vlan_id != None:
354 | if vlan_id_data != vlan_id:
355 | padding = 6
356 | new_vlan_id = f"{vlan_id:#0{padding}x}"
357 | mikrotik_config['dvid'][array_port_number] = new_vlan_id
358 | print(new_vlan_id)
359 |
360 | new_mikrotik_config = '{vlan:['
361 | for vlan_mode_hex in mikrotik_config['vlan']:
362 | if vlan_mode_count <= (len(mikrotik_config['vlan']) - 1):
363 | new_mikrotik_config += f"{vlan_mode_hex},"
364 | vlan_mode_count += 1
365 | else:
366 | new_mikrotik_config += f"{vlan_mode_hex}"
367 |
368 | new_mikrotik_config += '],vlni:['
369 | for vlan_receive_hex in mikrotik_config['vlni']:
370 | if vlan_receive_count <= (len(mikrotik_config['vlni']) - 1):
371 | new_mikrotik_config += f"{vlan_receive_hex},"
372 | vlan_receive_count += 1
373 | else:
374 | new_mikrotik_config += f"{vlan_receive_hex}"
375 |
376 | new_mikrotik_config += '],dvid:['
377 | for vlan_id_hex in mikrotik_config['dvid']:
378 | if vlan_id_count <= (len(mikrotik_config['dvid']) - 1):
379 | new_mikrotik_config += f"{vlan_id_hex},"
380 | vlan_id_count += 1
381 | else:
382 | new_mikrotik_config += f"{vlan_id_hex}"
383 |
384 | new_mikrotik_config += ']}'
385 |
386 | send_Mikrotik_Rest_Method(url=url, query=query, method='POST', username=username, password=password, body=new_mikrotik_config)
--------------------------------------------------------------------------------