├── .editorconfig ├── .github └── workflows │ ├── docs.yml │ └── tests.yml ├── .gitignore ├── .mocharc.json ├── CHANGELOG.md ├── EXAMPLES.md ├── LICENSE ├── README.md ├── TODO.md ├── __tests__ ├── exec │ ├── commands │ │ ├── address.ts │ │ ├── addrlabel.ts │ │ ├── batch.ts │ │ ├── link.ts │ │ ├── monitor.ts │ │ ├── ntable.ts │ │ ├── route.ts │ │ ├── rule.ts │ │ └── tuntap.ts │ └── utils │ │ ├── ip-forwarding.ts │ │ └── routing-tables.ts └── safe │ ├── cmd-generation │ ├── command-class.ts │ ├── fixtures │ │ ├── address-add.ts │ │ ├── address-change.ts │ │ ├── address-delete.ts │ │ ├── address-flush.ts │ │ ├── address-replace.ts │ │ ├── address-restore.ts │ │ ├── address-save.ts │ │ ├── address-show.ts │ │ ├── address-showdump.ts │ │ ├── addrlabel-add.ts │ │ ├── addrlabel-delete.ts │ │ ├── addrlabel-flush.ts │ │ ├── addrlabel-list.ts │ │ ├── batch-fromfile.ts │ │ ├── batch-fromstdin.ts │ │ ├── index.ts │ │ ├── link-add.ts │ │ ├── link-delete.ts │ │ ├── link-set.ts │ │ ├── link-show.ts │ │ ├── maddress-add.ts │ │ ├── maddress-del.ts │ │ ├── maddress-show.ts │ │ ├── mroute-show.ts │ │ ├── neighbour-add.ts │ │ ├── neighbour-change.ts │ │ ├── neighbour-delete.ts │ │ ├── neighbour-flush.ts │ │ ├── neighbour-get.ts │ │ ├── neighbour-replace.ts │ │ ├── neighbour-show.ts │ │ ├── ntable-change.ts │ │ ├── ntable-show.ts │ │ ├── route-add.ts │ │ ├── route-append.ts │ │ ├── route-change.ts │ │ ├── route-delete.ts │ │ ├── route-flush.ts │ │ ├── route-get.ts │ │ ├── route-replace.ts │ │ ├── route-restore.ts │ │ ├── route-save.ts │ │ ├── route-show.ts │ │ ├── rule-add.ts │ │ ├── rule-delete.ts │ │ ├── rule-flush.ts │ │ ├── rule-restore.ts │ │ ├── rule-save.ts │ │ ├── rule-show.ts │ │ ├── tunnel-add.ts │ │ ├── tunnel-change.ts │ │ ├── tunnel-del.ts │ │ ├── tunnel-prl.ts │ │ ├── tunnel-show.ts │ │ ├── tunnel-v6rd.ts │ │ ├── tuntap-add.ts │ │ ├── tuntap-del.ts │ │ └── tuntap-show.ts │ └── ip-commands.ts │ ├── parsers │ ├── monitor.fixtures.ts │ └── monitor.ts │ └── regexes.ts ├── package-lock.json ├── package.json ├── src ├── commands │ ├── address.constants.ts │ ├── address.ts │ ├── address │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── delete.interfaces.ts │ │ ├── delete.schema.ts │ │ ├── flush.interfaces.ts │ │ ├── flush.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── addrlabel.ts │ ├── addrlabel │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── del.interfaces.ts │ │ ├── del.schema.ts │ │ └── list.interfaces.ts │ ├── batch.ts │ ├── link.constants.ts │ ├── link.ts │ ├── link │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── delete.interfaces.ts │ │ ├── delete.schema.ts │ │ ├── extended-virtual-link-types │ │ │ ├── bond-slave.interfaces.ts │ │ │ ├── bond-slave.schema.ts │ │ │ ├── bridge-slave.interfaces.ts │ │ │ └── bridge-slave.schema.ts │ │ ├── set.interfaces.ts │ │ ├── set.schema.ts │ │ ├── show.interfaces.ts │ │ ├── show.schema.ts │ │ ├── virtual-link-types │ │ │ ├── bareup.interfaces.ts │ │ │ ├── bareup.schema.ts │ │ │ ├── bridge.interfaces.ts │ │ │ ├── bridge.schema.ts │ │ │ ├── can.interfaces.ts │ │ │ ├── can.schema.ts │ │ │ ├── erspan-ip6erspan.interfaces.ts │ │ │ ├── erspan-ip6erspan.schema.ts │ │ │ ├── geneve.interfaces.ts │ │ │ ├── geneve.schema.ts │ │ │ ├── gre-gretap.interfaces.ts │ │ │ ├── gre-gretap.schema.ts │ │ │ ├── hsr.interfaces.ts │ │ │ ├── hsr.schema.ts │ │ │ ├── ip6gre-ip6gretap.interfaces.ts │ │ │ ├── ip6gre-ip6gretap.schema.ts │ │ │ ├── ipip-sit.interfaces.ts │ │ │ ├── ipip-sit.schema.ts │ │ │ ├── ipoib.interfaces.ts │ │ │ ├── ipoib.schema.ts │ │ │ ├── macsec.interfaces.ts │ │ │ ├── macsec.schema.ts │ │ │ ├── macvlan-macvtap.interfaces.ts │ │ │ ├── macvlan-macvtap.schema.ts │ │ │ ├── rmnet.interfaces.ts │ │ │ ├── rmnet.schema.ts │ │ │ ├── veth-vxcan.interfaces.ts │ │ │ ├── veth-vxcan.schema.ts │ │ │ ├── vlan.interfaces.ts │ │ │ ├── vlan.schema.ts │ │ │ ├── vrf.interfaces.ts │ │ │ ├── vrf.schema.ts │ │ │ ├── vxlan.interfaces.ts │ │ │ ├── vxlan.schema.ts │ │ │ ├── xfrm.interfaces.ts │ │ │ └── xfrm.schema.ts │ │ └── xdp-options │ │ │ ├── object.interfaces.ts │ │ │ ├── object.schema.ts │ │ │ ├── off.interfaces.ts │ │ │ ├── off.schema.ts │ │ │ ├── pinned.interfaces.ts │ │ │ └── pinned.schema.ts │ ├── maddress.ts │ ├── maddress │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── monitor.constants.ts │ ├── monitor.ts │ ├── monitor │ │ ├── monitor.interfaces.ts │ │ └── monitor.schema.ts │ ├── mroute.ts │ ├── mroute │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── neighbour.constants.ts │ ├── neighbour.ts │ ├── neighbour │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── del.interfaces.ts │ │ ├── del.schema.ts │ │ ├── get.interfaces.ts │ │ ├── get.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── ntable.ts │ ├── ntable │ │ ├── change.interfaces.ts │ │ ├── change.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── route.constants.ts │ ├── route.ts │ ├── route │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── encap-types │ │ │ ├── bpf.interfaces.ts │ │ │ ├── bpf.schema.ts │ │ │ ├── ioam6.interfaces.ts │ │ │ ├── ioam6.schema.ts │ │ │ ├── ip.interfaces.ts │ │ │ ├── ip.schema.ts │ │ │ ├── mpls.interfaces.ts │ │ │ ├── mpls.schema.ts │ │ │ ├── seg6.interfaces.ts │ │ │ ├── seg6.schema.ts │ │ │ ├── seg6local.interfaces.ts │ │ │ └── seg6local.schema.ts │ │ ├── get.interfaces.ts │ │ ├── get.schema.ts │ │ ├── show.constants.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── rule.constants.ts │ ├── rule.ts │ ├── rule │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts │ ├── tunnel.constants.ts │ ├── tunnel.ts │ ├── tunnel │ │ ├── 6rd.interfaces.ts │ │ ├── 6rd.schema.ts │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── prl.interfaces.ts │ │ └── prl.schema.ts │ ├── tuntap.constants.ts │ ├── tuntap.ts │ └── tuntap │ │ ├── add.interfaces.ts │ │ ├── add.schema.ts │ │ ├── show.interfaces.ts │ │ └── show.schema.ts ├── common │ ├── classes │ │ ├── command-with-filepath.ts │ │ ├── command-with-redirect-from-filepath-and-returned-data.ts │ │ ├── command-with-redirect-from-filepath.ts │ │ ├── command-with-redirect-to-filepath.ts │ │ ├── command-with-returned-data.ts │ │ ├── command-with-stdin.ts │ │ ├── command.ts │ │ └── monitor-command.ts │ ├── constants │ │ ├── attribute-values.ts │ │ ├── regexes.ts │ │ ├── schemas.ts │ │ └── tests.ts │ ├── errors │ │ ├── command.ts │ │ └── parameters.ts │ ├── interfaces │ │ ├── common.ts │ │ ├── monitor.ts │ │ └── tests.ts │ ├── misc.ts │ └── validator.ts ├── index.ts └── utils │ ├── index.ts │ ├── ip-forwarding.constants.ts │ ├── ip-forwarding.ts │ ├── routing-tables.constants.ts │ ├── routing-tables.interfaces.ts │ ├── routing-tables.schemas.ts │ └── routing-tables.ts ├── tsconfig.json └── typedoc.config.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 2 11 | indent_style = space 12 | insert_final_newline = false 13 | max_line_length = 120 14 | trim_trailing_whitespace = true 15 | 16 | [*.md] 17 | trim_trailing_whitespace = false 18 | indent_size = 4 19 | indent_style = space 20 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build-and-deploy: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | 16 | - name: Cache node-modules 17 | uses: actions/cache@v3 18 | with: 19 | path: node_modules 20 | key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }} 21 | restore-keys: | 22 | ${{ runner.OS }}-node- 23 | 24 | - name: Install & Build 25 | run: npm install 26 | 27 | - name: Generate Docs 28 | run: npm run docs 29 | 30 | - name: Deploy 31 | uses: JamesIves/github-pages-deploy-action@4.1.0 32 | with: 33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 34 | BRANCH: gh-pages 35 | FOLDER: docs 36 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | pull_request: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: 19 | - 14.x 20 | - 16.x 21 | - 18.x 22 | 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v3 26 | 27 | - name: Use Node.js ${{ matrix.node-version }} 28 | uses: actions/setup-node@v3 29 | with: 30 | node-version: ${{ matrix.node-version }} 31 | 32 | - run: npm ci 33 | - run: npm run test:github-actions 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .directory 2 | /.idea 3 | /node_modules 4 | /lib 5 | /docs -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "timeout" : 15000, 3 | "recursive": true, 4 | "require" : [ 5 | "ts-node/register", 6 | "source-map-support/register" 7 | ], 8 | "reporter" : "progress", 9 | "sort" : true 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2024 Diosney Sarmiento 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 13 | all 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 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | ## TODO 2 | 3 | ### General 4 | 5 | - Should contribute `@types/iproute`? 6 | 7 | - Cleaning: 8 | - Change all remaining `pattern` into `format`. Add respective tests. 9 | - Add `sonarlint` or `prettify`? 10 | 11 | ### Commands 12 | 13 | - Implement the remaining operations or options that were left out: 14 | - `link` 15 | - `set` 16 | - `macaddr` set of options 17 | - `xstats` 18 | - `afstats` 19 | - `property` 20 | 21 | - `monitor` 22 | - Should parse output to `json` or wait for `iproute` team to add a `-json` option? 23 | 24 | - The interfaces of the `show` methods need to be completed. 25 | Those interfaces are: `RuleInfo`, `RouteInfo`, `LinkInfo`, `LinkWithAddressInfo`. 26 | 27 | - `neighbour` 28 | - Add exec tests. 29 | 30 | - `tunnel` 31 | - Add exec tests. 32 | 33 | - `tuntap` 34 | - Add manpage links when it gets created since it doesn't exist yet. 35 | 36 | ### Documentation 37 | 38 | - Document every property with schema `format` as a `@see {@link}` in the interfaces?. 39 | 40 | ### Tests 41 | 42 | - Add Docker to automatize `test:all`. 43 | - Add code coverage. 44 | - Add more unit tests. 45 | -------------------------------------------------------------------------------- /__tests__/exec/commands/addrlabel.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, before, after } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import { add, del, list } from '../../../src/commands/addrlabel'; 5 | import { AddrlabelInfo } from '../../../src/commands/addrlabel/list.interfaces'; 6 | import { AddrlabelAddOptions } from '../../../src'; 7 | 8 | describe('addrlabel', () => { 9 | describe('show', () => { 10 | it('should return all address labels', async () => { 11 | const labels = await list({ 12 | sudo: true 13 | }) as AddrlabelInfo[]; 14 | 15 | expect(labels).to.be.an('array').that.has.lengthOf.at.least(1); 16 | }); 17 | }); 18 | 19 | describe('add', () => { 20 | let newLabel: AddrlabelAddOptions = { 21 | prefix: '2001:db8::/32', 22 | label : 100 23 | }; 24 | 25 | let labelsBeforeAdd: AddrlabelInfo[] = []; 26 | 27 | before(async function () { 28 | labelsBeforeAdd = await list({ 29 | sudo: true 30 | }) as AddrlabelInfo[]; 31 | }); 32 | 33 | after(async function () { 34 | await del(newLabel, { 35 | sudo: true 36 | }); 37 | }); 38 | 39 | it('should add a new label', async () => { 40 | await add(newLabel, { 41 | sudo: true 42 | }); 43 | 44 | const labels = await list() as AddrlabelInfo[]; 45 | expect(labels).to.be.an('array'); 46 | expect(labels).to.be.an('array').that.has.lengthOf.at.least(labelsBeforeAdd.length + 1); 47 | 48 | const addedLabel = labels.find(item => item.label === newLabel.label); 49 | expect(addedLabel).not.to.be.undefined; 50 | expect(addedLabel).to.be.an('object'); 51 | }); 52 | }); 53 | 54 | describe('del', () => { 55 | let newLabel: AddrlabelAddOptions = { 56 | prefix: '2001:db8::/32', 57 | label : 100 58 | }; 59 | 60 | let labelsBeforeAdd: AddrlabelInfo[] = []; 61 | 62 | before(async function () { 63 | await add(newLabel, { 64 | sudo: true 65 | }); 66 | 67 | labelsBeforeAdd = await list({ 68 | sudo: true 69 | }) as AddrlabelInfo[]; 70 | }); 71 | 72 | it('should delete a label', async () => { 73 | await del(newLabel, { 74 | sudo: true 75 | }); 76 | 77 | const rules = await list() as AddrlabelInfo[]; 78 | expect(rules).to.be.an('array'); 79 | expect(rules).to.be.an('array').that.has.lengthOf.at.least(labelsBeforeAdd.length - 1); 80 | 81 | const addedRule = rules.find(item => item.label === newLabel.label); 82 | expect(addedRule).to.be.undefined; 83 | }); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /__tests__/exec/commands/batch.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'fs'; 2 | import { describe, it, before, after } from 'mocha'; 3 | 4 | import { fromFile, fromStdin } from '../../../src/commands/batch'; 5 | 6 | describe('batch', () => { 7 | describe('fromFile', () => { 8 | let filePath = `/tmp/batch-${ Date.now() }.commands`; 9 | 10 | before(async function () { 11 | await fs.writeFile(filePath, [ 12 | 'address add local 127.0.1.4/32 dev lo', 13 | 'address add local 127.0.1.5/32 dev lo', 14 | 15 | 'address del 127.0.1.4/32 dev lo', 16 | 'address del 127.0.1.5/32 dev lo' 17 | ].join('\n')); 18 | }); 19 | 20 | after(async function () { 21 | try { 22 | await fs.unlink(filePath); 23 | } 24 | catch (error) { 25 | } 26 | }); 27 | 28 | it('should run the commands in the file', async () => { 29 | await fromFile({ 30 | sudo: true, 31 | filePath 32 | }); 33 | }); 34 | }); 35 | 36 | describe('fromStdin', () => { 37 | let batch = [ 38 | 'address add local 127.0.1.4/32 dev lo', 39 | 'address add local 127.0.1.5/32 dev lo', 40 | 41 | 'address del 127.0.1.4/32 dev lo', 42 | 'address del 127.0.1.5/32 dev lo' 43 | ].join('\n'); 44 | 45 | it('should run the commands', async () => { 46 | await fromStdin({ 47 | sudo : true, 48 | stdin: batch 49 | }); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /__tests__/exec/commands/monitor.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import { monitor } from '../../../src/commands/monitor'; 5 | import { MonitorObjects } from '../../../src/commands/monitor.constants'; 6 | import { MonitorEmittedData } from '../../../src/common/interfaces/monitor'; 7 | import { AddressAddOptions } from '../../../src/commands/address/add.interfaces'; 8 | import { add, del } from '../../../src/commands/address'; 9 | import MonitorCommand from '../../../src/common/classes/monitor-command'; 10 | import { MonitorOptions } from '../../../src/commands/monitor/monitor.interfaces'; 11 | 12 | describe('monitor', function () { 13 | let command: MonitorCommand; 14 | 15 | let newAddress: AddressAddOptions = { 16 | local: '2001:db8:85a3::370:7334/128', 17 | dev : 'lo' 18 | }; 19 | 20 | after(async function () { 21 | await del(newAddress, { 22 | sudo: true 23 | }); 24 | }); 25 | 26 | it('should watch events in `all` channel', function (done) { 27 | let hasDoneBeenCalled = false; 28 | 29 | let safeDone = (error?: any) => { 30 | if (!hasDoneBeenCalled) { 31 | hasDoneBeenCalled = true; 32 | 33 | if (command) { 34 | command.close(); 35 | } 36 | done(error); 37 | } 38 | }; 39 | 40 | monitor({ 41 | object: MonitorObjects.All 42 | }, { 43 | sudo: true 44 | }) 45 | .then((_command) => { 46 | command = _command; 47 | 48 | command.on(MonitorObjects.All, (data: MonitorEmittedData) => { 49 | expect(data).to.be.an('object'); 50 | expect(data).to.have.keys([ 51 | 'timestamp', 52 | 'nsid', 53 | 'object', 54 | 'lines', 55 | 'originalLine' 56 | ]); 57 | expect(data.timestamp).to.be.a('string'); 58 | expect(data.nsid).to.be.a('string'); 59 | expect(data.object).to.be.a('string'); 60 | expect(data.lines).to.be.an('array').with.lengthOf.at.least(1); 61 | expect(data.originalLine).to.be.a('string'); 62 | 63 | safeDone(); 64 | }); 65 | 66 | command.on('error', safeDone); 67 | }); 68 | 69 | add(newAddress, { 70 | sudo: true 71 | }); 72 | }); 73 | }); -------------------------------------------------------------------------------- /__tests__/exec/commands/ntable.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import { show, change } from '../../../src/commands/ntable'; 5 | import { NtableInfo } from '../../../src'; 6 | 7 | describe('ntable', () => { 8 | describe('show', () => { 9 | it('should return all entries', async () => { 10 | const labels = await show({}, { 11 | sudo: true 12 | }) as NtableInfo[]; 13 | 14 | expect(labels).to.be.an('array').that.has.lengthOf.at.least(1); 15 | }); 16 | }); 17 | 18 | describe('change', () => { 19 | it('should change the `arp_cache` param', async () => { 20 | await change({ 21 | name : 'arp_cache', 22 | queue: 8, 23 | dev : 'lo' 24 | }, { 25 | sudo: true 26 | }); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /__tests__/exec/commands/tuntap.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, before, after } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import { add, del, show } from '../../../src/commands/tuntap'; 5 | import { TunTapTunnelInfo } from '../../../src/commands/tuntap/show.interfaces'; 6 | import { TunTapTunnelAddOptions } from '../../../src/commands/tuntap/add.interfaces'; 7 | import { TunTapTunnelModes } from '../../../src'; 8 | 9 | describe('tuntap', () => { 10 | describe('show', () => { 11 | it('should return all tuntap devices if no filters were provided', async () => { 12 | const entries = await show({}, { 13 | sudo: true 14 | }) as TunTapTunnelInfo[]; 15 | 16 | expect(entries).to.be.an('array').that.has.lengthOf.at.least(0); 17 | }); 18 | }); 19 | 20 | describe('add', () => { 21 | let newEntry: TunTapTunnelAddOptions = { 22 | mode: TunTapTunnelModes.Tun, 23 | name: 'mytun0-dev' 24 | }; 25 | 26 | let entriesBeforeAdd: TunTapTunnelInfo[] = []; 27 | 28 | before(async function () { 29 | entriesBeforeAdd = await show({}, { 30 | sudo: true 31 | }) as TunTapTunnelInfo[]; 32 | }); 33 | 34 | after(async function () { 35 | await del(newEntry, { 36 | sudo: true 37 | }); 38 | }); 39 | 40 | it('should add a new entry', async () => { 41 | await add(newEntry, { 42 | sudo: true 43 | }); 44 | 45 | const entries = await show() as TunTapTunnelInfo[]; 46 | expect(entries).to.be.an('array'); 47 | expect(entries).to.be.an('array').that.has.lengthOf.at.least(entriesBeforeAdd.length + 1); 48 | 49 | const addedEntry = entries.find(item => item.ifname === newEntry.name); 50 | expect(addedEntry).not.to.be.undefined; 51 | expect(addedEntry).to.be.an('object'); 52 | }); 53 | }); 54 | 55 | describe('del', () => { 56 | let newEntry: TunTapTunnelAddOptions = { 57 | mode: TunTapTunnelModes.Tun, 58 | name: 'mytun1-dev' 59 | }; 60 | 61 | let entriesBeforeAdd: TunTapTunnelInfo[] = []; 62 | 63 | before(async function () { 64 | await add(newEntry, { 65 | sudo: true 66 | }); 67 | 68 | entriesBeforeAdd = await show({}, { 69 | sudo: true 70 | }) as TunTapTunnelInfo[]; 71 | }); 72 | 73 | it('should delete a entry', async () => { 74 | await del(newEntry, { 75 | sudo: true 76 | }); 77 | 78 | const entries = await show() as TunTapTunnelInfo[]; 79 | expect(entries).to.be.an('array'); 80 | expect(entries).to.be.an('array').that.has.lengthOf.at.least(entriesBeforeAdd.length - 1); 81 | 82 | const addedEntry = entries.find(item => item.ifname === newEntry.name); 83 | expect(addedEntry).to.be.undefined; 84 | }); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-add.ts: -------------------------------------------------------------------------------- 1 | import { AddressAddOptions } from '../../../../src/commands/address/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `local` and `dev`', 7 | options : { 8 | local: '2001:0db8:85a3::0370:7334/64', 9 | dev : 'eth1' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'address', 15 | 'add', 16 | 'local', 17 | '2001:0db8:85a3::0370:7334/64', 18 | 'dev', 19 | 'eth1' 20 | ], 21 | expectedCmdToExec: ` ip address add local 2001:0db8:85a3::0370:7334/64 dev eth1` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-change.ts: -------------------------------------------------------------------------------- 1 | import { AddressAddOptions } from '../../../../src/commands/address/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `local` and `dev`', 7 | options : { 8 | local: '2001:0db8:85a3::0370:7334/64', 9 | dev : 'eth1' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'address', 15 | 'change', 16 | 'local', 17 | '2001:0db8:85a3::0370:7334/64', 18 | 'dev', 19 | 'eth1' 20 | ], 21 | expectedCmdToExec: ` ip address change local 2001:0db8:85a3::0370:7334/64 dev eth1` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-delete.ts: -------------------------------------------------------------------------------- 1 | import { AddressDeleteOptions } from '../../../../src/commands/address/delete.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `local` and `dev`', 7 | options : { 8 | local: '2001:0db8:85a3::0370:7334/64', 9 | dev : 'eth1' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'address', 15 | 'delete', 16 | 'local', 17 | '2001:0db8:85a3::0370:7334/64', 18 | 'dev', 19 | 'eth1' 20 | ], 21 | expectedCmdToExec: ` ip address delete local 2001:0db8:85a3::0370:7334/64 dev eth1` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-flush.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { AddressScopes } from '../../../../src/commands/address.constants'; 3 | import { AddressFlushOptions } from '../../../../src/commands/address/flush.interfaces'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with `local` and `dev`', 8 | options : { 9 | dev : 'eth4', 10 | scope: AddressScopes.Global 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'address', 16 | 'flush', 17 | 'dev', 18 | 'eth4', 19 | 'scope', 20 | AddressScopes.Global 21 | ], 22 | expectedCmdToExec: ` ip address flush dev eth4 scope ${AddressScopes.Global}` 23 | } 24 | ]; 25 | 26 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-replace.ts: -------------------------------------------------------------------------------- 1 | import { AddressAddOptions } from '../../../../src/commands/address/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `local` and `dev`', 7 | options : { 8 | local: '2001:0db8:85a3::0370:7334/64', 9 | dev : 'eth1' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'address', 15 | 'replace', 16 | 'local', 17 | '2001:0db8:85a3::0370:7334/64', 18 | 'dev', 19 | 'eth1' 20 | ], 21 | expectedCmdToExec: ` ip address replace local 2001:0db8:85a3::0370:7334/64 dev eth1` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-restore.ts: -------------------------------------------------------------------------------- 1 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture<{}, GlobalOptionsWithRequiredFilePath>[] = [ 5 | { 6 | description : 'with `filePath` set', 7 | options : {}, 8 | globalOptions : { 9 | filePath: './test-dump-file.binary' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'address', 15 | 'restore', 16 | '<', 17 | './test-dump-file.binary' 18 | ], 19 | expectedCmdToExec: ` ip address restore < ./test-dump-file.binary` 20 | } 21 | ]; 22 | 23 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-save.ts: -------------------------------------------------------------------------------- 1 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | import { AddressScopes } from '../../../../src/commands/address.constants'; 4 | import { AddressFlushOptions } from '../../../../src/commands/address/flush.interfaces'; 5 | 6 | export const Tests: TestFixture[] = [ 7 | { 8 | description : 'with `local` and `dev`', 9 | options : { 10 | dev : 'eth4', 11 | scope: AddressScopes.Global 12 | }, 13 | globalOptions : { 14 | filePath: './test-dump-file.binary' 15 | }, 16 | expectedCmd : [ 17 | '', 18 | 'ip', 19 | 'address', 20 | 'save', 21 | 'dev', 22 | 'eth4', 23 | 'scope', 24 | AddressScopes.Global, 25 | '>', 26 | './test-dump-file.binary' 27 | ], 28 | expectedCmdToExec: ` ip address save dev eth4 scope ${AddressScopes.Global} > ./test-dump-file.binary` 29 | } 30 | ]; 31 | 32 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-show.ts: -------------------------------------------------------------------------------- 1 | import { AddressShowOptions } from '../../../../src/commands/address/show.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'address', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json address show` 18 | }, 19 | { 20 | description : 'for all active interfaces', 21 | options : { 22 | up: true 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'address', 31 | 'show', 32 | 'up' 33 | ], 34 | expectedCmdToExec: ` ip -details -statistics -json address show up` 35 | }, 36 | { 37 | description : 'shows IPv4 and IPv6 addresses assigned to network interface `eth0`', 38 | options : { 39 | dev: 'eth0' 40 | }, 41 | expectedCmd : [ 42 | '', 43 | 'ip', 44 | '-details', 45 | '-statistics', 46 | '-json', 47 | 'address', 48 | 'show', 49 | 'dev', 50 | 'eth0' 51 | ], 52 | expectedCmdToExec: ` ip -details -statistics -json address show dev eth0` 53 | } 54 | ]; 55 | 56 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/address-showdump.ts: -------------------------------------------------------------------------------- 1 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture<{}, GlobalOptionsWithRequiredFilePath>[] = [ 5 | { 6 | description: 'with `filePath` set', 7 | options: {}, 8 | globalOptions: { 9 | filePath: './test-dump-file.binary' 10 | }, 11 | expectedCmd: [ 12 | '', 13 | 'ip', 14 | '-details', 15 | '-statistics', 16 | '-json', 17 | 'address', 18 | 'showdump', 19 | '<', 20 | './test-dump-file.binary' 21 | ], 22 | expectedCmdToExec: ` ip -details -statistics -json address showdump < ./test-dump-file.binary` 23 | } 24 | ]; 25 | 26 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/addrlabel-add.ts: -------------------------------------------------------------------------------- 1 | import { AddrlabelAddOptions } from '../../../../src/commands/addrlabel/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description: 'with `prefix` and `label`', 7 | options: { 8 | prefix: '2001:db8::/32', 9 | label: 100 10 | }, 11 | expectedCmd: [ 12 | '', 13 | 'ip', 14 | 'addrlabel', 15 | 'add', 16 | 'prefix', 17 | '2001:db8::/32', 18 | 'label', 19 | 100 20 | ], 21 | expectedCmdToExec: ` ip addrlabel add prefix 2001:db8::/32 label 100` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/addrlabel-delete.ts: -------------------------------------------------------------------------------- 1 | import { AddrlabelDelOptions } from '../../../../src/commands/addrlabel/del.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `prefix`', 7 | options : { 8 | prefix: '2001:db8::/32' 9 | }, 10 | expectedCmd : [ 11 | '', 12 | 'ip', 13 | 'addrlabel', 14 | 'del', 15 | 'prefix', 16 | '2001:db8::/32' 17 | ], 18 | expectedCmdToExec: ` ip addrlabel del prefix 2001:db8::/32` 19 | } 20 | ]; 21 | 22 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/addrlabel-flush.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | 'addrlabel', 12 | 'flush' 13 | ], 14 | expectedCmdToExec: ` ip addrlabel flush` 15 | } 16 | ]; 17 | 18 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/addrlabel-list.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { Empty } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'addrlabel', 15 | 'list' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json addrlabel list` 18 | } 19 | ]; 20 | 21 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/batch-fromfile.ts: -------------------------------------------------------------------------------- 1 | import { Empty, GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with input from file path', 7 | options : {}, 8 | globalOptions : { 9 | filePath: '/tmp/batch-file' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | '-batch', 15 | '/tmp/batch-file' 16 | ], 17 | expectedCmdToExec: ` ip -batch /tmp/batch-file` 18 | } 19 | ]; 20 | 21 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/batch-fromstdin.ts: -------------------------------------------------------------------------------- 1 | import { Empty, GlobalOptionsWithRequiredStdin } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with input from stdin', 7 | options : {}, 8 | globalOptions : { 9 | stdin: [ 10 | 'address add local 127.0.1.4 dev lo', 11 | 'address add local 127.0.1.5 dev lo', 12 | 'address add local 127.0.1.6 dev lo', 13 | 'address add local 127.0.1.7 dev lo' 14 | ].join('\n') 15 | }, 16 | expectedCmd : [ 17 | '', 18 | 'ip', 19 | '-batch', 20 | '- <[] = [ 6 | { 7 | description: 'with only `dev`', 8 | options: { 9 | dev: 'vlan100' 10 | }, 11 | expectedCmd: [ 12 | '', 13 | 'ip', 14 | 'link', 15 | 'delete', 16 | 'vlan100' 17 | ], 18 | expectedCmdToExec: ` ip link delete vlan100` 19 | }, 20 | { 21 | description: 'with `dev` with type=vlan', 22 | options: { 23 | dev : 'vlan100', 24 | type: { 25 | [LinkTypes.Vlan]: { 26 | protocol: VlanProtocols['802.1Q'], 27 | id: 100 28 | } 29 | } 30 | }, 31 | expectedCmd: [ 32 | '', 33 | 'ip', 34 | 'link', 35 | 'delete', 36 | 'vlan100', 37 | 'type', 38 | LinkTypes.Vlan, 39 | 'protocol', 40 | VlanProtocols['802.1Q'], 41 | 'id', 42 | 100 43 | ], 44 | expectedCmdToExec: ` ip link delete vlan100 type ${ LinkTypes.Vlan } protocol ${ VlanProtocols['802.1Q'] } id ${ 100 }` 45 | } 46 | ]; 47 | 48 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/link-show.ts: -------------------------------------------------------------------------------- 1 | import { LinkShowOptions } from '../../../../src/commands/link/show.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'link', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json link show` 18 | }, 19 | { 20 | description : 'for all up interfaces', 21 | options : { 22 | up: true 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'link', 31 | 'show', 32 | 'up' 33 | ], 34 | expectedCmdToExec: ` ip -details -statistics -json link show up` 35 | } 36 | ]; 37 | 38 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/maddress-add.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { MaddressAddOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'add multicast address `33:33:00:00:00:01` to interface `eth0`', 7 | options : { 8 | address: '33:33:00:00:00:01', 9 | dev : 'eth0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'maddress', 15 | 'add', 16 | '33:33:00:00:00:01', 17 | 'dev', 18 | 'eth0' 19 | ], 20 | expectedCmdToExec: ` ip maddress add 33:33:00:00:00:01 dev eth0` 21 | } 22 | ]; 23 | 24 | export default Tests; 25 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/maddress-del.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { MaddressAddOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'delete multicast address `33:33:00:00:00:01` from interface `eth0`', 7 | options : { 8 | address: '33:33:00:00:00:01', 9 | dev : 'eth0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'maddress', 15 | 'del', 16 | '33:33:00:00:00:01', 17 | 'dev', 18 | 'eth0' 19 | ], 20 | expectedCmdToExec: ` ip maddress del 33:33:00:00:00:01 dev eth0` 21 | } 22 | ]; 23 | 24 | export default Tests; 25 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/maddress-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { MaddressShowOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'show multicast addresses with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'maddress', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json maddress show` 18 | }, 19 | { 20 | description : 'show multicast addresses for interface `eth0`', 21 | options : { 22 | dev: 'eth0' 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'maddress', 31 | 'show', 32 | 'dev', 33 | 'eth0' 34 | ], 35 | expectedCmdToExec: ` ip -details -statistics -json maddress show dev eth0` 36 | } 37 | ]; 38 | 39 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/mroute-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { MrouteShowOptions, RouteRoutingTables } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'show multicast addresses with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'mroute', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json mroute show` 18 | }, 19 | { 20 | description : 'show multicast routes for destination `224.0.0.1/24`', 21 | options : { 22 | to: '224.0.0.1/24' 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'mroute', 31 | 'show', 32 | 'to', 33 | '224.0.0.1/24' 34 | ], 35 | expectedCmdToExec: ` ip -details -statistics -json mroute show to 224.0.0.1/24` 36 | }, 37 | { 38 | description : 'show multicast routes for incoming interface `eth0`', 39 | options : { 40 | iif: 'eth0' 41 | }, 42 | expectedCmd : [ 43 | '', 44 | 'ip', 45 | '-details', 46 | '-statistics', 47 | '-json', 48 | 'mroute', 49 | 'show', 50 | 'iif', 51 | 'eth0' 52 | ], 53 | expectedCmdToExec: ` ip -details -statistics -json mroute show iif eth0` 54 | }, 55 | { 56 | description : 'show multicast routes from source IP `192.168.1.10/24`', 57 | options : { 58 | from : '192.168.1.10/24', 59 | table: RouteRoutingTables.Local 60 | }, 61 | expectedCmd : [ 62 | '', 63 | 'ip', 64 | '-details', 65 | '-statistics', 66 | '-json', 67 | 'mroute', 68 | 'show', 69 | 'from', 70 | '192.168.1.10/24', 71 | 'table', 72 | RouteRoutingTables.Local 73 | ], 74 | expectedCmdToExec: ` ip -details -statistics -json mroute show from 192.168.1.10/24 table ${ RouteRoutingTables.Local }` 75 | } 76 | ]; 77 | 78 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-add.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourAddOptions } from '../../../../src'; 3 | import { NudStates } from '../../../../src/commands/neighbour.constants'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'simple ARP entry', 8 | options : { 9 | to : '192.168.1.100', 10 | lladdr: '00:aa:bb:cc:dd:ee', 11 | dev : 'eth0' 12 | }, 13 | expectedCmd : [ 14 | '', 15 | 'ip', 16 | 'neighbour', 17 | 'add', 18 | 'to', 19 | '192.168.1.100', 20 | 'lladdr', 21 | '00:aa:bb:cc:dd:ee', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip neighbour add to 192.168.1.100 lladdr 00:aa:bb:cc:dd:ee dev eth0` 26 | }, 27 | { 28 | description : 'permanent ARP entry', 29 | options : { 30 | to : '192.168.1.101', 31 | lladdr: '00:aa:bb:cc:dd:ef', 32 | dev : 'eth0', 33 | nud : NudStates.Permanent 34 | }, 35 | expectedCmd : [ 36 | '', 37 | 'ip', 38 | 'neighbour', 39 | 'add', 40 | 'to', 41 | '192.168.1.101', 42 | 'lladdr', 43 | '00:aa:bb:cc:dd:ef', 44 | 'nud', 45 | NudStates.Permanent, 46 | 'dev', 47 | 'eth0', 48 | ], 49 | expectedCmdToExec: ` ip neighbour add to 192.168.1.101 lladdr 00:aa:bb:cc:dd:ef nud ${ NudStates.Permanent } dev eth0` 50 | }, 51 | { 52 | description : 'proxy NDP Entry for IPv6', 53 | options : { 54 | to : '2001:0db8::3', 55 | lladdr: '00:aa:bb:cc:ee:fd', 56 | dev : 'eth0', 57 | }, 58 | expectedCmd : [ 59 | '', 60 | 'ip', 61 | 'neighbour', 62 | 'add', 63 | 'to', 64 | '2001:0db8::3', 65 | 'lladdr', 66 | '00:aa:bb:cc:ee:fd', 67 | 'dev', 68 | 'eth0', 69 | ], 70 | expectedCmdToExec: ` ip neighbour add to 2001:0db8::3 lladdr 00:aa:bb:cc:ee:fd dev eth0` 71 | } 72 | ]; 73 | 74 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-change.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourAddOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'MAC address of an ARP entry', 7 | options : { 8 | to : '192.168.1.100', 9 | lladdr: '11:22:33:44:55:66', 10 | dev : 'eth0' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'neighbour', 16 | 'change', 17 | 'to', 18 | '192.168.1.100', 19 | 'lladdr', 20 | '11:22:33:44:55:66', 21 | 'dev', 22 | 'eth0' 23 | ], 24 | expectedCmdToExec: ` ip neighbour change to 192.168.1.100 lladdr 11:22:33:44:55:66 dev eth0` 25 | }, 26 | { 27 | description : 'MAC address of a proxy ARP entry', 28 | options : { 29 | to : '192.168.1.102', 30 | lladdr: '11:22:33:44:55:68', 31 | dev : 'eth0', 32 | proxy : true 33 | }, 34 | expectedCmd : [ 35 | '', 36 | 'ip', 37 | 'neighbour', 38 | 'change', 39 | 'to', 40 | '192.168.1.102', 41 | 'lladdr', 42 | '11:22:33:44:55:68', 43 | 'proxy', 44 | 'dev', 45 | 'eth0' 46 | ], 47 | expectedCmdToExec: ` ip neighbour change to 192.168.1.102 lladdr 11:22:33:44:55:68 proxy dev eth0` 48 | }, 49 | { 50 | description : 'MAC address of an NDP entry with IPv6', 51 | options : { 52 | to : '2001:0db8::1', 53 | lladdr: '11:22:33:44:55:69', 54 | dev : 'eth0' 55 | }, 56 | expectedCmd : [ 57 | '', 58 | 'ip', 59 | 'neighbour', 60 | 'change', 61 | 'to', 62 | '2001:0db8::1', 63 | 'lladdr', 64 | '11:22:33:44:55:69', 65 | 'dev', 66 | 'eth0' 67 | ], 68 | expectedCmdToExec: ` ip neighbour change to 2001:0db8::1 lladdr 11:22:33:44:55:69 dev eth0` 69 | } 70 | ]; 71 | 72 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-delete.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourDelOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'ARP entry', 7 | options : { 8 | to : '192.168.1.100', 9 | dev: 'eth0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'neighbour', 15 | 'del', 16 | 'to', 17 | '192.168.1.100', 18 | 'dev', 19 | 'eth0' 20 | ], 21 | expectedCmdToExec: ` ip neighbour del to 192.168.1.100 dev eth0` 22 | }, 23 | { 24 | description : 'proxy ARP entry', 25 | options : { 26 | to : '192.168.1.100', 27 | dev : 'eth0', 28 | proxy: true 29 | }, 30 | expectedCmd : [ 31 | '', 32 | 'ip', 33 | 'neighbour', 34 | 'del', 35 | 'to', 36 | '192.168.1.100', 37 | 'proxy', 38 | 'dev', 39 | 'eth0' 40 | ], 41 | expectedCmdToExec: ` ip neighbour del to 192.168.1.100 proxy dev eth0` 42 | } 43 | ]; 44 | 45 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-flush.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourShowOptions } from '../../../../src'; 3 | import { NudStates } from '../../../../src/commands/neighbour.constants'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'ARP entries for a specific interface', 8 | options : { 9 | dev: 'eth0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'neighbour', 15 | 'flush', 16 | 'dev', 17 | 'eth0' 18 | ], 19 | expectedCmdToExec: ` ip neighbour flush dev eth0` 20 | }, 21 | { 22 | description : 'stale ARP entries', 23 | options : { 24 | nud: NudStates.Stale 25 | }, 26 | expectedCmd : [ 27 | '', 28 | 'ip', 29 | 'neighbour', 30 | 'flush', 31 | 'nud', 32 | NudStates.Stale 33 | ], 34 | expectedCmdToExec: ` ip neighbour flush nud ${ NudStates.Stale }` 35 | } 36 | ]; 37 | 38 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-get.ts: -------------------------------------------------------------------------------- 1 | import {TestFixture} from '../../../../src/common/interfaces/tests'; 2 | import {NeighbourGetOptions} from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : { 8 | to : '10.0.1.10', 9 | dev: 'eth0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | '-details', 15 | '-statistics', 16 | '-json', 17 | 'neighbour', 18 | 'get', 19 | 'to', 20 | '10.0.1.10', 21 | 'dev', 22 | 'eth0' 23 | ], 24 | expectedCmdToExec: ` ip -details -statistics -json neighbour get to 10.0.1.10 dev eth0` 25 | }, 26 | { 27 | description : 'with proxy enabled', 28 | options : { 29 | proxy: true, 30 | to : '10.0.1.10', 31 | dev : 'eth0' 32 | }, 33 | expectedCmd : [ 34 | '', 35 | 'ip', 36 | '-details', 37 | '-statistics', 38 | '-json', 39 | 'neighbour', 40 | 'get', 41 | 'proxy', 42 | 'to', 43 | '10.0.1.10', 44 | 'dev', 45 | 'eth0' 46 | ], 47 | expectedCmdToExec: ` ip -details -statistics -json neighbour get proxy to 10.0.1.10 dev eth0` 48 | } 49 | ]; 50 | 51 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-replace.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourAddOptions } from '../../../../src'; 3 | import { NudStates } from '../../../../src/commands/neighbour.constants'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'replace or add ARP entry with a MAC address', 8 | options : { 9 | to : '192.168.1.100', 10 | lladdr: '11:22:33:44:55:66', 11 | dev : 'eth0' 12 | }, 13 | expectedCmd : [ 14 | '', 15 | 'ip', 16 | 'neighbour', 17 | 'replace', 18 | 'to', 19 | '192.168.1.100', 20 | 'lladdr', 21 | '11:22:33:44:55:66', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip neighbour replace to 192.168.1.100 lladdr 11:22:33:44:55:66 dev eth0` 26 | }, 27 | { 28 | description : 'replace or add ARP entry and set to permanent', 29 | options : { 30 | to : '192.168.1.102', 31 | lladdr: '11:22:33:44:55:68', 32 | dev : 'eth0', 33 | nud: NudStates.Permanent 34 | }, 35 | expectedCmd : [ 36 | '', 37 | 'ip', 38 | 'neighbour', 39 | 'replace', 40 | 'to', 41 | '192.168.1.102', 42 | 'lladdr', 43 | '11:22:33:44:55:68', 44 | 'nud', 45 | NudStates.Permanent, 46 | 'dev', 47 | 'eth0', 48 | ], 49 | expectedCmdToExec: ` ip neighbour replace to 192.168.1.102 lladdr 11:22:33:44:55:68 nud ${NudStates.Permanent} dev eth0` 50 | } 51 | ]; 52 | 53 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/neighbour-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NeighbourShowOptions } from '../../../../src'; 3 | import { NudStates } from '../../../../src/commands/neighbour.constants'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | expectedCmd : [ 10 | '', 11 | 'ip', 12 | '-details', 13 | '-statistics', 14 | '-json', 15 | 'neighbour', 16 | 'show' 17 | ], 18 | expectedCmdToExec: ` ip -details -statistics -json neighbour show` 19 | }, 20 | { 21 | description : 'for a specific interface', 22 | options : { 23 | dev: 'eth0' 24 | }, 25 | expectedCmd : [ 26 | '', 27 | 'ip', 28 | '-details', 29 | '-statistics', 30 | '-json', 31 | 'neighbour', 32 | 'show', 33 | 'dev', 34 | 'eth0' 35 | ], 36 | expectedCmdToExec: ` ip -details -statistics -json neighbour show dev eth0` 37 | }, 38 | { 39 | description : 'show stale ARP entries', 40 | options : { 41 | nud: NudStates.Stale 42 | }, 43 | expectedCmd : [ 44 | '', 45 | 'ip', 46 | '-details', 47 | '-statistics', 48 | '-json', 49 | 'neighbour', 50 | 'show', 51 | 'nud', 52 | NudStates.Stale 53 | ], 54 | expectedCmdToExec: ` ip -details -statistics -json neighbour show nud ${ NudStates.Stale }` 55 | }, 56 | { 57 | description : 'for a specific IP and interface', 58 | options : { 59 | to : '192.168.1.100', 60 | dev: 'eth0' 61 | }, 62 | expectedCmd : [ 63 | '', 64 | 'ip', 65 | '-details', 66 | '-statistics', 67 | '-json', 68 | 'neighbour', 69 | 'show', 70 | 'to', 71 | '192.168.1.100', 72 | 'dev', 73 | 'eth0' 74 | ], 75 | expectedCmdToExec: ` ip -details -statistics -json neighbour show to 192.168.1.100 dev eth0` 76 | } 77 | ]; 78 | 79 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/ntable-change.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NtableChangeOptions } from '../../../../src/commands/ntable/change.interfaces'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'for a specific interface', 7 | options : { 8 | name : 'arp_cache', 9 | dev : 'eth0', 10 | queue: 8 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'ntable', 16 | 'change', 17 | 'name', 18 | 'arp_cache', 19 | 'dev', 20 | 'eth0', 21 | 'queue', 22 | 8 23 | ], 24 | expectedCmdToExec: ` ip ntable change name arp_cache dev eth0 queue 8` 25 | } 26 | ]; 27 | 28 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/ntable-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { NtableShowOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'ntable', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json ntable show` 18 | }, 19 | { 20 | description : 'for a specific interface', 21 | options : { 22 | dev: 'eth0' 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'ntable', 31 | 'show', 32 | 'dev', 33 | 'eth0' 34 | ], 35 | expectedCmdToExec: ` ip -details -statistics -json ntable show dev eth0` 36 | } 37 | ]; 38 | 39 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-append.ts: -------------------------------------------------------------------------------- 1 | import {RouteAddOptions} from '../../../../src/commands/route/add.interfaces'; 2 | import {TestFixture} from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description: 'with `to` `via` and `dev`', 7 | options: { 8 | to: 'default', 9 | via: { 10 | address: '192.168.1.1' 11 | }, 12 | dev: 'eth0' 13 | }, 14 | expectedCmd: [ 15 | '', 16 | 'ip', 17 | 'route', 18 | 'append', 19 | 'default', 20 | 'via', 21 | '192.168.1.1', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip route append default via 192.168.1.1 dev eth0` 26 | }, 27 | ]; 28 | 29 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-change.ts: -------------------------------------------------------------------------------- 1 | import {RouteAddOptions} from '../../../../src/commands/route/add.interfaces'; 2 | import {TestFixture} from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description: 'with `to` `via` and `dev`', 7 | options: { 8 | to: 'default', 9 | via: { 10 | address: '192.168.1.1' 11 | }, 12 | dev: 'eth0' 13 | }, 14 | expectedCmd: [ 15 | '', 16 | 'ip', 17 | 'route', 18 | 'change', 19 | 'default', 20 | 'via', 21 | '192.168.1.1', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip route change default via 192.168.1.1 dev eth0` 26 | }, 27 | ]; 28 | 29 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-delete.ts: -------------------------------------------------------------------------------- 1 | import {RouteAddOptions} from '../../../../src/commands/route/add.interfaces'; 2 | import {TestFixture} from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description: 'with `to` `via` and `dev`', 7 | options: { 8 | to: 'default', 9 | via: { 10 | address: '192.168.1.1' 11 | }, 12 | dev: 'eth0' 13 | }, 14 | expectedCmd: [ 15 | '', 16 | 'ip', 17 | 'route', 18 | 'delete', 19 | 'default', 20 | 'via', 21 | '192.168.1.1', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip route delete default via 192.168.1.1 dev eth0` 26 | }, 27 | ]; 28 | 29 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-flush.ts: -------------------------------------------------------------------------------- 1 | import { RouteRoutingTables } from '../../../../src/commands/route/show.constants'; 2 | import { RouteShowOptions } from '../../../../src/commands/route/show.interfaces'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | expectedCmd : [ 10 | '', 11 | 'ip', 12 | '-details', 13 | '-statistics', 14 | '-json', 15 | 'route', 16 | 'flush' 17 | ], 18 | expectedCmdToExec: ` ip -details -statistics -json route flush` 19 | }, 20 | { 21 | description : 'with `table = cache`', 22 | options : { 23 | table: RouteRoutingTables.Cache 24 | }, 25 | expectedCmd : [ 26 | '', 27 | 'ip', 28 | '-details', 29 | '-statistics', 30 | '-json', 31 | 'route', 32 | 'flush', 33 | 'table', 34 | RouteRoutingTables.Cache 35 | ], 36 | expectedCmdToExec: ` ip -details -statistics -json route flush table ${RouteRoutingTables.Cache}` 37 | } 38 | ]; 39 | 40 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-get.ts: -------------------------------------------------------------------------------- 1 | import { RouteGetOptions } from '../../../../src/commands/route/get.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'route', 15 | 'get' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json route get` 18 | }, 19 | { 20 | description : 'with `to = 8.8.8.8`', 21 | options : { 22 | to: '8.8.8.8' 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'route', 31 | 'get', 32 | 'to', 33 | '8.8.8.8' 34 | ], 35 | expectedCmdToExec: ` ip -details -statistics -json route get to 8.8.8.8` 36 | } 37 | ]; 38 | 39 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-replace.ts: -------------------------------------------------------------------------------- 1 | import {RouteAddOptions} from '../../../../src/commands/route/add.interfaces'; 2 | import {TestFixture} from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description: 'with `to` `via` and `dev`', 7 | options: { 8 | to: 'default', 9 | via: { 10 | address: '192.168.1.1' 11 | }, 12 | dev: 'eth0' 13 | }, 14 | expectedCmd: [ 15 | '', 16 | 'ip', 17 | 'route', 18 | 'replace', 19 | 'default', 20 | 'via', 21 | '192.168.1.1', 22 | 'dev', 23 | 'eth0' 24 | ], 25 | expectedCmdToExec: ` ip route replace default via 192.168.1.1 dev eth0` 26 | }, 27 | ]; 28 | 29 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-restore.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with `filePath` set', 8 | options : {}, 9 | globalOptions : { 10 | filePath: './test-dump-file.binary' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'route', 16 | 'restore', 17 | '<', 18 | './test-dump-file.binary' 19 | ], 20 | expectedCmdToExec: ` ip route restore < ./test-dump-file.binary` 21 | } 22 | ]; 23 | 24 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-save.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | globalOptions : { 10 | filePath: './test-dump-file.binary' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'route', 16 | 'save', 17 | '>', 18 | './test-dump-file.binary' 19 | ], 20 | expectedCmdToExec: ` ip route save > ./test-dump-file.binary` 21 | } 22 | ]; 23 | 24 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/route-show.ts: -------------------------------------------------------------------------------- 1 | import { RouteRoutingTables } from '../../../../src/commands/route/show.constants'; 2 | import { RouteShowOptions } from '../../../../src/commands/route/show.interfaces'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | expectedCmd : [ 10 | '', 11 | 'ip', 12 | '-details', 13 | '-statistics', 14 | '-json', 15 | 'route', 16 | 'show' 17 | ], 18 | expectedCmdToExec: ` ip -details -statistics -json route show` 19 | }, 20 | { 21 | description : 'with `table = main`', 22 | options : { 23 | table: RouteRoutingTables.Main 24 | }, 25 | expectedCmd : [ 26 | '', 27 | 'ip', 28 | '-details', 29 | '-statistics', 30 | '-json', 31 | 'route', 32 | 'show', 33 | 'table', 34 | RouteRoutingTables.Main 35 | ], 36 | expectedCmdToExec: ` ip -details -statistics -json route show table ${RouteRoutingTables.Main}` 37 | } 38 | ]; 39 | 40 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-add.ts: -------------------------------------------------------------------------------- 1 | import { RuleAddOptions } from '../../../../src/commands/rule/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `from` and `table`', 7 | options : { 8 | from : '192.168.1.10', 9 | table: 100 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'rule', 15 | 'add', 16 | 'from', 17 | '192.168.1.10', 18 | 'table', 19 | 100 20 | ], 21 | expectedCmdToExec: ` ip rule add from 192.168.1.10 table 100` 22 | }, 23 | { 24 | description : 'with `fwmark` and `table`', 25 | options : { 26 | fwmark: '0x1', 27 | table : 200 28 | }, 29 | expectedCmd : [ 30 | '', 31 | 'ip', 32 | 'rule', 33 | 'add', 34 | 'fwmark', 35 | '0x1', 36 | 'table', 37 | 200 38 | ], 39 | expectedCmdToExec: ` ip rule add fwmark 0x1 table 200` 40 | }, 41 | { 42 | description : 'with `tos`, `preference` and `table`', 43 | options : { 44 | tos : 10, 45 | preference: 3000, 46 | table : 300 47 | }, 48 | expectedCmd : [ 49 | '', 50 | 'ip', 51 | 'rule', 52 | 'add', 53 | 'tos', 54 | 10, 55 | 'preference', 56 | 3000, 57 | 'table', 58 | 300 59 | ], 60 | expectedCmdToExec: ` ip rule add tos 10 preference 3000 table 300` 61 | } 62 | ]; 63 | 64 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-delete.ts: -------------------------------------------------------------------------------- 1 | import { RuleAddOptions } from '../../../../src/commands/rule/add.interfaces'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `from` and `table`', 7 | options : { 8 | from : '192.168.1.10', 9 | table: 100 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'rule', 15 | 'delete', 16 | 'from', 17 | '192.168.1.10', 18 | 'table', 19 | 100 20 | ], 21 | expectedCmdToExec: ` ip rule delete from 192.168.1.10 table 100` 22 | } 23 | ]; 24 | 25 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-flush.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | 'rule', 12 | 'flush' 13 | ], 14 | expectedCmdToExec: ` ip rule flush` 15 | } 16 | ]; 17 | 18 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-restore.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with `filePath` set', 8 | options : {}, 9 | globalOptions : { 10 | filePath: './test-dump-file.binary' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'rule', 16 | 'restore', 17 | '<', 18 | './test-dump-file.binary' 19 | ], 20 | expectedCmdToExec: ` ip rule restore < ./test-dump-file.binary` 21 | } 22 | ]; 23 | 24 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-save.ts: -------------------------------------------------------------------------------- 1 | import { Empty } from '../../../../src/common/interfaces/common'; 2 | import { GlobalOptionsWithRequiredFilePath } from '../../../../src/common/interfaces/common'; 3 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | globalOptions : { 10 | filePath: './test-dump-file.binary' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'rule', 16 | 'save', 17 | '>', 18 | './test-dump-file.binary' 19 | ], 20 | expectedCmdToExec: ` ip rule save > ./test-dump-file.binary` 21 | } 22 | ]; 23 | 24 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/rule-show.ts: -------------------------------------------------------------------------------- 1 | import { RoutingTables } from '../../../../src/commands/rule.constants'; 2 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 3 | import { RuleShowOptions } from '../../../../src'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'with no params', 8 | options : {}, 9 | expectedCmd : [ 10 | '', 11 | 'ip', 12 | '-details', 13 | '-statistics', 14 | '-json', 15 | 'rule', 16 | 'show' 17 | ], 18 | expectedCmdToExec: ` ip -details -statistics -json rule show` 19 | }, 20 | { 21 | description : 'with `table = main`', 22 | options : { 23 | table: RoutingTables.Main 24 | }, 25 | expectedCmd : [ 26 | '', 27 | 'ip', 28 | '-details', 29 | '-statistics', 30 | '-json', 31 | 'rule', 32 | 'show', 33 | 'table', 34 | RoutingTables.Main 35 | ], 36 | expectedCmdToExec: ` ip -details -statistics -json rule show table ${RoutingTables.Main}` 37 | }, 38 | { 39 | description : 'shows IPv4 and IPv6 addresses assigned to network interface `eth0`', 40 | options : { 41 | preference: 0 42 | }, 43 | expectedCmd : [ 44 | '', 45 | 'ip', 46 | '-details', 47 | '-statistics', 48 | '-json', 49 | 'rule', 50 | 'show', 51 | 'preference', 52 | 0 53 | ], 54 | expectedCmdToExec: ` ip -details -statistics -json rule show preference 0` 55 | } 56 | ]; 57 | 58 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-add.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunnelAddOptions } from '../../../../src'; 3 | import { TunnelModes } from '../../../../src/commands/tunnel.constants'; 4 | 5 | export const Tests: TestFixture[] = [ 6 | { 7 | description : 'simple GRE tunnel', 8 | options : { 9 | name : 'tun0', 10 | mode : TunnelModes.Gre, 11 | remote: '203.0.113.4', 12 | local : '203.0.113.5', 13 | dev : 'eth0' 14 | }, 15 | expectedCmd : [ 16 | '', 17 | 'ip', 18 | 'tunnel', 19 | 'add', 20 | 'name', 21 | 'tun0', 22 | 'mode', 23 | TunnelModes.Gre, 24 | 'remote', 25 | '203.0.113.4', 26 | 'local', 27 | '203.0.113.5', 28 | 'dev', 29 | 'eth0' 30 | ], 31 | expectedCmdToExec: ` ip tunnel add name tun0 mode ${ TunnelModes.Gre } remote 203.0.113.4 local 203.0.113.5 dev eth0` 32 | }, 33 | { 34 | description : 'IPIP tunnel', 35 | options : { 36 | name : 'tun1', 37 | mode : TunnelModes.Ipip, 38 | remote: '203.0.113.6', 39 | local : '203.0.113.7', 40 | dev : 'eth1' 41 | }, 42 | expectedCmd : [ 43 | '', 44 | 'ip', 45 | 'tunnel', 46 | 'add', 47 | 'name', 48 | 'tun1', 49 | 'mode', 50 | TunnelModes.Ipip, 51 | 'remote', 52 | '203.0.113.6', 53 | 'local', 54 | '203.0.113.7', 55 | 'dev', 56 | 'eth1' 57 | ], 58 | expectedCmdToExec: ` ip tunnel add name tun1 mode ${ TunnelModes.Ipip } remote 203.0.113.6 local 203.0.113.7 dev eth1` 59 | } 60 | ]; 61 | 62 | export default Tests; 63 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-change.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunnelAddOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'change GRE tunnel parameters', 7 | options : { 8 | name: 'tun0', 9 | ttl : 64, 10 | dev : 'eth0' 11 | }, 12 | expectedCmd : [ 13 | '', 14 | 'ip', 15 | 'tunnel', 16 | 'change', 17 | 'name', 18 | 'tun0', 19 | 'ttl', 20 | 64, 21 | 'dev', 22 | 'eth0' 23 | ], 24 | expectedCmdToExec: ` ip tunnel change name tun0 ttl 64 dev eth0` 25 | }, 26 | { 27 | description : 'change IPIP tunnel parameters', 28 | options : { 29 | name: 'tun1', 30 | ttl : 32, 31 | dev : 'eth1' 32 | }, 33 | expectedCmd : [ 34 | '', 35 | 'ip', 36 | 'tunnel', 37 | 'change', 38 | 'name', 39 | 'tun1', 40 | 'ttl', 41 | 32, 42 | 'dev', 43 | 'eth1' 44 | ], 45 | expectedCmdToExec: ` ip tunnel change name tun1 ttl 32 dev eth1` 46 | } 47 | ]; 48 | 49 | export default Tests; 50 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-del.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunnelAddOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'delete simple GRE tunnel', 7 | options : { 8 | name: 'tun0' 9 | }, 10 | expectedCmd : [ 11 | '', 12 | 'ip', 13 | 'tunnel', 14 | 'del', 15 | 'name', 16 | 'tun0' 17 | ], 18 | expectedCmdToExec: ` ip tunnel del name tun0` 19 | }, 20 | { 21 | description : 'delete IPIP tunnel', 22 | options : { 23 | name: 'tun1' 24 | }, 25 | expectedCmd : [ 26 | '', 27 | 'ip', 28 | 'tunnel', 29 | 'del', 30 | 'name', 31 | 'tun1' 32 | ], 33 | expectedCmdToExec: ` ip tunnel del name tun1` 34 | } 35 | ]; 36 | 37 | export default Tests; 38 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-prl.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunnelPrlOptions } from '../../../../src'; // Assuming there's a suitable type for prl (Potential Router List) 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with `prl-default` option set', 7 | options : { 8 | dev : 'tun0', 9 | 'prl-default': '203.0.113.8' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'tunnel', 15 | 'prl', 16 | 'dev', 17 | 'tun0', 18 | 'prl-default', 19 | '203.0.113.8' 20 | ], 21 | expectedCmdToExec: ` ip tunnel prl dev tun0 prl-default 203.0.113.8` 22 | }, 23 | { 24 | description : 'with `prl-delete` option set', 25 | options : { 26 | dev : 'tun0', 27 | 'prl-delete': '203.0.113.9' 28 | }, 29 | expectedCmd : [ 30 | '', 31 | 'ip', 32 | 'tunnel', 33 | 'prl', 34 | 'dev', 35 | 'tun0', 36 | 'prl-delete', 37 | '203.0.113.9' 38 | ], 39 | expectedCmdToExec: ` ip tunnel prl dev tun0 prl-delete 203.0.113.9` 40 | } 41 | ]; 42 | 43 | export default Tests; 44 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { Empty } from '../../../../src'; // Assuming there's a suitable type for show 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'show all tunnels', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'tunnel', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json tunnel show` 18 | } 19 | ]; 20 | 21 | export default Tests; 22 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tunnel-v6rd.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { Tunnel6rdOptions } from '../../../../src'; // Assuming there's a suitable type for 6rd configurations 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'simple 6rd tunnel', 7 | options : { 8 | dev : 'tun0', 9 | '6rd-prefix': '2001:db8::' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'tunnel', 15 | '6rd', 16 | 'dev', 17 | 'tun0', 18 | '6rd-prefix', 19 | '2001:db8::' 20 | ], 21 | expectedCmdToExec: ` ip tunnel 6rd dev tun0 6rd-prefix 2001:db8::` 22 | }, 23 | { 24 | description : '6rd tunnel with relay prefix', 25 | options : { 26 | dev : 'tun0', 27 | '6rd-prefix' : '2001:db9::', 28 | '6rd-relay_prefix': '192.168.1.0' 29 | }, 30 | expectedCmd : [ 31 | '', 32 | 'ip', 33 | 'tunnel', 34 | '6rd', 35 | 'dev', 36 | 'tun0', 37 | '6rd-prefix', 38 | '2001:db9::', 39 | '6rd-relay_prefix', 40 | '192.168.1.0' 41 | ], 42 | expectedCmdToExec: ` ip tunnel 6rd dev tun0 6rd-prefix 2001:db9:: 6rd-relay_prefix 192.168.1.0` 43 | } 44 | // You can continue adding more cases as needed for various configurations 45 | ]; 46 | 47 | export default Tests; 48 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tuntap-add.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunTapTunnelAddOptions, TunTapTunnelModes } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'create a TUN device named `mytun0`', 7 | options : { 8 | dev : 'mytun0', 9 | mode: TunTapTunnelModes.Tun 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'tuntap', 15 | 'add', 16 | 'dev', 17 | 'mytun0', 18 | 'mode', 19 | TunTapTunnelModes.Tun 20 | ], 21 | expectedCmdToExec: ` ip tuntap add dev mytun0 mode ${ TunTapTunnelModes.Tun }` 22 | }, 23 | { 24 | description : 'create a TAP device named `mytap0`', 25 | options : { 26 | dev : 'mytap0', 27 | mode: TunTapTunnelModes.Tap 28 | }, 29 | expectedCmd : [ 30 | '', 31 | 'ip', 32 | 'tuntap', 33 | 'add', 34 | 'dev', 35 | 'mytap0', 36 | 'mode', 37 | TunTapTunnelModes.Tap 38 | ], 39 | expectedCmdToExec: ` ip tuntap add dev mytap0 mode ${ TunTapTunnelModes.Tap }` 40 | }, 41 | { 42 | description : 'create a TAP device named `mytap1` and set the user ID to 1000 (commonly the default user ID for the first non-root user)', 43 | options : { 44 | dev : 'mytap1', 45 | mode: TunTapTunnelModes.Tap, 46 | user: 1000 47 | }, 48 | expectedCmd : [ 49 | '', 50 | 'ip', 51 | 'tuntap', 52 | 'add', 53 | 'dev', 54 | 'mytap1', 55 | 'mode', 56 | TunTapTunnelModes.Tap, 57 | 'user', 58 | 1000 59 | ], 60 | expectedCmdToExec: ` ip tuntap add dev mytap1 mode ${ TunTapTunnelModes.Tap } user 1000` 61 | }, 62 | { 63 | description : 'create a TUN device with multi-queue support (for improved multi-core performance)', 64 | options : { 65 | dev : 'mytun1', 66 | mode : TunTapTunnelModes.Tun, 67 | multi_queue: true 68 | }, 69 | expectedCmd : [ 70 | '', 71 | 'ip', 72 | 'tuntap', 73 | 'add', 74 | 'dev', 75 | 'mytun1', 76 | 'mode', 77 | TunTapTunnelModes.Tun, 78 | 'multi_queue' 79 | ], 80 | expectedCmdToExec: ` ip tuntap add dev mytun1 mode ${ TunTapTunnelModes.Tun } multi_queue` 81 | } 82 | ]; 83 | 84 | export default Tests; 85 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tuntap-del.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunTapTunnelAddOptions, TunTapTunnelModes } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'delete a TUN device named `mytun0`', 7 | options : { 8 | mode: TunTapTunnelModes.Tun, 9 | name: 'mytun0' 10 | }, 11 | expectedCmd : [ 12 | '', 13 | 'ip', 14 | 'tuntap', 15 | 'del', 16 | 'mode', 17 | TunTapTunnelModes.Tun, 18 | 'name', 19 | 'mytun0' 20 | ], 21 | expectedCmdToExec: ` ip tuntap del mode ${ TunTapTunnelModes.Tun } name mytun0` 22 | }, 23 | { 24 | description : 'delete a TAP device named `mytap0`', 25 | options : { 26 | mode: TunTapTunnelModes.Tap, 27 | name: 'mytap0' 28 | }, 29 | expectedCmd : [ 30 | '', 31 | 'ip', 32 | 'tuntap', 33 | 'del', 34 | 'mode', 35 | TunTapTunnelModes.Tap, 36 | 'name', 37 | 'mytap0' 38 | ], 39 | expectedCmdToExec: ` ip tuntap del mode ${ TunTapTunnelModes.Tap } name mytap0` 40 | }, 41 | { 42 | description : 'delete a TAP device named `mytap1`', 43 | options : { 44 | mode: TunTapTunnelModes.Tap, 45 | name: 'mytap1' 46 | }, 47 | expectedCmd : [ 48 | '', 49 | 'ip', 50 | 'tuntap', 51 | 'del', 52 | 'mode', 53 | TunTapTunnelModes.Tap, 54 | 'name', 55 | 'mytap1' 56 | ], 57 | expectedCmdToExec: ` ip tuntap del mode ${ TunTapTunnelModes.Tap } name mytap1` 58 | } 59 | ]; 60 | 61 | export default Tests; 62 | -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/fixtures/tuntap-show.ts: -------------------------------------------------------------------------------- 1 | import { TestFixture } from '../../../../src/common/interfaces/tests'; 2 | import { TunTapTunnelModes, TunTapTunnelShowOptions } from '../../../../src'; 3 | 4 | export const Tests: TestFixture[] = [ 5 | { 6 | description : 'with no params', 7 | options : {}, 8 | expectedCmd : [ 9 | '', 10 | 'ip', 11 | '-details', 12 | '-statistics', 13 | '-json', 14 | 'tuntap', 15 | 'show' 16 | ], 17 | expectedCmdToExec: ` ip -details -statistics -json tuntap show` 18 | }, 19 | { 20 | description : 'with a mode set', 21 | options : { 22 | mode: TunTapTunnelModes.Tun 23 | }, 24 | expectedCmd : [ 25 | '', 26 | 'ip', 27 | '-details', 28 | '-statistics', 29 | '-json', 30 | 'tuntap', 31 | 'show', 32 | 'mode', 33 | TunTapTunnelModes.Tun 34 | ], 35 | expectedCmdToExec: ` ip -details -statistics -json tuntap show mode ${ TunTapTunnelModes.Tun }` 36 | } 37 | ]; 38 | 39 | export default Tests; -------------------------------------------------------------------------------- /__tests__/safe/cmd-generation/ip-commands.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import { fixtures } from './fixtures'; 5 | 6 | Object 7 | .keys(fixtures) 8 | .forEach((key) => { 9 | describe(key, function () { 10 | fixtures[key].forEach(({ operator, testBattery, method, skipOptions }) => { 11 | 12 | describe(operator, function () { 13 | testBattery.forEach((test) => { 14 | 15 | describe(test.description, function () { 16 | it('should build the proper cmd array & string', async function () { 17 | let globalOptions: any = Object 18 | .assign({}, test.globalOptions || {}, 19 | { 20 | dryRun: true 21 | }); 22 | 23 | let ipCommand = (skipOptions) 24 | ? await method(globalOptions) as any 25 | : await method(test.options as any, globalOptions) as any; 26 | 27 | expect(ipCommand.cmd) 28 | .to.be.an('array') 29 | .and.to.be.deep.eq(test.expectedCmd); 30 | 31 | expect(ipCommand.cmdToExec) 32 | .to.be.a('string') 33 | .and.to.be.eq(test.expectedCmdToExec); 34 | }); 35 | }); 36 | }); 37 | }); 38 | }); 39 | }); 40 | }); -------------------------------------------------------------------------------- /__tests__/safe/parsers/monitor.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | import MonitorCommand from '../../../src/common/classes/monitor-command'; 5 | import { generatedFromTests } from './monitor.fixtures'; 6 | 7 | describe('monitor', () => { 8 | describe('parseOutput', () => { 9 | it('should properly return a parsed object', () => { 10 | const line = generatedFromTests.split('\n'); 11 | 12 | for (let lineNumber = 0, outputLength = line.length - 1; 13 | lineNumber < outputLength; 14 | lineNumber++) { 15 | 16 | let parsedData = MonitorCommand.parseLineOutput(line[lineNumber]); 17 | 18 | expect(parsedData).to.be.an('object'); 19 | expect(parsedData).to.have.keys([ 20 | 'timestamp', 21 | 'nsid', 22 | 'object', 23 | 'lines', 24 | 'originalLine' 25 | ]); 26 | 27 | expect(parsedData.timestamp).to.be.a('string'); 28 | expect(parsedData.nsid).to.be.a('string'); 29 | expect(parsedData.object).to.be.a('string'); 30 | expect(parsedData.lines).to.be.an('array').with.lengthOf.at.least(1); 31 | expect(parsedData.originalLine).to.be.a('string'); 32 | } 33 | }); 34 | }); 35 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iproute", 3 | "version": "2.3.0", 4 | "description": "Show and manipulate network devices, addresses, routing, policy routing, tunnels, IP forwarding, address labels and other `iproute` objects.", 5 | "main": "./lib/index.js", 6 | "types": "./lib/index.d.ts", 7 | "scripts": { 8 | "build": "npm run build:ts", 9 | "build:ts": "npm run clean && npx tsc --project tsconfig.json", 10 | "clean": "npx rimraf ./lib", 11 | "test": "npm run test:safe", 12 | "test:all": "npm run build && npx mocha --spec=./__tests__/**/*.ts", 13 | "test:safe": "npm run build && npx mocha --spec=./__tests__/safe/**/*.ts", 14 | "test:exec": "npm run build && npx mocha --spec=./__tests__/exec/**/*.ts", 15 | "test:github-actions": "npm run build && npx mocha --spec='./__tests__/**/*.ts' --exclude='./__tests__/exec/utils/**/*.ts' --exclude='./__tests__/exec/commands/monitor.ts'", 16 | "docs": "npx typedoc --options typedoc.config.json" 17 | }, 18 | "keywords": [ 19 | "device", 20 | "interface", 21 | "address", 22 | "route", 23 | "routing", 24 | "ip", 25 | "iproute", 26 | "iproute2", 27 | "tunnel", 28 | "network", 29 | "monitor", 30 | "link", 31 | "vlan", 32 | "rule", 33 | "rpdb", 34 | "table", 35 | "monitor", 36 | "network", 37 | "networking", 38 | "utils", 39 | "forwarding", 40 | "addrlabel", 41 | "neighbour", 42 | "neigh", 43 | "neighbour", 44 | "ntable", 45 | "tuntap", 46 | "maddress", 47 | "mroute", 48 | "batch" 49 | ], 50 | "dependencies": { 51 | "ajv": "^8.12.0", 52 | "ajv-formats": "^2.1.1", 53 | "lodash.isplainobject": "^4.0.6" 54 | }, 55 | "engines": { 56 | "node": ">=14.0.0" 57 | }, 58 | "homepage": "https://diosney.github.io/node-iproute", 59 | "bugs": { 60 | "url": "https://github.com/diosney/node-iproute/issues" 61 | }, 62 | "author": { 63 | "name": "Diosney Sarmiento", 64 | "email": "diosney.s@gmail.com" 65 | }, 66 | "license": "MIT", 67 | "repository": { 68 | "type": "git", 69 | "url": "https://github.com/diosney/node-iproute.git" 70 | }, 71 | "funding": { 72 | "type": "ko-fi", 73 | "url": "https://ko-fi.com/diosney" 74 | }, 75 | "files": [ 76 | "lib/" 77 | ], 78 | "devDependencies": { 79 | "@types/ajv": "^1.0.0", 80 | "@types/chai": "^4.3.5", 81 | "@types/lodash.isplainobject": "^4.0.7", 82 | "@types/mocha": "^10.0.1", 83 | "@types/node": "^18.17.5", 84 | "chai": "^4.3.7", 85 | "mocha": "^10.2.0", 86 | "rimraf": "^5.0.1", 87 | "source-map-support": "^0.5.21", 88 | "ts-node": "^10.9.1", 89 | "typedoc": "^0.25.0", 90 | "typescript": "^5.1.6" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/commands/address.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The scope of the area where this address is valid. 3 | * The available scopes are listed in file `/etc/iproute2/rt_scopes`. 4 | * Predefined scope values are: 5 | * 6 | * @category Constants 7 | */ 8 | export enum AddressScopes { 9 | /** The address is globally valid. */ 10 | Global = 'global', 11 | /** (IPv6 only, deprecated) The address is site local, i.e. it is valid inside this site. */ 12 | Site = 'site', 13 | /** The address is link local, i.e. it is valid only on this device. */ 14 | Link = 'link', 15 | /** The address is valid only inside this host. */ 16 | Host = 'host', 17 | } 18 | 19 | /** 20 | * Representing various network address families. 21 | * @category Constants 22 | */ 23 | export enum AddressFamilies { 24 | /** IPv4 protocol. */ 25 | Inet = 'inet', 26 | /** IPv6 protocol. */ 27 | Inet6 = 'inet6', 28 | /** Multi-Protocol Label Switching. */ 29 | Mpls = 'mpls', 30 | /** Bridging (MAC-level). */ 31 | Bridge = 'bridge', 32 | /** Link layer interface. */ 33 | Link = 'link', 34 | } -------------------------------------------------------------------------------- /src/commands/address/delete.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { AddressScopes } from '../address.constants'; 2 | 3 | /** 4 | * Address delete options. 5 | * @category Interfaces 6 | */ 7 | export interface AddressDeleteOptions { 8 | /** 9 | * The address of the interface. The format of the address depends on the protocol. 10 | * 11 | * It is a dotted quad for IP and a sequence of hexadecimal halfwords separated by colons for IPv6. 12 | * The ADDRESS may be followed by a slash and a decimal number which encodes the network prefix length. 13 | */ 14 | local: string; 15 | /** 16 | * The address of the remote endpoint for pointopoint interfaces. 17 | * 18 | * Again, the ADDRESS may be followed by a slash and a decimal number, encoding the network prefix length. 19 | * If a peer address is specified, the local address cannot have a prefix length. 20 | * The network prefix is associated with the peer rather than with the local address. 21 | */ 22 | peer?: string; 23 | /** 24 | * The broadcast address on the interface. 25 | * 26 | * It is possible to use the special symbols '+' and '-' instead of the broadcast address. 27 | * In this case, the broadcast address is derived by setting/resetting the host bits of the interface prefix. 28 | */ 29 | broadcast?: '+' | '-' | string; 30 | /** TODO: Missing from manpage. */ 31 | anycast?: string; 32 | /** 33 | * Each address may be tagged with a label string. 34 | * In order to preserve compatibility with Linux-2.0 net aliases, this string must coincide with the 35 | * name of the device or must be prefixed with the device name followed by colon. 36 | * The maximum allowed total length of label is 15 characters. 37 | */ 38 | label?: string; 39 | /** 40 | * The scope of the area where this address is valid. 41 | * The available scopes are listed in file `/etc/iproute2/rt_scopes`. 42 | */ 43 | scope?: AddressScopes | number; 44 | /** The name of the device. */ 45 | dev: string; 46 | /** 47 | * (IPv6 only) make the kernel manage temporary addresses created from this one as template on behalf of 48 | * Privacy Extensions (RFC3041). 49 | * 50 | * For this to become active, the `use_tempaddr` sysctl setting has to be set to a value greater than zero. 51 | * The given address needs to have a prefix length of 64. 52 | * 53 | * This flag allows to use privacy extensions in a manually configured network, just like if stateless 54 | * auto-configuration was active. 55 | */ 56 | mngtmpaddr?: true; 57 | } -------------------------------------------------------------------------------- /src/commands/address/delete.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { AddressDeleteOptions } from './delete.interfaces'; 5 | import { AddressScopes } from '../address.constants'; 6 | 7 | export const AddressDeleteSchema: JSONSchemaType = { 8 | $id: SchemaIds.AddressDelete, 9 | type: 'object', 10 | required: [ 'local', 'dev' ], 11 | properties: { 12 | local: { 13 | type: 'string', 14 | format: 'ip-with-optional-mask' 15 | }, 16 | peer: { 17 | type: 'string', 18 | format: 'ip-with-optional-mask', 19 | nullable: true 20 | }, 21 | broadcast: { 22 | type: 'string', 23 | format: 'ip-with-optional-mask', 24 | nullable: true 25 | }, 26 | anycast: { 27 | type: 'string', 28 | format: 'ip-with-optional-mask', 29 | nullable: true 30 | }, 31 | label: { 32 | type: 'string', 33 | minLength: 1, 34 | maxLength: 15, 35 | nullable: true 36 | }, 37 | scope: { 38 | type: [ 'string', 'integer' ], 39 | nullable: true, 40 | oneOf: [ 41 | { 42 | type: 'string', 43 | enum: Object.values(AddressScopes) as AddressScopes[], 44 | nullable: true 45 | }, 46 | { 47 | type: 'integer', 48 | minimum: 0, 49 | nullable: true 50 | } 51 | ] 52 | }, 53 | dev: { 54 | type: 'string', 55 | minLength: 1, 56 | maxLength: 15 57 | }, 58 | mngtmpaddr: { 59 | type: 'boolean', 60 | enum: [ true ], 61 | nullable: true 62 | } 63 | } 64 | }; -------------------------------------------------------------------------------- /src/commands/addrlabel/add.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Addrlabel add options. 3 | * @category Interfaces 4 | */ 5 | export interface AddrlabelAddOptions { 6 | /** The address prefix. */ 7 | prefix: string; 8 | /** The outgoing interface. */ 9 | dev?: string; 10 | /** The label for the prefix. `0xffffffff` is reserved. */ 11 | label: number; 12 | } -------------------------------------------------------------------------------- /src/commands/addrlabel/add.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { AddrlabelAddOptions } from './add.interfaces'; 5 | 6 | export const AddrlabelAddSchema: JSONSchemaType = { 7 | $id: SchemaIds.AddrlabelAdd, 8 | type: 'object', 9 | required: ['prefix', 'label'], 10 | properties: { 11 | prefix: { 12 | type: 'string', 13 | minLength: 1, 14 | format: 'ip-with-required-mask' 15 | }, 16 | dev: { 17 | type: 'string', 18 | minLength: 1, 19 | nullable: true 20 | }, 21 | label: { 22 | type: 'integer', 23 | minimum: 0, 24 | } 25 | } 26 | }; -------------------------------------------------------------------------------- /src/commands/addrlabel/del.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { AddrlabelAddOptions } from './add.interfaces'; 2 | 3 | /** 4 | * Addrlabel delete options. 5 | * @category Interfaces 6 | */ 7 | export type AddrlabelDelOptions = Partial> & Omit; 8 | -------------------------------------------------------------------------------- /src/commands/addrlabel/del.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { AddrlabelDelOptions } from './del.interfaces'; 5 | 6 | export const AddrlabelDelSchema: JSONSchemaType = { 7 | $id: SchemaIds.AddrlabelDel, 8 | type: 'object', 9 | required: ['prefix'], 10 | properties: { 11 | prefix: { 12 | type: 'string', 13 | minLength: 1, 14 | format: 'ip-with-required-mask' 15 | }, 16 | dev: { 17 | type: 'string', 18 | minLength: 1, 19 | nullable: true 20 | }, 21 | label: { 22 | type: 'integer', 23 | minimum: 0, 24 | nullable: true 25 | } 26 | } 27 | }; -------------------------------------------------------------------------------- /src/commands/addrlabel/list.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Addrlabel info. 3 | * @category Interfaces 4 | */ 5 | export interface AddrlabelInfo { 6 | address: string; 7 | prefixlen: number; 8 | label: number; 9 | } -------------------------------------------------------------------------------- /src/commands/batch.ts: -------------------------------------------------------------------------------- 1 | import CommandWithFilepath from '../common/classes/command-with-filepath'; 2 | import Command from '../common/classes/command'; 3 | import CommandWithStdin from '../common/classes/command-with-stdin'; 4 | 5 | import { EmptySchema, SchemaIds, StdinGlobalOptionSchema } from '../common/constants/schemas'; 6 | 7 | import { 8 | Empty, 9 | GlobalOptionsWithRequiredFilePath, 10 | GlobalOptionsWithRequiredStdin 11 | } from '../common/interfaces/common'; 12 | 13 | /** 14 | * Read commands from provided file and invoke them. 15 | * First failure will cause termination of `ip`. 16 | * 17 | * @param globalOptions - Global parameters options that affects the command execution. 18 | * 19 | * @throws {@link ParametersError} - Throws when passed parameters are invalid. 20 | * @throws {@link CommandError} - Throws when the executed command fails. 21 | * 22 | * @example 23 | * 24 | * Import module 25 | * ``` 26 | * import { batch } from 'iproute'; 27 | * ``` 28 | * 29 | * Executes batch commands from a file 30 | * ``` 31 | * await batch.fromFile({ 32 | * filePath: '/tmp/filepath' 33 | * }); 34 | * ``` 35 | */ 36 | export async function fromFile(globalOptions: GlobalOptionsWithRequiredFilePath): Promise> { 37 | const cmd = ['ip', '-batch']; 38 | 39 | const ipCmd = new CommandWithFilepath( 40 | SchemaIds.Empty, 41 | EmptySchema, 42 | {}, 43 | globalOptions, 44 | cmd); 45 | 46 | return await ipCmd.exec(); 47 | } 48 | 49 | /** 50 | * Read commands from standard input and invoke them. 51 | * First failure will cause termination of `ip`. 52 | * 53 | * @param globalOptions - Global parameters options that affects the command execution. 54 | * 55 | * @throws {@link ParametersError} - Throws when passed parameters are invalid. 56 | * @throws {@link CommandError} - Throws when the executed command fails. 57 | * 58 | * @example 59 | * 60 | * Import module 61 | * ``` 62 | * import { batch } from 'iproute'; 63 | * ``` 64 | * 65 | * Executes batch commands from stdin 66 | * ``` 67 | * await batch.fromStdin({ 68 | * stdin: [ 69 | * 'address add local 127.0.1.4/32 dev lo', 70 | * 'address add local 127.0.1.5/32 dev lo', 71 | * 'address add local 127.0.1.6/32 dev lo', 72 | * 'address add local 127.0.1.7/32 dev lo' 73 | * ].join('\n') 74 | * }); 75 | * ``` 76 | */ 77 | export async function fromStdin(globalOptions: GlobalOptionsWithRequiredStdin): Promise> { 78 | const cmd = ['ip', '-batch']; 79 | 80 | const ipCmd = new CommandWithStdin( 81 | SchemaIds.Empty, 82 | EmptySchema, 83 | {}, 84 | globalOptions, 85 | cmd); 86 | 87 | return await ipCmd.exec(); 88 | } 89 | 90 | export default { 91 | fromFile, 92 | fromStdin 93 | }; -------------------------------------------------------------------------------- /src/commands/link/delete.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { LinkTypes } from '../link.constants'; 2 | import { LinkTypesMappings } from './add.interfaces'; 3 | 4 | /** 5 | * Link delete options. 6 | * @category Interfaces 7 | */ 8 | export interface LinkDeleteOptions { 9 | /** Specifies the virtual device to act operate on. */ 10 | dev?: string; 11 | /** 12 | * Specifies the group of virtual links to delete. 13 | * Group 0 is not allowed to be deleted since it is the default group. 14 | */ 15 | group?: number; 16 | /** 17 | * Specifies the type of the device. 18 | * @see {@link LinkTypes} 19 | */ 20 | type?: { 21 | [key in LinkTypes]?: LinkTypesMappings[key]; 22 | }; 23 | } -------------------------------------------------------------------------------- /src/commands/link/delete.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { LinkDeleteOptions } from './delete.interfaces'; 5 | import { typePropertiesSchema } from './add.schema'; 6 | 7 | export const LinkDeleteSchema: JSONSchemaType = { 8 | $id: SchemaIds.LinkDelete, 9 | type: 'object', 10 | required: [], 11 | properties: { 12 | dev: { 13 | type: 'string', 14 | minLength: 1, 15 | keyless: true, 16 | nullable: true 17 | }, 18 | group: { 19 | type: 'integer', 20 | minimum: 0, 21 | nullable: true 22 | }, 23 | type: { 24 | type: 'object', 25 | nullable: true, 26 | properties: typePropertiesSchema 27 | } 28 | } 29 | }; -------------------------------------------------------------------------------- /src/commands/link/extended-virtual-link-types/bond-slave.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Set link bond-slave type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface SetLinkBondSlaveTypeArgs { 6 | /** Set the slave's queue ID (a 16bit unsigned value). */ 7 | queue_id?: number; 8 | } -------------------------------------------------------------------------------- /src/commands/link/extended-virtual-link-types/bond-slave.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SetLinkBondSlaveTypeArgs } from './bond-slave.interfaces'; 4 | 5 | export const SetLinkBondSlaveArgsSchema: JSONSchemaType = { 6 | type : 'object', 7 | required : [], 8 | additionalProperties: false, 9 | properties : { 10 | queue_id: { 11 | type : 'integer', 12 | minimum : 0, 13 | nullable: true 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /src/commands/link/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { ExtendedLinkTypes } from '../link.constants'; 4 | import { SchemaIds } from '../../common/constants/schemas'; 5 | import { LinkShowOptions } from './show.interfaces'; 6 | 7 | export const LinkShowSchema: JSONSchemaType = { 8 | $id: SchemaIds.LinkShow, 9 | type: 'object', 10 | required: [], 11 | properties: { 12 | dev: { 13 | type: 'string', 14 | minLength: 1, 15 | nullable: true 16 | }, 17 | group: { 18 | type: 'integer', 19 | minimum: 0, 20 | nullable: true 21 | }, 22 | up: { 23 | type: 'boolean', 24 | enum: [true], 25 | nullable: true 26 | }, 27 | master: { 28 | type: 'string', 29 | minLength: 1, 30 | nullable: true 31 | }, 32 | type: { 33 | type: 'string', 34 | enum: Object.values(ExtendedLinkTypes) as ExtendedLinkTypes[], 35 | nullable: true 36 | }, 37 | vrf: { 38 | type: 'string', 39 | minLength: 1, 40 | nullable: true 41 | } 42 | } 43 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/bareup.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add link bare UDP type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddLinkBareudpTypeArgs { 6 | /** Specifies the destination port for the UDP tunnel. */ 7 | dstport: number; 8 | /** 9 | * Specifies the `ethertype` of the L3 protocol being tunnelled. 10 | * `ethertype` can be given as plain Ethernet protocol number or using the protocol name 11 | * ("ipv4", "ipv6", "mpls_uc", etc.). 12 | * 13 | * TODO: Add an enum with all known protocols numbers and names? 14 | * @see https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml 15 | */ 16 | ethertype: string | number; 17 | /** Selects the lowest value of the UDP tunnel source port range. */ 18 | srcportmin?: number; 19 | /** 20 | * Activates support for protocols similar to the one specified by {@link ethertype}. 21 | * When {@link ethertype} is "mpls_uc" (that is, unicast MPLS), this allows the tunnel 22 | * to also handle multicast MPLS. 23 | * 24 | * When {@link ethertype} is "ipv4", this allows the tunnel to also handle IPv6. 25 | * This option is disabled by default. 26 | */ 27 | multiproto?: boolean; 28 | /** @see {@link multiproto} */ 29 | nomultiproto?: boolean; 30 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/bareup.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddLinkBareudpTypeArgs } from './bareup.interfaces'; 4 | 5 | export const AddLinkBareudpArgsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: ['dstport', 'ethertype'], 8 | additionalProperties: false, 9 | properties: { 10 | dstport: { 11 | type: 'integer', 12 | minimum: 1, 13 | maximum: 65535 14 | }, 15 | ethertype: { 16 | type: ['string', 'integer'], 17 | oneOf: [ 18 | { 19 | type: 'string' 20 | }, 21 | { 22 | type: 'integer', 23 | minimum: 0, 24 | maximum: 255 25 | } 26 | ] 27 | }, 28 | srcportmin: { 29 | type: 'integer', 30 | nullable: true, 31 | minimum: 1, 32 | maximum: 65535 33 | }, 34 | multiproto: { 35 | type: 'boolean', 36 | nullable: true 37 | }, 38 | nomultiproto: { 39 | type: 'boolean', 40 | nullable: true 41 | } 42 | } 43 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/erspan-ip6erspan.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { ErspanDirections } from '../../link.constants'; 2 | 3 | /** 4 | * Add link erspan & IP6 erspan type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkErspanIp6erspanTypeArgs { 8 | /** Specifies the remote address of the tunnel. */ 9 | remote: string; 10 | /** 11 | * Specifies the fixed local address for tunneled packets. 12 | * It must be an address on another interface on this host. 13 | */ 14 | local: string; 15 | /** 16 | * Enable sequence numbering of ERSPAN packets. 17 | * This can be useful for detecting packet loss. 18 | */ 19 | seq: true; 20 | /** A 32-bit key to identify the GRE tunnel. */ 21 | key: number; 22 | /** 23 | * TODO: Add an enum for validator? 24 | * 25 | * Specifies the ERSPAN version number. 26 | * `version` indicates the ERSPAN version to be created: 27 | * 28 | * 0 for version 0 type I, 29 | * 1 for version 1 (type II) 30 | * or 2 for version 2 (type III). 31 | */ 32 | erspan_ver: number; 33 | /** 34 | * Specifies the ERSPAN v1 index field. 35 | * IDX indicates a 20 bit index/port number associated with the ERSPAN 36 | * traffic's source port and direction. 37 | */ 38 | erspan?: number; 39 | /** Specifies the ERSPAN v2 mirrored traffic's direction. 40 | */ 41 | erspan_dir?: ErspanDirections; 42 | /** 43 | * A unique identifier of an ERSPAN v2 engine within a system. 44 | * `hwid` is a 6-bit value for users to configure. 45 | */ 46 | erspan_hwid?: number; 47 | /** Specifies whether to allow remote endpoint to have an address configured on local host. */ 48 | 'allow-localremote'?: boolean; 49 | /** @see {@link['allow-localremote']} */ 50 | 'noallow-localremote'?: boolean; 51 | /** 52 | * Make this tunnel externally controlled (or not, which is the default). 53 | * 54 | * In the kernel, this is referred to as collect metadata mode. 55 | * This flag is mutually exclusive with the {@link remote}, {@link local}, {@link erspan_ver}, 56 | * {@link erspan}, {@link erspan_dir} and {@link erspan_hwid} options. 57 | */ 58 | external?: true; 59 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/erspan-ip6erspan.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { ErspanDirections } from '../../link.constants'; 4 | import { AddLinkErspanIp6erspanTypeArgs } from './erspan-ip6erspan.interfaces'; 5 | 6 | export const AddLinkErspanIp6ErspanArgsSchema: JSONSchemaType = { 7 | type : 'object', 8 | required : ['remote', 'local', 'seq', 'key', 'erspan_ver'], 9 | additionalProperties: false, 10 | properties : { 11 | remote : { 12 | type : 'string', 13 | format: 'ip' 14 | }, 15 | local : { 16 | type : 'string', 17 | format: 'ip' 18 | }, 19 | seq : { 20 | type: 'boolean', 21 | enum: [true] 22 | }, 23 | key : { 24 | type : 'integer', 25 | minimum: 0, 26 | maximum: 4294967295 27 | }, 28 | erspan_ver : { 29 | type : 'integer', 30 | minimum: 0, 31 | maximum: 2 32 | }, 33 | erspan : { 34 | type : 'integer', 35 | minimum : 0, 36 | maximum : 1048576, 37 | nullable: true 38 | }, 39 | erspan_dir : { 40 | type : 'string', 41 | enum : Object.values(ErspanDirections) as ErspanDirections[], 42 | nullable: true 43 | }, 44 | erspan_hwid : { 45 | type : 'integer', 46 | minimum : 0, 47 | maximum : 63, 48 | nullable: true 49 | }, 50 | 'allow-localremote' : { 51 | type : 'boolean', 52 | nullable: true 53 | }, 54 | 'noallow-localremote': { 55 | type : 'boolean', 56 | nullable: true 57 | }, 58 | external : { 59 | type : 'boolean', 60 | enum : [true], 61 | nullable: true 62 | } 63 | } 64 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/geneve.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { DontFragmentFlagValues } from '../../link.constants'; 2 | 3 | /** 4 | * Add link geneve type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkGeneveTypeArgs { 8 | /** Specifies the Virtual Network Identifier to use. */ 9 | id: number; 10 | /** Specifies the unicast destination IP address to use in outgoing packets. */ 11 | remote: string; 12 | /** 13 | * Specifies the TTL value to use in outgoing packets. 14 | * "0" or "auto" means use whatever default value, "inherit" means inherit 15 | * the inner protocol's ttl. 16 | * 17 | * Default option is "0". 18 | */ 19 | ttl?: number | string; 20 | /** Specifies the TOS value to use in outgoing packets. */ 21 | tos?: number; 22 | /** 23 | * Specifies the usage of the Don't Fragment flag (DF) bit in outgoing packets with IPv4 headers. 24 | * 25 | * The value inherit causes the bit to be copied from the original IP header. 26 | * The values unset and set cause the bit to be always unset or always set, respectively. 27 | * 28 | * By default, the bit is not set. 29 | */ 30 | df?: DontFragmentFlagValues; 31 | /** Specifies the flow label to use in outgoing packets. */ 32 | flowlabel?: number; 33 | /** Select a destination port other than the default of 6081. */ 34 | dstport?: number; 35 | /** 36 | * Make this tunnel externally controlled (or not, which is the default). 37 | * This flag is mutually exclusive with the {@link id}, {@link remote}, {@link ttl}, {@link tos} and 38 | * {@link flowlabel} options. 39 | */ 40 | external?: boolean; 41 | /** @see {@link external} */ 42 | noexternal?: boolean; 43 | /** Specifies if UDP checksum is calculated for transmitted packets over IPv4. */ 44 | udpcsum?: boolean; 45 | /** @see {@link udpcsum} */ 46 | noudpcsum?: boolean; 47 | /** Skip UDP checksum calculation for transmitted packets over IPv6. */ 48 | udp6zerocsumtx?: boolean; 49 | /** @see {@link udp6zerocsumtx} */ 50 | noudp6zerocsumtx?: boolean; 51 | /** Allow incoming UDP packets over IPv6 with zero checksum field. */ 52 | udp6zerocsumrx?: boolean; 53 | /** @see {@link udp6zerocsumrx} */ 54 | noudp6zerocsumrx?: boolean; 55 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/geneve.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { DontFragmentFlagValues, TtlSpecialValues } from '../../link.constants'; 4 | import { AddLinkGeneveTypeArgs } from './geneve.interfaces'; 5 | 6 | export const AddLinkGeneveArgsSchema: JSONSchemaType = { 7 | type : 'object', 8 | required : ['id', 'remote'], 9 | additionalProperties: false, 10 | properties : { 11 | id : { 12 | type : 'integer', 13 | minimum: 0, 14 | maximum: 16777215 15 | }, 16 | remote : { 17 | type : 'string', 18 | format: 'ip' 19 | }, 20 | ttl : { 21 | type : ['string', 'integer'], 22 | nullable: true, 23 | oneOf : [ 24 | { 25 | type : 'string', 26 | enum : Object.values(TtlSpecialValues) as TtlSpecialValues[], 27 | nullable: true 28 | }, 29 | { 30 | type : 'integer', 31 | minimum : 0, 32 | maximum : 255, 33 | nullable: true 34 | } 35 | ] 36 | }, 37 | tos : { 38 | type : 'integer', 39 | nullable: true, 40 | minimum : 0, 41 | maximum : 63 42 | }, 43 | df : { 44 | type : 'string', 45 | enum : Object.values(DontFragmentFlagValues) as DontFragmentFlagValues[], 46 | nullable: true 47 | }, 48 | flowlabel : { 49 | type : 'integer', 50 | minimum : 0, 51 | maximum : 1048575, 52 | nullable: true 53 | }, 54 | dstport : { 55 | type : 'integer', 56 | nullable: true, 57 | minimum : 1, 58 | maximum : 65535 59 | }, 60 | external : { 61 | type : 'boolean', 62 | nullable: true 63 | }, 64 | noexternal : { 65 | type : 'boolean', 66 | nullable: true 67 | }, 68 | udpcsum : { 69 | type : 'boolean', 70 | nullable: true 71 | }, 72 | noudpcsum : { 73 | type : 'boolean', 74 | nullable: true 75 | }, 76 | udp6zerocsumtx : { 77 | type : 'boolean', 78 | nullable: true 79 | }, 80 | noudp6zerocsumtx: { 81 | type : 'boolean', 82 | nullable: true 83 | }, 84 | udp6zerocsumrx : { 85 | type : 'boolean', 86 | nullable: true 87 | }, 88 | noudp6zerocsumrx: { 89 | type : 'boolean', 90 | nullable: true 91 | } 92 | } 93 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/hsr.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { HsrProtocols, HsrVersions } from '../../link.constants'; 2 | 3 | /** 4 | * Add link hsr type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkHsrTypeArgs { 8 | /** Specifies the physical device used for the first of the two ring ports. */ 9 | slave1: string; 10 | /** Specifies the physical device used for the second of the two ring ports. */ 11 | slave2: string; 12 | /** 13 | * The last byte of the multicast address used for HSR supervision frames. 14 | * Default option is "0", possible values 0-255. 15 | */ 16 | supervision?: number; 17 | /** Selects the lowest value of the UDP tunnel source port range. */ 18 | version?: HsrVersions; 19 | /** Selects the lowest value of the UDP tunnel source port range. */ 20 | proto?: HsrProtocols; 21 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/hsr.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { HsrProtocols, HsrVersions } from '../../link.constants'; 4 | import { AddLinkHsrTypeArgs } from './hsr.interfaces'; 5 | 6 | export const AddLinkHsrArgsSchema: JSONSchemaType = { 7 | type : 'object', 8 | required : ['slave1', 'slave2'], 9 | additionalProperties: false, 10 | properties : { 11 | slave1 : { 12 | type : 'string', 13 | minLength: 1 14 | }, 15 | slave2 : { 16 | type : 'string', 17 | minLength: 1 18 | }, 19 | supervision: { 20 | type : 'integer', 21 | minimum : 0, 22 | maximum : 255, 23 | nullable: true 24 | }, 25 | version : { 26 | type : 'integer', 27 | enum : Object.values(HsrVersions) as HsrVersions[], 28 | nullable: true 29 | }, 30 | proto : { 31 | type : 'integer', 32 | enum : Object.values(HsrProtocols) as HsrProtocols[], 33 | nullable: true 34 | } 35 | } 36 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/ipip-sit.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { IpipSipDeviceModes, SecondaryUdpEncapsulations } from '../../link.constants'; 2 | 3 | /** 4 | * Add link IPIP & Sit type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkIpipSitTypeArgs { 8 | /** Specifies the remote address of the tunnel. */ 9 | remote: string; 10 | /** 11 | * Specifies the fixed local address for tunneled packets. 12 | * It must be an address on another interface on this host. 13 | */ 14 | local: string; 15 | /** @see {@link SecondaryUdpEncapsulations} */ 16 | encap?: SecondaryUdpEncapsulations; 17 | /** 18 | * Specifies the source port in UDP encapsulation. 19 | * 20 | * PORT indicates the port by number, "auto" indicates that the port number 21 | * should be chosen automatically (the kernel picks a flow based on the flow 22 | * hash of the encapsulated packet). 23 | */ 24 | 'encap-sport'?: number | 'auto'; 25 | /** TODO: No doc in man. */ 26 | 'encap-dport'?: number ; 27 | /** Specifies if UDP checksums are enabled in the secondary encapsulation. */ 28 | 'encap-csum'?: boolean; 29 | /** @see {@link['encap-csum']} */ 30 | 'noencap-csum'?: boolean; 31 | /** 32 | * Specifies if Remote Checksum Offload is enabled. 33 | * This is only applicable for Generic UDP Encapsulation. 34 | */ 35 | 'encap-remcsum'?: boolean; 36 | /** @see {@link['encap-remcsum']} */ 37 | 'noencap-remcsum'?: boolean; 38 | /** 39 | * Specifies mode in which device should run. 40 | * 41 | * "ip6ip" indicates IPv6-Over-IPv4, 42 | * "ipip" indicates "IPv4-Over-IPv4", 43 | * "mplsip" indicates MPLS-Over-IPv4, 44 | * "any" indicates IPv6, IPv4 or MPLS Over IPv4. 45 | * 46 | * Supported for SIT where the default is "ip6ip" and IPIP where the default is "ipip". 47 | * IPv6-Over-IPv4 is not supported for IPIP. 48 | */ 49 | // TODO: Separate interfaces and validations between IPIP & SIT? They don't support the same types. 50 | mode?: IpipSipDeviceModes; 51 | /** Make this tunnel externally controlled (e.g. ip route encap). */ 52 | external?: true; 53 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/ipip-sit.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { IpipSipDeviceModes, SecondaryUdpEncapsulations } from '../../link.constants'; 4 | import { AddLinkIpipSitTypeArgs } from './ipip-sit.interfaces'; 5 | 6 | export const AddLinkIpipSipArgsSchema: JSONSchemaType = { 7 | type: 'object', 8 | required: [ 'remote', 'local' ], 9 | additionalProperties: false, 10 | properties: { 11 | remote: { 12 | type: 'string', 13 | format: 'ip' 14 | }, 15 | local: { 16 | type: 'string', 17 | format: 'ip' 18 | }, 19 | encap: { 20 | type: 'string', 21 | enum: Object.values(SecondaryUdpEncapsulations) as SecondaryUdpEncapsulations[], 22 | nullable: true 23 | }, 24 | 'encap-sport': { 25 | type: [ 'string', 'integer' ], 26 | nullable: true, 27 | oneOf: [ 28 | { 29 | type: 'string', 30 | enum: [ 'auto' ], 31 | nullable: true 32 | }, 33 | { 34 | type: 'integer', 35 | minimum: 0, 36 | maximum: 65535, 37 | nullable: true 38 | } 39 | ] 40 | }, 41 | 'encap-dport': { 42 | type: 'integer', 43 | nullable: true, 44 | minimum: 0, 45 | maximum: 65535 46 | }, 47 | 'encap-csum': { 48 | type: 'boolean', 49 | nullable: true 50 | }, 51 | 'noencap-csum': { 52 | type: 'boolean', 53 | nullable: true 54 | }, 55 | 'encap-remcsum': { 56 | type: 'boolean', 57 | nullable: true 58 | }, 59 | 'noencap-remcsum': { 60 | type: 'boolean', 61 | nullable: true 62 | }, 63 | mode: { 64 | type: 'string', 65 | enum: Object.values(IpipSipDeviceModes) as IpipSipDeviceModes[], 66 | nullable: true 67 | }, 68 | external: { 69 | type: 'boolean', 70 | enum: [ true ], 71 | nullable: true 72 | } 73 | } 74 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/ipoib.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { IpoIbModes } from '../../link.constants'; 2 | 3 | /** 4 | * Add link IpoIb type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkIpoibTypeArgs { 8 | /** Specifies the IB P-Key to use. */ 9 | pkey?: string; 10 | /** Specifies the mode to use. */ 11 | mode?: IpoIbModes; 12 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/ipoib.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { IpoIbModes } from '../../link.constants'; 4 | import { AddLinkIpoibTypeArgs } from './ipoib.interfaces'; 5 | 6 | export const AddLinkIpoibArgsSchema: JSONSchemaType = { 7 | type : 'object', 8 | required : [], 9 | additionalProperties: false, 10 | properties : { 11 | pkey: { 12 | type : 'string', 13 | format : '4-hex', 14 | nullable: true 15 | }, 16 | mode: { 17 | type : 'string', 18 | enum : Object.values(IpoIbModes) as IpoIbModes[], 19 | nullable: true 20 | } 21 | } 22 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/macsec.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { OnOffToggle } from '../../../common/constants/attribute-values'; 2 | import { MacsecValidationModeOptions } from '../../link.constants'; 3 | 4 | /** 5 | * Add link macsec type arguments. 6 | * @category Interfaces 7 | */ 8 | export interface AddLinkMacsecTypeArgs { 9 | /** Sets the system identifier component of secure channel for this MACsec device. */ 10 | address?: string; 11 | /** 12 | * Sets the port number component of secure channel for this MACsec device, in a range 13 | * from 1 to 65535 inclusive. 14 | * 15 | * Numbers with a leading " 0 " or " 0x " are interpreted as octal and hexadecimal, respectively. 16 | */ 17 | port?: number; 18 | /** 19 | * Sets the secure channel identifier for this MACsec device. 20 | * SCI is a 64bit wide number in hexadecimal format. 21 | */ 22 | sci?: string; 23 | /** Defines the cipher suite to use. */ 24 | cipher?: string; 25 | /** Sets the length of the Integrity Check Value (ICV). */ 26 | icvlen?: number; 27 | /** Switches between authenticated encryption, or authenticity mode only. */ 28 | encrypt?: OnOffToggle; 29 | /** Specifies whether the SCI is included in every packet, or only when it is necessary. */ 30 | send_sci?: OnOffToggle; 31 | /** Sets the End Station bit. */ 32 | end_station?: OnOffToggle; 33 | /** Sets the Single Copy Broadcast bit. */ 34 | scb?: OnOffToggle; 35 | /** Enables MACsec protection on the device. */ 36 | protect?: OnOffToggle; 37 | /** Enables replay protection on the device. */ 38 | replay?: OnOffToggle; 39 | /** Sets the size of the replay window. */ 40 | window?: number; 41 | /** Sets the validation mode on the device. */ 42 | validate?: MacsecValidationModeOptions; 43 | /** Sets the active secure association for transmission. */ 44 | encodingsa?: number; 45 | } 46 | -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/macsec.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { OnOffToggle } from '../../../common/constants/attribute-values'; 3 | 4 | import { 5 | MacsecValidationModeOptions, 6 | SecureAssociationEncodings 7 | } from '../../link.constants'; 8 | 9 | import { AddLinkMacsecTypeArgs } from './macsec.interfaces'; 10 | 11 | export const AddLinkMacsecArgsSchema: JSONSchemaType = { 12 | type: 'object', 13 | required: [], 14 | additionalProperties: false, 15 | properties: { 16 | address: { 17 | type: 'string', 18 | format: 'mac', 19 | nullable: true 20 | }, 21 | port: { 22 | type: 'integer', 23 | minimum: 1, 24 | maximum: 65535, 25 | nullable: true 26 | }, 27 | sci: { 28 | type: 'string', 29 | pattern: '^[0-9a-fA-F]{16}$', 30 | nullable: true 31 | }, 32 | cipher: { 33 | type: 'string', 34 | minLength: 1, 35 | nullable: true 36 | }, 37 | icvlen: { 38 | type: 'integer', 39 | minimum: 1, 40 | maximum: 16, 41 | nullable: true 42 | }, 43 | encrypt: { 44 | type: 'string', 45 | enum: Object.values(OnOffToggle) as OnOffToggle[], 46 | nullable: true 47 | }, 48 | send_sci: { 49 | type: 'string', 50 | enum: Object.values(OnOffToggle) as OnOffToggle[], 51 | nullable: true 52 | }, 53 | end_station: { 54 | type: 'string', 55 | enum: Object.values(OnOffToggle) as OnOffToggle[], 56 | nullable: true 57 | }, 58 | scb: { 59 | type: 'string', 60 | enum: Object.values(OnOffToggle) as OnOffToggle[], 61 | nullable: true 62 | }, 63 | protect: { 64 | type: 'string', 65 | enum: Object.values(OnOffToggle) as OnOffToggle[], 66 | nullable: true 67 | }, 68 | replay: { 69 | type: 'string', 70 | enum: Object.values(OnOffToggle) as OnOffToggle[], 71 | nullable: true 72 | }, 73 | window: { 74 | type: 'integer', 75 | minimum: 0, 76 | // 2^32-1 77 | maximum: 4294967295, 78 | nullable: true 79 | }, 80 | validate: { 81 | type: 'string', 82 | enum: Object.values(MacsecValidationModeOptions) as MacsecValidationModeOptions[], 83 | nullable: true 84 | }, 85 | encodingsa: { 86 | type: 'integer', 87 | enum: Object.values(SecureAssociationEncodings) as SecureAssociationEncodings[], 88 | nullable: true 89 | } 90 | } 91 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/macvlan-macvtap.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { MacvlanMacvtapModes } from '../../link.constants'; 2 | 3 | /** 4 | * Add link macvlan & macvtap type arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddLinkMacvlanMacvtapTypeArgs { 8 | /** 9 | * Specifies the mode. 10 | * 11 | * @see {@link MacvlanMacvtapModes} 12 | */ 13 | mode: MacvlanMacvtapModes; 14 | /** 15 | * Set the length of the RX queue used to process broadcast and multicast packets. 16 | * 17 | * LENGTH must be a positive integer in the range [0-4294967295]. 18 | * Setting a length of 0 will effectively drop all broadcast/multicast traffic. 19 | * If not specified the macvlan driver default (1000) is used. 20 | * 21 | * Note that all macvlans that share the same underlying device are using the same queue. 22 | * The parameter here is a request, the actual queue length used will be the maximum length 23 | * that any macvlan interface has requested. 24 | * 25 | * When listing device parameters both the bcqueuelen parameter as well as the actual used bcqueuelen 26 | * are listed to better help the user understand the setting. 27 | */ 28 | bcqueuelen?: number; 29 | } 30 | 31 | /** 32 | * Set link macvlan & macvtap type arguments. 33 | * @category Interfaces 34 | */ 35 | export interface SetLinkMacvlanMacvtapTypeArgs { 36 | /** Modify list of allowed {@link macaddr} for link in source mode. */ 37 | macaddr?: true; 38 | /** Add MACADDR to allowed list. */ 39 | add?: string; 40 | /** Replace allowed list. */ 41 | set?: string; 42 | /** Remove MACADDR from allowed list. */ 43 | del?: string; 44 | /** Flush whole allowed list. */ 45 | flush?: true; 46 | /** 47 | * Set the length of the RX queue used to process broadcast and multicast packets. 48 | * LENGTH must be a positive integer in the range [0-4294967295]. 49 | * 50 | * Setting a length of 0 will effectively drop all broadcast/multicast traffic. 51 | * If not specified the macvlan driver default (1000) is used. 52 | * 53 | * Note that all macvlans that share the same un‐derlying device are using the same queue. 54 | * The parameter here is a request, the actual queue length used will be the maximum length 55 | * that any macvlan interface has requested. 56 | * 57 | * When listing device parameters both the {@link bcqueuelen} parameter as well as the actual used 58 | * {@link bcqueuelen} are listed to better help the user understand the setting. 59 | */ 60 | bcqueuelen?: number; 61 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/macvlan-macvtap.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { MacvlanMacvtapModes } from '../../link.constants'; 4 | 5 | import { 6 | AddLinkMacvlanMacvtapTypeArgs, 7 | SetLinkMacvlanMacvtapTypeArgs 8 | } from './macvlan-macvtap.interfaces'; 9 | 10 | export const AddLinkMacvlanMacvtapArgsSchema: JSONSchemaType = { 11 | type : 'object', 12 | required : ['mode'], 13 | additionalProperties: false, 14 | properties : { 15 | mode : { 16 | type: 'string', 17 | enum: Object.values(MacvlanMacvtapModes) as MacvlanMacvtapModes[] 18 | }, 19 | bcqueuelen: { 20 | type : 'integer', 21 | nullable: true, 22 | minimum : 1, 23 | maximum : 4294967295 24 | } 25 | } 26 | }; 27 | 28 | export const SetLinkMacvlanMacvtapArgsSchema: JSONSchemaType = { 29 | type : 'object', 30 | required : [], 31 | additionalProperties: false, 32 | properties : { 33 | macaddr : { 34 | type : 'boolean', 35 | enum : [true], 36 | nullable: true 37 | }, 38 | add : { 39 | type : 'string', 40 | format : 'mac', 41 | nullable: true 42 | }, 43 | set : { 44 | type : 'string', 45 | format : 'mac', 46 | nullable: true 47 | }, 48 | del : { 49 | type : 'string', 50 | format : 'mac', 51 | nullable: true 52 | }, 53 | flush : { 54 | type : 'boolean', 55 | enum : [true], 56 | nullable: true 57 | }, 58 | bcqueuelen: { 59 | type : 'integer', 60 | nullable: true, 61 | minimum : 1, 62 | maximum : 4294967295 63 | } 64 | } 65 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/rmnet.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add link rmnet type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddLinkRmnetTypeArgs { 6 | /** Specifies the mux identifier for the rmnet device, possible values 1-254. */ 7 | mux_id: number; 8 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/rmnet.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddLinkRmnetTypeArgs } from './rmnet.interfaces'; 4 | 5 | export const AddLinkRmnetArgsSchema: JSONSchemaType = { 6 | type : 'object', 7 | required : ['mux_id'], 8 | additionalProperties: false, 9 | properties : { 10 | mux_id: { 11 | type : 'integer', 12 | minimum: 1, 13 | maximum: 254 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/veth-vxcan.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add link veth & vxcan type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddLinkVethVxcanTypeArgs { 6 | /** Specifies the virtual pair device name of the VETH/VXCAN tunnel. */ 7 | 'peer name'?: string; 8 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/veth-vxcan.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddLinkVethVxcanTypeArgs } from './veth-vxcan.interfaces'; 4 | 5 | export const AddLinkVethVxcanArgsSchema: JSONSchemaType = { 6 | type : 'object', 7 | required : [], 8 | additionalProperties: false, 9 | properties : { 10 | 'peer name': { 11 | type : 'string', 12 | minLength: 1, 13 | nullable : true 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/vlan.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { OnOffToggle } from '../../../common/constants/attribute-values'; 2 | import { VlanProtocols } from '../../link.constants'; 3 | 4 | /** 5 | * Add link vlan type arguments. 6 | * @category Interfaces 7 | */ 8 | export interface AddLinkVlanTypeArgs { 9 | /** VLAN Protocol. */ 10 | protocol: VlanProtocols; 11 | /** 12 | * Specifies the VLAN Identifier to use. 13 | * Note that numbers with a leading " 0 " or " 0x " are interpreted as octal 14 | * or hexadecimal, respectively. 15 | */ 16 | id: number; 17 | /** Specifies whether ethernet headers are reordered or not (default is on). */ 18 | reorder_hdr?: OnOffToggle; 19 | /** Specifies whether this VLAN should be registered using GARP VLAN Registration Protocol. */ 20 | gvrp?: OnOffToggle; 21 | /** Specifies whether this VLAN should be registered using Multiple VLAN Registration Protocol. */ 22 | mvrp?: OnOffToggle; 23 | /** Specifies whether the VLAN device state is bound to the physical device state. */ 24 | loose_binding?: OnOffToggle; 25 | /** Specifies whether the VLAN device link state tracks the state of bridge ports that are members of the VLAN. */ 26 | bridge_binding?: OnOffToggle; 27 | /** 28 | * Defines a mapping of VLAN header prio field to the Linux internal packet priority on incoming frames. 29 | * The format is FROM:TO with multiple mappings separated by spaces. 30 | */ 31 | 'ingress-qos-map'?: string[]; 32 | /** 33 | * Defines a mapping of Linux internal packet priority to VLAN header prio field but for outgoing frames. 34 | * The format is the same as for {@link ingress-qos-map}. 35 | */ 36 | 'egress-qos-map'?: string[]; 37 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/vlan.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { OnOffToggle } from '../../../common/constants/attribute-values'; 4 | import { VlanProtocols } from '../../link.constants'; 5 | 6 | import { 7 | AddLinkVlanTypeArgs 8 | } from './vlan.interfaces'; 9 | 10 | export const AddLinkVlanArgsSchema: JSONSchemaType = { 11 | type: 'object', 12 | required: [ 'protocol', 'id' ], 13 | additionalProperties: false, 14 | properties: { 15 | protocol: { 16 | type: 'string', 17 | enum: Object.values(VlanProtocols) as VlanProtocols[] 18 | }, 19 | id: { 20 | type: 'integer', 21 | minimum: 0, 22 | maximum: 4095 23 | }, 24 | reorder_hdr: { 25 | type: 'string', 26 | enum: Object.values(OnOffToggle) as OnOffToggle[], 27 | nullable: true 28 | }, 29 | gvrp: { 30 | type: 'string', 31 | enum: Object.values(OnOffToggle) as OnOffToggle[], 32 | nullable: true 33 | }, 34 | mvrp: { 35 | type: 'string', 36 | enum: Object.values(OnOffToggle) as OnOffToggle[], 37 | nullable: true 38 | }, 39 | loose_binding: { 40 | type: 'string', 41 | enum: Object.values(OnOffToggle) as OnOffToggle[], 42 | nullable: true 43 | }, 44 | bridge_binding: { 45 | type: 'string', 46 | enum: Object.values(OnOffToggle) as OnOffToggle[], 47 | nullable: true 48 | }, 49 | 'ingress-qos-map': { 50 | type: 'array', 51 | minItems: 1, 52 | nullable: true, 53 | items: { 54 | type: 'string', 55 | format: 'colon-separated-numbers' 56 | } 57 | }, 58 | 'egress-qos-map': { 59 | type: 'array', 60 | minItems: 1, 61 | nullable: true, 62 | items: { 63 | type: 'string', 64 | format: 'colon-separated-numbers' 65 | } 66 | } 67 | } 68 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/vrf.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add link vrf type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddLinkVrfTypeArgs { 6 | /** Table id associated with VRF device. */ 7 | table: number; 8 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/vrf.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddLinkVrfTypeArgs } from './vrf.interfaces'; 4 | 5 | export const AddLinkVrfArgsSchema: JSONSchemaType = { 6 | type : 'object', 7 | required : ['table'], 8 | additionalProperties: false, 9 | properties : { 10 | table: { 11 | type : 'integer', 12 | minimum: 1, 13 | maximum: 4294967295 14 | } 15 | } 16 | }; -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/xfrm.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add link xfrm type arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddLinkXfrmTypeArgs { 6 | /** Specifies the underlying physical interface from which transform traffic is sent and received. */ 7 | dev: string; 8 | /** 9 | * Specifies the hexadecimal lookup key used to send traffic to and from specific xfrm policies. 10 | * 11 | * Policies must be configured with the same key. 12 | * If not set, the key defaults to 0 and will match any policies which similarly do not have a 13 | * lookup key configuration. 14 | */ 15 | if_id?: number; 16 | } -------------------------------------------------------------------------------- /src/commands/link/virtual-link-types/xfrm.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddLinkXfrmTypeArgs } from './xfrm.interfaces'; 4 | 5 | export const AddLinkXfrmArgsSchema: JSONSchemaType = { 6 | type : 'object', 7 | required : ['dev'], 8 | additionalProperties: false, 9 | properties : { 10 | dev : { 11 | type : 'string', 12 | minLength: 1 13 | }, 14 | if_id: { 15 | type : 'integer', 16 | minimum : 1, 17 | maximum : 4294967295, 18 | nullable: true 19 | } 20 | } 21 | }; -------------------------------------------------------------------------------- /src/commands/link/xdp-options/object.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Link set xdp object options. 3 | * @category Interfaces 4 | */ 5 | export interface LinkSetXdpObjectOptions { 6 | /** 7 | * Attaches a XDP/BPF program to the given device. 8 | * 9 | * The FILE points to a BPF ELF file (f.e. generated by LLVM) that contains the BPF program code, map specifications, 10 | * etc. If a XDP/BPF program is already attached to the given device, an error will be thrown. 11 | * 12 | * If no XDP/BPF program is currently attached, the device supports XDP and the program from the BPF ELF file passes 13 | * the kernel verifier, then it will be attached to the device. 14 | * 15 | * If the option -force is passed to `ip` then any prior attached XDP/BPF program will be atomically overridden 16 | * and no error will be thrown in this case. 17 | * 18 | * If no section option is passed, then the default section name ("prog") will be assumed, otherwise the provided 19 | * section name will be used. 20 | * 21 | * If no verbose option is passed, then a verifier log will only be dumped on load error. 22 | * See also EXAMPLES section for usage examples. 23 | */ 24 | file: string; 25 | /** 26 | * Specifies a section name that contains the BPF program code. 27 | * If no section name is specified, the default one ("prog") will be used. 28 | * This option is to be passed with the object option. 29 | */ 30 | section?: string; 31 | /** 32 | * Act in verbose mode. For example, even in case of success, this will print the verifier log in case a program was 33 | * loaded from a BPF ELF file. 34 | */ 35 | verbose?: true; 36 | } -------------------------------------------------------------------------------- /src/commands/link/xdp-options/object.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { LinkSetXdpObjectOptions } from './object.interfaces'; 4 | 5 | export const LinkSetXdpObjectOptionsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: ['file'], 8 | properties: { 9 | file: { 10 | type: 'string', 11 | minLength: 1, 12 | keyless: true 13 | }, 14 | section: { 15 | type: 'string', 16 | minLength: 1, 17 | nullable: true 18 | }, 19 | verbose: { 20 | type: 'boolean', 21 | enum: [true], 22 | nullable: true 23 | } 24 | } 25 | }; -------------------------------------------------------------------------------- /src/commands/link/xdp-options/off.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Link set xdp off options. 3 | * @category Interfaces 4 | */ 5 | export interface LinkSetXdpOffOptions { 6 | /** `off` detaches any currently attached XDP/BPF program from the given device. */ 7 | value: true; 8 | } -------------------------------------------------------------------------------- /src/commands/link/xdp-options/off.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { LinkSetXdpOffOptions } from './off.interfaces'; 4 | 5 | export const LinkSetXdpOffOptionsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: ['value'], 8 | properties: { 9 | value: { 10 | type: 'boolean', 11 | enum: [true], 12 | keyless: true 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /src/commands/link/xdp-options/pinned.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Link set xdp pinned options. 3 | * @category Interfaces 4 | */ 5 | export interface LinkSetXdpPinnedOptions { 6 | /** 7 | * Attaches a XDP/BPF program to the given device. 8 | * The FILE points to an already pinned BPF program in the BPF file system. 9 | * The option section doesn't apply here, but otherwise semantics are the same as with the option object described 10 | * already. 11 | */ 12 | file: string; 13 | } -------------------------------------------------------------------------------- /src/commands/link/xdp-options/pinned.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { LinkSetXdpPinnedOptions } from './pinned.interfaces'; 4 | 5 | export const LinkSetXdpPinnedOptionsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: ['file'], 8 | properties: { 9 | file: { 10 | type: 'string', 11 | minLength: 1, 12 | keyless: true 13 | } 14 | } 15 | }; -------------------------------------------------------------------------------- /src/commands/maddress/add.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Maddress add options. 3 | * @category Interfaces 4 | */ 5 | export interface MaddressAddOptions { 6 | /** The link-layer multicast address. */ 7 | address: string; 8 | /** The device to join/leave this multicast address. */ 9 | dev: string; 10 | } -------------------------------------------------------------------------------- /src/commands/maddress/add.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { MaddressAddOptions } from './add.interfaces'; 5 | 6 | export const MaddressAddSchema: JSONSchemaType = { 7 | $id: SchemaIds.MaddressAdd, 8 | type: 'object', 9 | required: ['address', 'dev'], 10 | properties: { 11 | address: { 12 | type: 'string', 13 | minLength: 1, 14 | format: 'mac', 15 | keyless: true 16 | }, 17 | dev: { 18 | type: 'string', 19 | minLength: 1 20 | } 21 | } 22 | }; -------------------------------------------------------------------------------- /src/commands/maddress/show.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { AddressFamilies } from '../address.constants'; 2 | 3 | /** 4 | * Maddress show options. 5 | * @category Interfaces 6 | */ 7 | export interface MaddressShowOptions { 8 | /** The device to join/leave this multicast address. */ 9 | dev?: string; 10 | } 11 | 12 | /** 13 | * Maddress Info. 14 | * TODO: Need help to build this undocumented & comprehensive interface. 15 | * 16 | * @category Interfaces 17 | */ 18 | export interface MaddressInfo { 19 | ifindex: number; 20 | ifname: string; 21 | maddr: Array<{ 22 | family?: AddressFamilies; 23 | address?: string; 24 | link?: string; 25 | users?: number; 26 | }>; 27 | } -------------------------------------------------------------------------------- /src/commands/maddress/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { MaddressShowOptions } from './show.interfaces'; 5 | 6 | export const MaddressShowSchema: JSONSchemaType = { 7 | $id : SchemaIds.MaddressShow, 8 | type : 'object', 9 | required : [], 10 | properties: { 11 | dev: { 12 | type : 'string', 13 | minLength: 1, 14 | nullable : true 15 | } 16 | } 17 | }; -------------------------------------------------------------------------------- /src/commands/monitor.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Monitor objects. 3 | * @category Constants 4 | */ 5 | export enum MonitorObjects { 6 | All = 'all', 7 | Link = 'link', 8 | Address = 'address', 9 | Route = 'route', 10 | Mroute = 'mroute', 11 | Prefix = 'prefix', 12 | Neigh = 'neigh', 13 | Netconf = 'netconf', 14 | Rule = 'rule', 15 | Nsid = 'nsid', 16 | Nexthop = 'nexthop' 17 | } -------------------------------------------------------------------------------- /src/commands/monitor.ts: -------------------------------------------------------------------------------- 1 | import MonitorCommand from '../common/classes/monitor-command'; 2 | import { SchemaIds } from '../common/constants/schemas'; 3 | import { GlobalOptions } from '../common/interfaces/common'; 4 | import { MonitorOptions } from './monitor/monitor.interfaces'; 5 | import { MonitorSchema } from './monitor/monitor.schema'; 6 | 7 | /** 8 | * State monitoring. 9 | * 10 | * @param options - Parameters options to be passed down to `ip`. 11 | * @param globalOptions - Global parameters options that affects the command execution. 12 | * 13 | * @throws {@link ParametersError} - Throws when passed parameters are invalid. 14 | * @throws {@link CommandError} - Throws when the executed command fails. 15 | * 16 | * @example 17 | * 18 | * Import module 19 | * ``` 20 | * import { monitor } from 'iproute'; 21 | * ``` 22 | * 23 | * Monitor all objects state changes 24 | * ``` 25 | * monitor({ 26 | * object: MonitorObjects.All 27 | * }); 28 | * ``` 29 | * 30 | * After starting the monitor, you can start watching for changes 31 | * ``` 32 | * let command: MonitorCommand; 33 | * 34 | * monitor({ 35 | * object: MonitorObjects.All 36 | * }) 37 | * .then((_command) => { 38 | * command = _command; 39 | * 40 | * command.on(MonitorObjects.All, (data: MonitorEmittedData) => { 41 | * // Do something with `data`. 42 | * }); 43 | * 44 | * command.on('error', (error) => { 45 | * // Do something with `data`. 46 | * }); 47 | * }); 48 | * 49 | * setTimeout(() => { 50 | * command.close(); 51 | * }, 5000); 52 | * ``` 53 | */ 54 | export async function monitor(options: MonitorOptions, 55 | globalOptions: GlobalOptions = {}): Promise> { 56 | 57 | const cmd = ['ip', 'monitor']; 58 | 59 | const ipCmd = new MonitorCommand( 60 | SchemaIds.Monitor, 61 | MonitorSchema, 62 | options, 63 | { 64 | ...globalOptions, 65 | '-tshort' : true, 66 | '-oneline': true 67 | }, 68 | cmd); 69 | 70 | return await ipCmd.exec(); 71 | } 72 | 73 | export default monitor; -------------------------------------------------------------------------------- /src/commands/monitor/monitor.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { MonitorObjects } from '../monitor.constants'; 2 | 3 | /** 4 | * Monitor options. 5 | * @category Interfaces 6 | */ 7 | export interface MonitorOptions { 8 | /** Object type to monitor. */ 9 | object: MonitorObjects; 10 | /** 11 | * If set, a prefix is displayed before each message to show the family of the message. 12 | * For `monitor`, is always enforced internally for consistency. 13 | */ 14 | label?: true; 15 | /** 16 | * If set, the program listens to all network namespaces that have a `nsid` assigned into the network namespace 17 | * where the program is running. 18 | * 19 | * A prefix is displayed to show the network namespace where the message originates. 20 | * For `monitor`, is always enforced internally for consistency. 21 | */ 22 | 'all-nsid'?: true; 23 | /** Prints only events related to this device. */ 24 | dev?: string; 25 | } -------------------------------------------------------------------------------- /src/commands/monitor/monitor.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { MonitorOptions } from './monitor.interfaces'; 4 | import { SchemaIds } from '../../common/constants/schemas'; 5 | import { MonitorObjects } from '../monitor.constants'; 6 | 7 | export const MonitorSchema: JSONSchemaType = { 8 | $id: SchemaIds.Monitor, 9 | type: 'object', 10 | required: ['object'], 11 | properties: { 12 | object: { 13 | type: 'string', 14 | enum: Object.values(MonitorObjects) as MonitorObjects[], 15 | keyless: true 16 | }, 17 | label: { 18 | type: 'boolean', 19 | enum: [true], 20 | nullable: true 21 | }, 22 | 'all-nsid': { 23 | type: 'boolean', 24 | enum: [true], 25 | nullable: true 26 | }, 27 | dev: { 28 | type: 'string', 29 | minLength: 1, 30 | nullable: true 31 | } 32 | } 33 | }; -------------------------------------------------------------------------------- /src/commands/mroute.ts: -------------------------------------------------------------------------------- 1 | import CommandWithReturnedData from '../common/classes/command-with-returned-data'; 2 | import Command from '../common/classes/command'; 3 | import { SchemaIds } from '../common/constants/schemas'; 4 | import { GlobalOptions } from '../common/interfaces/common'; 5 | import { MrouteInfo, MrouteShowOptions } from './mroute/show.interfaces'; 6 | import { MrouteShowSchema } from './mroute/show.schema'; 7 | 8 | /** 9 | * List multicast routing cache entries. 10 | * 11 | * @param options - Parameters options to be passed down to `ip`. 12 | * @param globalOptions - Global parameters options that affects the command execution. 13 | * 14 | * @throws {@link ParametersError} - Throws when passed parameters are invalid. 15 | * @throws {@link CommandError} - Throws when the executed command fails. 16 | * 17 | * @example 18 | * 19 | * Import module 20 | * ``` 21 | * import { mroute } from 'iproute'; 22 | * ``` 23 | * 24 | * Show multicast routes 25 | * ``` 26 | * const entries = await mroute.show({}); 27 | * ``` 28 | */ 29 | export async function show(options: MrouteShowOptions, 30 | globalOptions: GlobalOptions = {}): Promise | MrouteInfo[]> { 31 | 32 | const cmd = ['ip', 'mroute', 'show']; 33 | 34 | const ipCmd = new CommandWithReturnedData( 35 | SchemaIds.MrouteShow, 36 | MrouteShowSchema, 37 | options, 38 | { 39 | ...globalOptions, 40 | // Overrides for a better show. 41 | '-details' : true, 42 | '-statistics': true, 43 | '-json' : true 44 | }, 45 | cmd); 46 | 47 | return await ipCmd.exec(); 48 | } 49 | 50 | export default { 51 | show 52 | }; -------------------------------------------------------------------------------- /src/commands/mroute/show.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { RouteRoutingTables } from '../route/show.constants'; 2 | 3 | /** 4 | * Mroute show options. 5 | * @category Interfaces 6 | */ 7 | export interface MrouteShowOptions { 8 | /** The prefix selecting the destination multicast addresses to list. */ 9 | to?: string; 10 | /** The prefix selecting the IP source addresses of the multicast route. */ 11 | from?: string; 12 | /** The interface on which multicast packets are received. */ 13 | iif?: string; 14 | /** 15 | * The table id selecting the multicast table. 16 | * It can be `local`, `main`, `default`, `all` or a number. 17 | */ 18 | table?: number | RouteRoutingTables; 19 | } 20 | 21 | /** 22 | * Mroute Info. 23 | * TODO: Need help to build this undocumented & comprehensive interface. 24 | * 25 | * @category Interfaces 26 | */ 27 | export interface MrouteInfo { 28 | } -------------------------------------------------------------------------------- /src/commands/mroute/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { MrouteShowOptions } from './show.interfaces'; 5 | import { RouteRoutingTables } from '../route/show.constants'; 6 | 7 | export const MrouteShowSchema: JSONSchemaType = { 8 | $id : SchemaIds.MrouteShow, 9 | type : 'object', 10 | required : [], 11 | properties: { 12 | to : { 13 | type : 'string', 14 | format : 'ip-with-required-mask', 15 | nullable: true 16 | }, 17 | from : { 18 | type : 'string', 19 | format : 'ip-with-required-mask', 20 | nullable: true 21 | }, 22 | iif : { 23 | type : 'string', 24 | minLength: 1, 25 | nullable : true 26 | }, 27 | table: { 28 | type : ['string', 'integer'], 29 | nullable: true, 30 | oneOf : [ 31 | { 32 | type : 'string', 33 | enum : Object.values(RouteRoutingTables) as RouteRoutingTables[], 34 | nullable: true 35 | }, 36 | { 37 | type : 'integer', 38 | minimum : 0, 39 | nullable: true 40 | } 41 | ] 42 | } 43 | } 44 | }; -------------------------------------------------------------------------------- /src/commands/neighbour.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Neighbour Unreachability Detection (NUD) states. 3 | * @category Constants 4 | */ 5 | export enum NudStates { 6 | /** The neighbour entry is valid forever and can be only be removed administratively. */ 7 | Permanent = 'permanent', 8 | /** 9 | * The neighbour entry is valid. 10 | * No attempts to validate this entry will be made but it can be removed when its lifetime expires. 11 | */ 12 | Noarp = 'noarp', 13 | /** The neighbour entry is valid until the reachability timeout expires. */ 14 | Reachable = 'reachable', 15 | /** 16 | * The neighbour entry is valid but suspicious. 17 | * This option to `ip neigh` does not change the neighbour state if it was valid and the address 18 | * is not changed by this command. 19 | */ 20 | Stale = 'stale', 21 | /** 22 | * This is a pseudo state used when initially creating a neighbour entry or after trying to 23 | * remove it before it becomes free to do so. 24 | */ 25 | None = 'none', 26 | /** The neighbour entry has not (yet) been validated/resolved. */ 27 | Incomplete = 'incomplete', 28 | /** Neighbor entry validation is currently delayed. */ 29 | Delay = 'delay', 30 | /** Neighbor is being probed. */ 31 | Probe = 'probe', 32 | /** Max number of probes exceeded without success, neighbor validation has ultimately failed. */ 33 | Failed = 'failed' 34 | } -------------------------------------------------------------------------------- /src/commands/neighbour/add.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { NudStates } from '../neighbour.constants'; 2 | 3 | /** 4 | * Neighbour add options. 5 | * @category Interfaces 6 | */ 7 | export interface NeighbourAddOptions { 8 | /** 9 | * The protocol address of the neighbour. 10 | * It is either an IPv4 or IPv6 address. 11 | */ 12 | to: string; 13 | /** 14 | * The link layer address of the neighbour. 15 | * LLADDRESS can also be null. 16 | */ 17 | lladdr?: string; 18 | /** 19 | * The state of the neighbour entry. 20 | * `nud` is an abbreviation for 'Neighbour Unreachability Detection'. 21 | */ 22 | nud?: NudStates; 23 | /** Indicates whether we are proxying for this neighbour entry. */ 24 | proxy?: true; 25 | /** The interface to which this neighbour is attached. */ 26 | dev?: string; 27 | /** Indicates whether neighbour is a router. */ 28 | router?: true; 29 | /** 30 | * This neigh entry was learned externally. 31 | * This option can be used to indicate to the kernel that this is a controller learnt dynamic entry. 32 | * Kernel will not gc such an entry. 33 | */ 34 | extern_learn?: true; 35 | } -------------------------------------------------------------------------------- /src/commands/neighbour/add.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NeighbourAddOptions } from './add.interfaces'; 5 | import { NudStates } from '../neighbour.constants'; 6 | 7 | export const NeighbourAddSchema: JSONSchemaType = { 8 | $id : SchemaIds.NeighbourAdd, 9 | type : 'object', 10 | required : ['to'], 11 | properties: { 12 | to : { 13 | type : 'string', 14 | minLength: 1, 15 | format : 'ip' 16 | }, 17 | lladdr : { 18 | type : 'string', 19 | minLength: 1, 20 | format : 'mac', 21 | nullable : true 22 | }, 23 | nud : { 24 | type : 'string', 25 | enum : Object.values(NudStates) as NudStates[], 26 | nullable: true 27 | }, 28 | proxy : { 29 | type : 'boolean', 30 | enum : [true], 31 | nullable: true 32 | }, 33 | dev : { 34 | type : 'string', 35 | minLength: 1, 36 | nullable : true 37 | }, 38 | router : { 39 | type : 'boolean', 40 | enum : [true], 41 | nullable: true 42 | }, 43 | extern_learn: { 44 | type : 'boolean', 45 | enum : [true], 46 | nullable: true 47 | } 48 | } 49 | }; -------------------------------------------------------------------------------- /src/commands/neighbour/del.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Neighbour del options. 3 | * @category Interfaces 4 | */ 5 | export interface NeighbourDelOptions { 6 | /** 7 | * The protocol address of the neighbour. 8 | * It is either an IPv4 or IPv6 address. 9 | */ 10 | to: string; 11 | /** Indicates whether we are proxying for this neighbour entry. */ 12 | proxy?: true; 13 | /** The interface to which this neighbour is attached. */ 14 | dev?: string; 15 | /** Indicates whether neighbour is a router. */ 16 | router?: true; 17 | /** 18 | * This neigh entry was learned externally. 19 | * This option can be used to indicate to the kernel that this is a controller learnt dynamic entry. 20 | * Kernel will not gc such an entry. 21 | */ 22 | extern_learn?: true; 23 | } -------------------------------------------------------------------------------- /src/commands/neighbour/del.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NeighbourDelOptions } from './del.interfaces'; 5 | 6 | export const NeighbourDelSchema: JSONSchemaType = { 7 | $id : SchemaIds.NeighbourDel, 8 | type : 'object', 9 | required : ['to'], 10 | properties: { 11 | to : { 12 | type : 'string', 13 | minLength: 1, 14 | format : 'ip' 15 | }, 16 | proxy : { 17 | type : 'boolean', 18 | enum : [true], 19 | nullable: true 20 | }, 21 | dev : { 22 | type : 'string', 23 | minLength: 1, 24 | nullable : true 25 | }, 26 | router : { 27 | type : 'boolean', 28 | enum : [true], 29 | nullable: true 30 | }, 31 | extern_learn: { 32 | type : 'boolean', 33 | enum : [true], 34 | nullable: true 35 | } 36 | } 37 | }; -------------------------------------------------------------------------------- /src/commands/neighbour/get.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Neighbour get options. 3 | * @category Interfaces 4 | */ 5 | export interface NeighbourGetOptions { 6 | /** Gets the proxy requests too. */ 7 | proxy?: true; 8 | /** The prefix selecting the neighbours to list. */ 9 | to: string; 10 | /** Only list the neighbours attached to this device. */ 11 | dev: string; 12 | } -------------------------------------------------------------------------------- /src/commands/neighbour/get.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NeighbourGetOptions } from './get.interfaces'; 5 | 6 | export const NeighbourGetSchema: JSONSchemaType = { 7 | $id: SchemaIds.RouteGet, 8 | type: 'object', 9 | required: ['to', 'dev'], 10 | properties: { 11 | proxy: { 12 | type: 'boolean', 13 | enum: [true], 14 | nullable: true 15 | }, 16 | to: { 17 | type: 'string', 18 | minLength: 1, 19 | format: 'ip' 20 | }, 21 | dev: { 22 | type: 'string', 23 | minLength: 1 24 | } 25 | } 26 | }; -------------------------------------------------------------------------------- /src/commands/neighbour/show.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { NudStates } from '../neighbour.constants'; 2 | 3 | /** 4 | * Neighbour show options. 5 | * @category Interfaces 6 | */ 7 | export interface NeighbourShowOptions { 8 | /** List neighbour proxies. */ 9 | proxy?: true; 10 | /** The prefix selecting the neighbours to list. */ 11 | to?: string; 12 | /** Only list the neighbours attached to this device. */ 13 | dev?: string; 14 | /** 15 | * Only list neighbour entries in this state. 16 | * If this option is absent, `ip` lists all entries except for {@link NudStates.None} and {@link NudStates.Noarp}. 17 | */ 18 | nud?: NudStates; 19 | /** Only list the neighbours for given VRF. */ 20 | vrf?: string; 21 | } 22 | 23 | /** 24 | * Neighbour Info. 25 | * TODO: Need help to build this undocumented & comprehensive interface. 26 | * 27 | * @category Interfaces 28 | */ 29 | export interface NeighbourInfo { 30 | dst: string; 31 | dev: string; 32 | lladdr: string; 33 | state: string[]; 34 | refcnt?: number; 35 | used?: number; 36 | confirmed?: number; 37 | updated?: number; 38 | probes?: number; 39 | } -------------------------------------------------------------------------------- /src/commands/neighbour/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NudStates } from '../neighbour.constants'; 5 | import { NeighbourShowOptions } from './show.interfaces'; 6 | 7 | export const NeighbourShowSchema: JSONSchemaType = { 8 | $id : SchemaIds.NeighbourShow, 9 | type : 'object', 10 | required : [], 11 | properties: { 12 | proxy: { 13 | type : 'boolean', 14 | enum : [true], 15 | nullable: true 16 | }, 17 | to : { 18 | type : 'string', 19 | minLength: 1, 20 | format : 'ip', 21 | nullable : true 22 | }, 23 | dev : { 24 | type : 'string', 25 | minLength: 1, 26 | nullable : true 27 | }, 28 | nud : { 29 | type : 'string', 30 | enum : Object.values(NudStates) as NudStates[], 31 | nullable: true 32 | }, 33 | vrf : { 34 | type : 'string', 35 | minLength: 1, 36 | nullable : true 37 | } 38 | } 39 | }; -------------------------------------------------------------------------------- /src/commands/ntable/change.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ntable change options. 3 | * @category Interfaces 4 | */ 5 | export interface NtableChangeOptions { 6 | /** The name of the table to modify. */ 7 | name: string; 8 | /** The name of the device to modify the table values. */ 9 | dev?: string; 10 | /** The threshold value 1. */ 11 | thresh1?: number; 12 | /** The threshold value 2. */ 13 | thresh2?: number; 14 | /** The threshold value 3. */ 15 | thresh3?: number; 16 | /** Garbage collection interval in milliseconds. */ 17 | gc_int?: number; 18 | /** Base reachable time in milliseconds. */ 19 | base_reachable?: number; 20 | /** Retransmission time in milliseconds. */ 21 | retrans?: number; 22 | /** Time duration to consider a neighbor entry as stale in milliseconds. */ 23 | gc_stale?: number; 24 | /** Delay before first probe in milliseconds. */ 25 | delay_probe?: number; 26 | /** Maximum length of the queue. */ 27 | queue?: number; 28 | /** Number of application level probes to send. */ 29 | app_probs?: number; 30 | /** Number of unicast probes to send. */ 31 | ucast_probes?: number; 32 | /** Number of multicast probes to send. */ 33 | mcast_probes?: number; 34 | /** Delay before sending anycast probes in milliseconds. */ 35 | anycast_delay?: number; 36 | /** Delay before sending proxy probes in milliseconds. */ 37 | proxy_delay?: number; 38 | /** Maximum length of the proxy queue. */ 39 | proxy_queue?: number; 40 | /** Locktime duration in milliseconds. */ 41 | locktime?: number; 42 | } -------------------------------------------------------------------------------- /src/commands/ntable/change.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NtableChangeOptions } from './change.interfaces'; 5 | 6 | export const NtableChangeSchema: JSONSchemaType = { 7 | $id : SchemaIds.NtableChange, 8 | type : 'object', 9 | required : ['name'], 10 | properties: { 11 | name : { 12 | type : 'string', 13 | minLength: 1 14 | }, 15 | dev : { 16 | type : 'string', 17 | minLength: 1, 18 | nullable : true 19 | }, 20 | thresh1 : { 21 | type : 'number', 22 | nullable: true, 23 | minimum : 0 24 | }, 25 | thresh2 : { 26 | type : 'number', 27 | nullable: true, 28 | minimum : 0 29 | }, 30 | thresh3 : { 31 | type : 'number', 32 | nullable: true, 33 | minimum : 0 34 | }, 35 | gc_int : { 36 | type : 'number', 37 | nullable: true, 38 | minimum : 0 39 | }, 40 | base_reachable: { 41 | type : 'number', 42 | nullable: true, 43 | minimum : 0 44 | }, 45 | retrans : { 46 | type : 'number', 47 | nullable: true, 48 | minimum : 0 49 | }, 50 | gc_stale : { 51 | type : 'number', 52 | nullable: true, 53 | minimum : 0 54 | }, 55 | delay_probe : { 56 | type : 'number', 57 | nullable: true, 58 | minimum : 0 59 | }, 60 | queue : { 61 | type : 'number', 62 | nullable: true, 63 | minimum : 0 64 | }, 65 | app_probs : { 66 | type : 'number', 67 | nullable: true, 68 | minimum : 0 69 | }, 70 | ucast_probes : { 71 | type : 'number', 72 | nullable: true, 73 | minimum : 0 74 | }, 75 | mcast_probes : { 76 | type : 'number', 77 | nullable: true, 78 | minimum : 0 79 | }, 80 | anycast_delay : { 81 | type : 'number', 82 | nullable: true, 83 | minimum : 0 84 | }, 85 | proxy_delay : { 86 | type : 'number', 87 | nullable: true, 88 | minimum : 0 89 | }, 90 | proxy_queue : { 91 | type : 'number', 92 | nullable: true, 93 | minimum : 0 94 | }, 95 | locktime : { 96 | type : 'number', 97 | nullable: true, 98 | minimum : 0 99 | } 100 | } 101 | }; -------------------------------------------------------------------------------- /src/commands/ntable/show.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ntable show options. 3 | * @category Interfaces 4 | */ 5 | export interface NtableShowOptions { 6 | /** Only list the table attached to this device. */ 7 | dev?: string; 8 | /** Only lists the table with the given name. */ 9 | name?: string; 10 | } 11 | 12 | /** 13 | * Ntable Info. 14 | * TODO: Need help to build this undocumented & comprehensive interface. 15 | * 16 | * @category Interfaces 17 | */ 18 | export interface NtableInfo { 19 | family: string; 20 | name: string; 21 | dev: string; 22 | refcnt: number; 23 | reachable: number; 24 | base_reachable: number; 25 | retrans: number; 26 | gc_stale: number; 27 | delay_probe: number; 28 | queue: number; 29 | app_probes: number; 30 | ucast_probes: number; 31 | mcast_probes: number; 32 | anycast_delay: number; 33 | proxy_delay: number; 34 | proxy_queue: number; 35 | 36 | locktime?: number; 37 | thresh1?: number; 38 | thresh2?: number; 39 | thresh3?: number; 40 | gc_interval?: number; 41 | key_length?: number; 42 | entry_size?: number; 43 | entries?: number; 44 | last_flush?: string; 45 | last_rand?: string; 46 | hash_rnd?: number; 47 | hash_mask?: string; 48 | hash_chain_gc?: number; 49 | proxy_qlen?: number; 50 | allocs?: number; 51 | destroys?: number; 52 | hash_grows?: number; 53 | res_failed?: number; 54 | lookups?: number; 55 | hits?: number; 56 | rcv_probes_mcast?: number; 57 | rcv_probes_ucast?: number; 58 | periodic_gc_runs?: number; 59 | forced_gc_runs?: number; 60 | table_fulls?: number; 61 | } -------------------------------------------------------------------------------- /src/commands/ntable/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { NtableShowOptions } from './show.interfaces'; 5 | 6 | export const NtableShowSchema: JSONSchemaType = { 7 | $id : SchemaIds.NtableShow, 8 | type : 'object', 9 | required : [], 10 | properties: { 11 | dev : { 12 | type : 'string', 13 | minLength: 1, 14 | nullable : true 15 | }, 16 | name: { 17 | type : 'string', 18 | minLength: 1, 19 | nullable : true 20 | } 21 | } 22 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/bpf.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add route bpf encap arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddRouteBpfEncapArgs { 6 | /** BPF program to execute for incoming packets. */ 7 | in?: string; 8 | /** BPF program to execute for outgoing packets. */ 9 | out?: string; 10 | /** BPF program to execute for transmitted packets. */ 11 | xmit?: string; 12 | /** Size of header BPF program will attach (xmit). */ 13 | headroom?: number; 14 | } -------------------------------------------------------------------------------- /src/commands/route/encap-types/bpf.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddRouteBpfEncapArgs } from './bpf.interfaces'; 4 | 5 | export const RouteBpfEncapArgsSchema: JSONSchemaType = { 6 | type: 'object', 7 | nullable: true, 8 | required: [], 9 | properties: { 10 | in: { 11 | type: 'string', 12 | minLength: 1, 13 | nullable: true 14 | }, 15 | out: { 16 | type: 'string', 17 | minLength: 1, 18 | nullable: true 19 | }, 20 | xmit: { 21 | type: 'string', 22 | minLength: 1, 23 | nullable: true 24 | }, 25 | headroom: { 26 | type: 'integer', 27 | minimum: 1, 28 | nullable: true 29 | } 30 | } 31 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/ioam6.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add route ioam6 encap arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddRouteIoam6EncapArgs { 6 | /** XXX */ 7 | trace: true; 8 | /** XXX */ 9 | prealloc: true; 10 | /** List of IOAM data required in the trace, represented by a bitfield (24 bits). */ 11 | type: number; 12 | /** 13 | * Numerical value to represent an IOAM namespace. 14 | * See `ip-ioam(8)`. 15 | */ 16 | ns: number; 17 | /** Size, in octets, of the pre-allocated trace data block. */ 18 | size: number; 19 | } -------------------------------------------------------------------------------- /src/commands/route/encap-types/ioam6.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddRouteIoam6EncapArgs } from './ioam6.interfaces'; 4 | 5 | export const RouteIoam6EncapArgsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: [ 'trace', 'prealloc', 'type', 'ns', 'size' ], 8 | properties: { 9 | trace: { 10 | type: 'boolean', 11 | enum: [ true ] 12 | }, 13 | prealloc: { 14 | type: 'boolean', 15 | enum: [ true ] 16 | }, 17 | type: { 18 | type: 'integer', 19 | minimum: 0 20 | }, 21 | ns: { 22 | type: 'integer', 23 | minimum: 1 24 | }, 25 | size: { 26 | type: 'integer', 27 | minimum: 1 28 | } 29 | } 30 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/ip.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { TtlSpecialValues } from '../../link.constants'; 2 | 3 | /** 4 | * Add route ip encap arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddRouteIpEncapArgs { 8 | /** Tunel id. */ 9 | id: number; 10 | /** Remote IP. */ 11 | dst: string; 12 | /** XXX */ 13 | src?: string; 14 | /** XXX */ 15 | tos?: number; 16 | /** XXX */ 17 | ttl?: number | TtlSpecialValues; 18 | } -------------------------------------------------------------------------------- /src/commands/route/encap-types/ip.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { TtlSpecialValues } from '../../link.constants'; 4 | import { AddRouteIpEncapArgs } from './ip.interfaces'; 5 | 6 | export const RouteIpEncapArgsSchema: JSONSchemaType = { 7 | type: 'object', 8 | required: [ 'id', 'dst' ], 9 | nullable: true, 10 | properties: { 11 | id: { 12 | type: 'integer', 13 | minimum: 1 14 | }, 15 | dst: { 16 | type: 'string', 17 | format: 'ip-with-optional-mask' 18 | }, 19 | src: { 20 | type: 'string', 21 | format: 'ip-with-optional-mask', 22 | nullable: true 23 | }, 24 | tos: { 25 | type: 'integer', 26 | nullable: true, 27 | minimum: 0, 28 | maximum: 255 29 | }, 30 | ttl: { 31 | type: [ 'string', 'integer' ], 32 | nullable: true, 33 | oneOf: [ 34 | { 35 | type: 'string', 36 | enum: Object.values(TtlSpecialValues) as TtlSpecialValues[], 37 | nullable: true 38 | }, 39 | { 40 | type: 'integer', 41 | minimum: 0, 42 | maximum: 255, 43 | nullable: true 44 | } 45 | ] 46 | } 47 | } 48 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/mpls.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { TtlSpecialValues } from '../../link.constants'; 2 | 3 | /** 4 | * Add route mpls encap arguments. 5 | * @category Interfaces 6 | */ 7 | export interface AddRouteMplsEncapArgs { 8 | /** Mpls label stack with labels separated by /. */ 9 | label: true | string; 10 | /** TTL to use for MPLS header or 0 to inherit from IP header. */ 11 | ttl?: number | TtlSpecialValues; 12 | } -------------------------------------------------------------------------------- /src/commands/route/encap-types/mpls.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { TtlSpecialValues } from '../../link.constants'; 4 | import { AddRouteMplsEncapArgs } from './mpls.interfaces'; 5 | 6 | export const RouteMplsEncapArgsSchema: JSONSchemaType = { 7 | type: 'object', 8 | nullable: true, 9 | required: ['label'], 10 | properties: { 11 | label: { 12 | type: ['boolean', 'string'], 13 | keyless: true, 14 | oneOf: [ 15 | { 16 | type: 'string', 17 | format: 'slash-separated-numbers', 18 | minLength: 1, 19 | keyless: true 20 | }, 21 | { 22 | type: 'boolean', 23 | enum: [true], 24 | keyless: true 25 | } 26 | ] 27 | }, 28 | ttl: { 29 | type: ['string', 'integer'], 30 | nullable: true, 31 | oneOf: [ 32 | { 33 | type: 'string', 34 | enum: Object.values(TtlSpecialValues) as TtlSpecialValues[], 35 | nullable: true 36 | }, 37 | { 38 | type: 'integer', 39 | minimum: 0, 40 | maximum: 255, 41 | nullable: true 42 | } 43 | ] 44 | } 45 | } 46 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/seg6.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Add route seg6 encap arguments. 3 | * @category Interfaces 4 | */ 5 | export interface AddRouteSeg6EncapArgs { 6 | mode: true; 7 | /** Encapsulate packet in an outer IPv6 header with SR. */ 8 | encap?: true; 9 | /** Directly insert Segment Routing Header after IPv6 header. */ 10 | inline?: true; 11 | /** Encapsulate ingress L2 frame within an outer IPv6 header and SRH. */ 12 | l2encap?: true; 13 | /** List of comma-separated IPv6 addresses. */ 14 | segs: string; 15 | /** 16 | * Numerical value in decimal representation. 17 | * See ip-sr(8). 18 | */ 19 | hmac?: number; 20 | } -------------------------------------------------------------------------------- /src/commands/route/encap-types/seg6.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { AddRouteSeg6EncapArgs } from './seg6.interfaces'; 4 | 5 | export const RouteSeg6EncapArgsSchema: JSONSchemaType = { 6 | type: 'object', 7 | required: [ 'mode', 'segs' ], 8 | properties: { 9 | mode: { 10 | type: 'boolean', 11 | enum: [ true ] 12 | }, 13 | encap: { 14 | type: 'boolean', 15 | enum: [ true ], 16 | nullable: true 17 | }, 18 | inline: { 19 | type: 'boolean', 20 | enum: [ true ], 21 | nullable: true 22 | }, 23 | l2encap: { 24 | type: 'boolean', 25 | enum: [ true ], 26 | nullable: true 27 | }, 28 | segs: { 29 | type: 'string', 30 | format: 'comma-separated-ipv6-addresses' 31 | }, 32 | hmac: { 33 | type: 'integer', 34 | minimum: 0, 35 | nullable: true 36 | } 37 | } 38 | }; -------------------------------------------------------------------------------- /src/commands/route/encap-types/seg6local.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { EncapSeg6LocalActions } from '../../route.constants'; 2 | import { EncapSeg6LocalActionsMappings, NextHopArgs } from '../add.interfaces'; 3 | import { RouteRoutingTables } from '../show.constants'; 4 | 5 | /** 6 | * Add route seg6local encap arguments. 7 | * @category Interfaces 8 | */ 9 | export interface AddRouteSeg6LocalEncapArgs { 10 | /** 11 | * Operation to perform on matching packets. 12 | * @see {@link EncapSeg6LocalActions} 13 | */ 14 | action: { 15 | [key in EncapSeg6LocalActions]?: EncapSeg6LocalActionsMappings[key]; 16 | }; 17 | /** 18 | * Used to collect statistics on the processing of actions. 19 | * Three counters are implemented: 20 | * 21 | * 1) packets correctly processed; 22 | * 2) bytes correctly processed; 23 | * 3) packets that cause a processing error (i.e., missing SID List, wrong SID List, etc). 24 | * 25 | * To retrieve the counters related to an action use the `show` method. 26 | */ 27 | count?: true; 28 | } 29 | 30 | /** 31 | * EndXSeg6local encap arguments. 32 | * @category Interfaces 33 | */ 34 | export interface EndXSeg6LocalEncapArgs extends NextHopArgs { 35 | nh6: true; 36 | } 37 | 38 | /** 39 | * EndDt6Seg6local encap arguments. 40 | * @category Interfaces 41 | */ 42 | export interface EndDt6Seg6LocalEncapArgs extends NextHopArgs { 43 | table?: number | RouteRoutingTables; 44 | vrftable?: number | RouteRoutingTables; 45 | } 46 | 47 | /** 48 | * EndB6Seg6local encap arguments. 49 | * @category Interfaces 50 | */ 51 | export interface EndB6Seg6LocalEncapArgs extends NextHopArgs { 52 | srh: true; 53 | /** List of comma separated IPv6 addresses. */ 54 | segs: string; 55 | /** 56 | * Numerical value in decimal representation. 57 | * See ip-sr(8). 58 | */ 59 | hmac?: number; 60 | } 61 | 62 | /** 63 | * EndDx6Seg6local encap arguments. 64 | * @category Interfaces 65 | */ 66 | export type EndDx6Seg6LocalEncapArgs = EndXSeg6LocalEncapArgs; 67 | /** 68 | * EndDt4Seg6local encap arguments. 69 | * @category Interfaces 70 | */ 71 | export type EndDt4Seg6LocalEncapArgs = EndDt6Seg6LocalEncapArgs; 72 | /** 73 | * EndDt46Seg6local encap arguments. 74 | * @category Interfaces 75 | */ 76 | export type EndDt46Seg6LocalEncapArgs = EndDt6Seg6LocalEncapArgs; 77 | /** 78 | * EndB6Seg6local encap arguments. 79 | * @category Interfaces 80 | */ 81 | export type EndB6EncapsSeg6LocalEncapArgs = EndB6Seg6LocalEncapArgs; -------------------------------------------------------------------------------- /src/commands/route/get.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Route get options. 3 | * @category Interfaces 4 | */ 5 | export interface RouteGetOptions { 6 | /** 7 | * Return full `fib` lookup matched route. 8 | * Default is to return the resolved `dst` entry. 9 | */ 10 | fibmatch?: true; 11 | /** The destination address. */ 12 | to?: string; 13 | /** The source address. */ 14 | from?: string; 15 | /** The device from which this packet is expected to arrive. */ 16 | iif?: string; 17 | /** Force the output device on which this packet will be routed. */ 18 | oif?: string; 19 | /** The firewall mark (fwmark). */ 20 | mark?: string; 21 | /** Only select routes with the given TOS. */ 22 | tos?: number; 23 | /** Force the `vrf` device on which this packet will be routed. */ 24 | vrf?: string; 25 | /** IP protocol as seen by the route lookup. */ 26 | ipproto?: string | number; 27 | /** Source port as seen by the route lookup. */ 28 | sport?: number; 29 | /** Destination port as seen by the route lookup. */ 30 | dport?: number; 31 | /** 32 | * If no source address (option from) was given, relookup the route with the source set to the 33 | * preferred address received from the first lookup. 34 | * If policy routing is used, it may be a different route. 35 | */ 36 | connected?: true; 37 | } -------------------------------------------------------------------------------- /src/commands/route/get.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { RouteGetOptions } from './get.interfaces'; 5 | 6 | export const RouteGetSchema: JSONSchemaType = { 7 | $id : SchemaIds.RouteGet, 8 | type : 'object', 9 | required : [], 10 | properties: { 11 | fibmatch : { 12 | type : 'boolean', 13 | enum : [true], 14 | nullable: true 15 | }, 16 | to : { 17 | type : 'string', 18 | format : 'ip-with-optional-mask-and-all-and-default-values', 19 | nullable: true 20 | }, 21 | from : { 22 | type : 'string', 23 | format : 'ip-with-required-mask-and-all-and-default-values', 24 | nullable: true 25 | }, 26 | iif : { 27 | type : 'string', 28 | minLength: 1, 29 | maxLength: 15, 30 | nullable : true 31 | }, 32 | oif : { 33 | type : 'string', 34 | minLength: 1, 35 | maxLength: 15, 36 | nullable : true 37 | }, 38 | mark : { 39 | type : 'string', 40 | nullable: true, 41 | pattern : '^(0x[0-9a-fA-F]+|[0-9]+)(/(0x[0-9a-fA-F]+|[0-9]+))?$' 42 | }, 43 | tos : { 44 | type : 'integer', 45 | nullable: true, 46 | minimum : 0, 47 | maximum : 255 48 | }, 49 | vrf : { 50 | type : 'string', 51 | minLength: 1, 52 | nullable : true 53 | }, 54 | ipproto : { 55 | type : ['string', 'integer'], 56 | nullable: true, 57 | oneOf : [ 58 | { 59 | type : 'string', 60 | minLength: 1, 61 | nullable : true 62 | }, 63 | { 64 | type : 'integer', 65 | minimum : 0, 66 | nullable: true 67 | } 68 | ] 69 | }, 70 | sport : { 71 | type : 'integer', 72 | minimum : 0, 73 | nullable: true 74 | }, 75 | dport : { 76 | type : 'integer', 77 | minimum : 0, 78 | nullable: true 79 | }, 80 | connected: { 81 | type : 'boolean', 82 | enum : [true], 83 | nullable: true 84 | } 85 | } 86 | }; -------------------------------------------------------------------------------- /src/commands/rule.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Routing table special names. 3 | * @category Constants 4 | */ 5 | export enum RoutingTables { 6 | /** 7 | * The `local` table is a special routing table containing high priority control routes for local 8 | * and broadcast addresses. 9 | */ 10 | Local = 'local', 11 | /** The `main` table is the normal routing table containing all non-policy routes. */ 12 | Main = 'main', 13 | /** 14 | * The `default` table is empty. 15 | * It is reserved for some post-processing if no previous default rules selected the packet. 16 | */ 17 | Default = 'default', 18 | } 19 | 20 | /** 21 | * Rule special values. 22 | * @category Constants 23 | */ 24 | export enum RuleTypes { 25 | /** The rule prescribes to return the route found in the routing table referenced by the rule. */ 26 | Unicast = 'unicast', 27 | /** The rule prescribes to silently drop the packet. */ 28 | Blackhole = 'blackhole', 29 | /** The rule prescribes to generate a 'Network is unreachable' error. */ 30 | Unreachable = 'unreachable', 31 | /** The rule prescribes to generate 'Communication is administratively prohibited' error. */ 32 | Prohibit = 'prohibit', 33 | /** The rule prescribes to translate the source address of the IP packet into some other value. */ 34 | Nat = 'nat' 35 | } -------------------------------------------------------------------------------- /src/commands/rule/add.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { RoutingTables } from '../rule.constants'; 2 | import { RuleShowOptions } from './show.interfaces'; 3 | 4 | /** 5 | * Rule add options. 6 | * @category Interfaces 7 | */ 8 | export interface RuleAddOptions extends RuleShowOptions { 9 | /** 10 | * The routing table identifier to lookup if the rule selector matches. 11 | * It is also possible to use lookup instead of table. 12 | */ 13 | table?: number | RoutingTables; 14 | /** 15 | * The routing protocol who installed the rule in question. 16 | * As an example when zebra installs a rule it would get RTPROT_ZEBRA as the installing protocol. 17 | */ 18 | protocol?: string | number; 19 | /** 20 | * The base of the IP address block to translate (for source addresses). 21 | * The ADDRESS may be either the start of the block of NAT addresses (selected by NAT routes) or a local host 22 | * address (or even zero). 23 | * 24 | * In the last case the router does not translate the packets, but masquerades them to this address. 25 | * Using `map-to` instead of `nat` means the same thing. 26 | */ 27 | nat?: string; 28 | /** 29 | * Realms to select if the rule matched and the routing table lookup succeeded. 30 | * Realm TO is only used if the route did not select any realm. 31 | */ 32 | realms?: string; 33 | /** 34 | * Attribute is used to jump to a rule with a specified priority. 35 | * It essentially alters the typical sequence in which rules are evaluated. 36 | */ 37 | goto?: number; 38 | /** Reject routing decisions that have a prefix length of NUMBER or less. */ 39 | suppress_prefixlength?: number; 40 | /** Reject routing decisions that use a device belonging to the interface group GROUP. */ 41 | suppress_ifgroup?: number; 42 | } -------------------------------------------------------------------------------- /src/commands/tunnel.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tunnel available modes. 3 | * @category Constants 4 | */ 5 | export enum TunnelModes { 6 | // IPv4 7 | Ipip = 'ipip', 8 | Sit = 'sit', 9 | Isatap = 'isatap', 10 | Gre = 'gre', 11 | // 12 | // IPv6 13 | // 14 | Ip6ip6 = 'ip6ip6', 15 | Ipip6 = 'ipip6', 16 | Ip6gre = 'ip6gre', 17 | vti6 = 'vti6', 18 | Any = 'any' 19 | } 20 | 21 | /** 22 | * Tunnel Info. 23 | * TODO: Need help to build this undocumented & comprehensive interface. 24 | * 25 | * @category Interfaces 26 | */ 27 | export interface TunnelInfo { 28 | // XXX 29 | } -------------------------------------------------------------------------------- /src/commands/tunnel/6rd.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tunnel 6rd options. 3 | * @category Interfaces 4 | */ 5 | export interface Tunnel6rdOptions { 6 | /** 7 | * Bind the tunnel to the device NAME so that tunneled packets will only be routed via this 8 | * device and will not be able to escape to another device when the route to endpoint changes. 9 | */ 10 | dev: string; 11 | /** XXX. */ 12 | '6rd-prefix'?: string; 13 | /** XXX. */ 14 | '6rd-relay_prefix'?: string; 15 | /** XXX. */ 16 | '6rd-reset'?: true; 17 | } -------------------------------------------------------------------------------- /src/commands/tunnel/6rd.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { Tunnel6rdOptions } from './6rd.interfaces'; 5 | 6 | export const Tunnel6rdSchema: JSONSchemaType = { 7 | $id : SchemaIds.Tunnel6rd, 8 | type : 'object', 9 | required : ['dev'], 10 | properties: { 11 | dev : { 12 | type : 'string', 13 | minLength: 1 14 | }, 15 | '6rd-prefix' : { 16 | type : 'string', 17 | format : 'ip-or-any', 18 | minLength: 1, 19 | nullable : true 20 | }, 21 | '6rd-relay_prefix': { 22 | type : 'string', 23 | format : 'ip-or-any', 24 | minLength: 1, 25 | nullable : true 26 | }, 27 | '6rd-reset' : { 28 | type : 'boolean', 29 | enum : [true], 30 | nullable: true 31 | } 32 | } 33 | }; -------------------------------------------------------------------------------- /src/commands/tunnel/prl.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tunnel prl options. 3 | * @category Interfaces 4 | */ 5 | export interface TunnelPrlOptions { 6 | /** 7 | * Bind the tunnel to the device NAME so that tunneled packets will only be routed via this 8 | * device and will not be able to escape to another device when the route to endpoint changes. 9 | */ 10 | dev: string; 11 | /** Add or delete ADDR as a potential router or default router. */ 12 | 'prl-default'?: string; 13 | /** @see {@link['prl-default']} */ 14 | 'prl-nodefault'?: string; 15 | /** @see {@link['prl-default']} */ 16 | 'prl-delete'?: string; 17 | } -------------------------------------------------------------------------------- /src/commands/tunnel/prl.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { TunnelPrlOptions } from './prl.interfaces'; 5 | 6 | export const TunnelPrlSchema: JSONSchemaType = { 7 | $id : SchemaIds.TunnelPrl, 8 | type : 'object', 9 | required : ['dev'], 10 | properties: { 11 | dev : { 12 | type : 'string', 13 | minLength: 1 14 | }, 15 | 'prl-default' : { 16 | type : 'string', 17 | format : 'ip-or-any', 18 | minLength: 1, 19 | nullable : true 20 | }, 21 | 'prl-nodefault': { 22 | type : 'string', 23 | format : 'ip-or-any', 24 | minLength: 1, 25 | nullable : true 26 | }, 27 | 'prl-delete' : { 28 | type : 'string', 29 | format : 'ip-or-any', 30 | minLength: 1, 31 | nullable : true 32 | } 33 | } 34 | }; -------------------------------------------------------------------------------- /src/commands/tuntap.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tunnel available modes. 3 | * @category Constants 4 | */ 5 | export enum TunTapTunnelModes { 6 | Tun = 'tun', 7 | Tap = 'tap', 8 | } -------------------------------------------------------------------------------- /src/commands/tuntap/add.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { TunTapTunnelModes } from '../tuntap.constants'; 2 | 3 | /** 4 | * Tunnel add options. 5 | * @category Interfaces 6 | */ 7 | export interface TunTapTunnelAddOptions { 8 | /** The physical device to attach this tunnel to. */ 9 | dev?: string; 10 | /** Set the tunnel mode. */ 11 | mode: TunTapTunnelModes; 12 | /** XXX */ 13 | user?: string | number; 14 | /** XXX */ 15 | group?: string | number; 16 | /** XXX */ 17 | one_queue?: true; 18 | /** XXX */ 19 | pi?: true; 20 | /** XXX */ 21 | vnet_hdr?: true; 22 | /** XXX */ 23 | multi_queue?: true; 24 | /** XXX */ 25 | name?: string; 26 | } -------------------------------------------------------------------------------- /src/commands/tuntap/add.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { TunTapTunnelAddOptions } from './add.interfaces'; 5 | import { TunTapTunnelModes } from '../tuntap.constants'; 6 | 7 | export const TunTapAddSchema: JSONSchemaType = { 8 | $id : SchemaIds.TunTapAdd, 9 | type : 'object', 10 | required : ['mode'], 11 | properties: { 12 | dev : { 13 | type : 'string', 14 | minLength: 1, 15 | nullable : true 16 | }, 17 | mode : { 18 | type: 'string', 19 | enum: Object.values(TunTapTunnelModes) as TunTapTunnelModes[] 20 | }, 21 | user : { 22 | type : ['string', 'integer'], 23 | nullable: true, 24 | oneOf : [ 25 | { 26 | type : 'string', 27 | minLength: 1 28 | }, 29 | { 30 | type : 'integer', 31 | minimum: 0 32 | } 33 | ] 34 | }, 35 | group : { 36 | type : ['string', 'integer'], 37 | nullable: true, 38 | anyOf : [ 39 | { 40 | type : 'string', 41 | minLength: 1, 42 | nullable : true 43 | }, 44 | { 45 | type : 'integer', 46 | minimum : 0, 47 | nullable: true 48 | } 49 | ] 50 | }, 51 | one_queue : { 52 | type : 'boolean', 53 | enum : [true], 54 | nullable: true 55 | }, 56 | pi : { 57 | type : 'boolean', 58 | enum : [true], 59 | nullable: true 60 | }, 61 | vnet_hdr : { 62 | type : 'boolean', 63 | enum : [true], 64 | nullable: true 65 | }, 66 | multi_queue: { 67 | type : 'boolean', 68 | enum : [true], 69 | nullable: true 70 | }, 71 | name : { 72 | type : 'string', 73 | minLength: 1, 74 | nullable : true 75 | } 76 | } 77 | }; -------------------------------------------------------------------------------- /src/commands/tuntap/show.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { TunTapTunnelAddOptions } from './add.interfaces'; 2 | 3 | /** 4 | * Tunnel show options. 5 | * @category Interfaces 6 | */ 7 | export type TunTapTunnelShowOptions = Partial> & Omit; 8 | 9 | /** 10 | * Tunnel Info. 11 | * TODO: Need help to build this undocumented & comprehensive interface. 12 | * 13 | * @category Interfaces 14 | */ 15 | export interface TunTapTunnelInfo { 16 | ifname: string; 17 | flags: string[]; 18 | // XXX 19 | processes: Array; 20 | } -------------------------------------------------------------------------------- /src/commands/tuntap/show.schema.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../../common/constants/schemas'; 4 | import { TunTapTunnelModes } from '../tuntap.constants'; 5 | import { TunTapTunnelShowOptions } from './show.interfaces'; 6 | 7 | export const TunTapShowSchema: JSONSchemaType = { 8 | $id : SchemaIds.TunTapShow, 9 | type : 'object', 10 | required : [], 11 | properties: { 12 | dev : { 13 | type : 'string', 14 | minLength: 1, 15 | nullable : true 16 | }, 17 | mode : { 18 | type : 'string', 19 | enum : Object.values(TunTapTunnelModes) as TunTapTunnelModes[], 20 | nullable: true 21 | }, 22 | user : { 23 | type : ['string', 'integer'], 24 | nullable: true, 25 | anyOf : [ 26 | { 27 | type : 'string', 28 | minLength: 1, 29 | nullable : true 30 | }, 31 | { 32 | type : 'integer', 33 | minimum : 0, 34 | nullable: true 35 | } 36 | ] 37 | }, 38 | group : { 39 | type : ['string', 'integer'], 40 | nullable: true, 41 | anyOf : [ 42 | { 43 | type : 'string', 44 | minLength: 1, 45 | nullable : true 46 | }, 47 | { 48 | type : 'integer', 49 | minimum : 0, 50 | nullable: true 51 | } 52 | ] 53 | }, 54 | one_queue : { 55 | type : 'boolean', 56 | enum : [true], 57 | nullable: true 58 | }, 59 | pi : { 60 | type : 'boolean', 61 | enum : [true], 62 | nullable: true 63 | }, 64 | vnet_hdr : { 65 | type : 'boolean', 66 | enum : [true], 67 | nullable: true 68 | }, 69 | multi_queue: { 70 | type : 'boolean', 71 | enum : [true], 72 | nullable: true 73 | }, 74 | name : { 75 | type : 'string', 76 | minLength: 1, 77 | nullable : true 78 | } 79 | } 80 | }; -------------------------------------------------------------------------------- /src/common/classes/command-with-filepath.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { FilePathGlobalOptionSchema, SchemaIds } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptionsWithRequiredFilePath } from '../interfaces/common'; 8 | import Command from './command'; 9 | import { validate } from '../misc'; 10 | 11 | const promisifiedExec = promisify(exec); 12 | 13 | export default class CommandWithFilepath extends Command { 16 | 17 | constructor(protected schemaId: SchemaIds, 18 | protected schema: JSONSchemaType, 19 | protected options: T_CommandOptions, 20 | protected globalOptions: GlobalOptionsWithRequiredFilePath, 21 | protected ipCmd: string[]) { 22 | 23 | super(schemaId, 24 | schema, 25 | options, 26 | globalOptions, 27 | ipCmd); 28 | 29 | validate(SchemaIds.FilePathGlobalOption, FilePathGlobalOptionSchema, globalOptions); 30 | this.buildCmd(); 31 | } 32 | 33 | protected override buildCmd() { 34 | super.buildCmd(); 35 | 36 | this._cmd = this.cmd.concat(...[`${ this.globalOptions.filePath }`]); 37 | this._cmdToExec = this.cmd.join(' '); 38 | } 39 | 40 | override async exec(): Promise { 41 | if (this.globalOptions.dryRun) { 42 | return this; 43 | } 44 | 45 | const { stderr } = await promisifiedExec(this._cmdToExec); 46 | 47 | if (!stderr) { 48 | return this; 49 | } 50 | 51 | const message = stderr.replace(/\n/g, ''); 52 | throw new CommandError(message, this._cmdToExec); 53 | } 54 | } -------------------------------------------------------------------------------- /src/common/classes/command-with-redirect-from-filepath-and-returned-data.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { SchemaIds } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptionsWithRequiredFilePath } from '../interfaces/common'; 8 | import CommandWithRedirectFromFilepath from './command-with-redirect-from-filepath'; 9 | 10 | const promisifiedExec = promisify(exec); 11 | 12 | export default class CommandWithRedirectFromFilepathAndReturnedData extends CommandWithRedirectFromFilepath { 15 | 16 | constructor(protected schemaId: SchemaIds, 17 | protected schema: JSONSchemaType, 18 | protected options: T_CommandOptions, 19 | protected globalOptions: GlobalOptionsWithRequiredFilePath, 20 | protected ipCmd: string[]) { 21 | 22 | super(schemaId, 23 | schema, 24 | options, 25 | globalOptions, 26 | ipCmd); 27 | } 28 | 29 | override async exec(): Promise { 30 | if (this.globalOptions.dryRun) { 31 | return this; 32 | } 33 | 34 | const { 35 | stderr, 36 | stdout 37 | } = await promisifiedExec(this._cmdToExec); 38 | 39 | if (!stderr) { 40 | return JSON.parse(stdout); 41 | } 42 | 43 | const message = stderr.replace(/\n/g, ''); 44 | throw new CommandError(message, this._cmdToExec); 45 | } 46 | } -------------------------------------------------------------------------------- /src/common/classes/command-with-redirect-from-filepath.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { FilePathGlobalOptionSchema, SchemaIds } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptionsWithRequiredFilePath } from '../interfaces/common'; 8 | import Command from './command'; 9 | import { validate } from '../misc'; 10 | 11 | const promisifiedExec = promisify(exec); 12 | 13 | export default class CommandWithRedirectFromFilepath extends Command { 14 | constructor(protected schemaId: SchemaIds, 15 | protected schema: JSONSchemaType, 16 | protected options: T_CommandOptions, 17 | protected globalOptions: GlobalOptionsWithRequiredFilePath, 18 | protected ipCmd: string[]) { 19 | 20 | super(schemaId, 21 | schema, 22 | options, 23 | globalOptions, 24 | ipCmd); 25 | 26 | validate(SchemaIds.FilePathGlobalOption, FilePathGlobalOptionSchema, globalOptions); 27 | 28 | this.buildCmd(); 29 | } 30 | 31 | protected override buildCmd() { 32 | super.buildCmd(); 33 | 34 | this._cmd = this.cmd.concat(...[ `<`, `${ this.globalOptions.filePath }` ]); 35 | this._cmdToExec = this.cmd.join(' '); 36 | } 37 | 38 | override async exec(): Promise { 39 | if (this.globalOptions.dryRun) { 40 | return this; 41 | } 42 | 43 | const { stderr } = await promisifiedExec(this._cmdToExec); 44 | 45 | if (!stderr) { 46 | return this; 47 | } 48 | 49 | const message = stderr.replace(/\n/g, ''); 50 | throw new CommandError(message, this._cmdToExec); 51 | } 52 | } -------------------------------------------------------------------------------- /src/common/classes/command-with-redirect-to-filepath.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { FilePathGlobalOptionSchema, SchemaIds } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptionsWithRequiredFilePath } from '../interfaces/common'; 8 | import Command from './command'; 9 | import { validate } from '../misc'; 10 | 11 | const promisifiedExec = promisify(exec); 12 | 13 | export default class CommandWithRedirectToFilepath extends Command { 14 | constructor(protected schemaId: SchemaIds, 15 | protected schema: JSONSchemaType, 16 | protected options: T_CommandOptions, 17 | protected globalOptions: GlobalOptionsWithRequiredFilePath, 18 | protected ipCmd: string[]) { 19 | 20 | super(schemaId, 21 | schema, 22 | options, 23 | globalOptions, 24 | ipCmd); 25 | 26 | validate(SchemaIds.FilePathGlobalOption, FilePathGlobalOptionSchema, globalOptions); 27 | this.buildCmd(); 28 | } 29 | 30 | protected override buildCmd() { 31 | super.buildCmd(); 32 | 33 | this._cmd = this.cmd.concat(...[ `>`, `${ this.globalOptions.filePath }` ]); 34 | this._cmdToExec = this.cmd.join(' '); 35 | } 36 | 37 | override async exec(): Promise { 38 | if (this.globalOptions.dryRun) { 39 | return this; 40 | } 41 | 42 | const { stderr } = await promisifiedExec(this._cmdToExec); 43 | 44 | if (!stderr) { 45 | return this; 46 | } 47 | 48 | const message = stderr.replace(/\n/g, ''); 49 | throw new CommandError(message, this._cmdToExec); 50 | } 51 | } -------------------------------------------------------------------------------- /src/common/classes/command-with-returned-data.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { SchemaIds } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptions } from '../interfaces/common'; 8 | import Command from './command'; 9 | 10 | const promisifiedExec = promisify(exec); 11 | 12 | export default class CommandWithReturnedData extends Command { 13 | constructor(protected schemaId: SchemaIds, 14 | protected schema: JSONSchemaType, 15 | protected options: T_CommandOptions, 16 | protected globalOptions: GlobalOptions, 17 | protected ipCmd: string[]) { 18 | 19 | super(schemaId, 20 | schema, 21 | options, 22 | globalOptions, 23 | ipCmd); 24 | } 25 | 26 | override async exec(): Promise { 27 | if (this.globalOptions.dryRun) { 28 | return this; 29 | } 30 | 31 | const { 32 | stderr, 33 | stdout 34 | } = await promisifiedExec(this._cmdToExec); 35 | 36 | if (!stderr) { 37 | return JSON.parse(stdout); 38 | } 39 | 40 | const message = stderr.replace(/\n/g, ''); 41 | throw new CommandError(message, this._cmdToExec); 42 | } 43 | } -------------------------------------------------------------------------------- /src/common/classes/command-with-stdin.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | import { promisify } from 'util'; 3 | import { exec } from 'child_process'; 4 | 5 | import { SchemaIds, StdinGlobalOptionSchema } from '../constants/schemas'; 6 | import { CommandError } from '../errors/command'; 7 | import { GlobalOptionsWithRequiredStdin } from '../interfaces/common'; 8 | import Command from './command'; 9 | import { validate } from '../misc'; 10 | 11 | const promisifiedExec = promisify(exec); 12 | 13 | export default class CommandWithStdin extends Command { 16 | constructor(protected schemaId: SchemaIds, 17 | protected schema: JSONSchemaType, 18 | protected options: T_CommandOptions, 19 | protected globalOptions: GlobalOptionsWithRequiredStdin, 20 | protected ipCmd: string[]) { 21 | 22 | super(schemaId, 23 | schema, 24 | options, 25 | globalOptions, 26 | ipCmd); 27 | 28 | validate(SchemaIds.StdinGlobalOption, StdinGlobalOptionSchema, globalOptions); 29 | 30 | this.buildCmd(); 31 | } 32 | 33 | protected override buildCmd() { 34 | super.buildCmd(); 35 | 36 | this._cmd = this.cmd.concat('- < { 41 | if (this.globalOptions.dryRun) { 42 | return this; 43 | } 44 | 45 | const { stderr } = await promisifiedExec(this._cmdToExec); 46 | 47 | if (!stderr) { 48 | return this; 49 | } 50 | 51 | const message = stderr.replace(/\n/g, ''); 52 | throw new CommandError(message, this._cmdToExec); 53 | } 54 | } -------------------------------------------------------------------------------- /src/common/constants/attribute-values.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a simple toggle state, either `on` or `off`. 3 | * @category Constants 4 | */ 5 | export enum OnOffToggle { 6 | On = 'on', 7 | Off = 'off' 8 | } 9 | 10 | /** 11 | * Represents a binary state for enabling or disabling a feature or functionality. 12 | * @category Constants 13 | */ 14 | export enum EnableDisableToggle { 15 | Enable = 1, 16 | Disable = 0 17 | } 18 | 19 | /** 20 | * Represents the state for enabling or disabling a feature, expressed as strings. 21 | * @category Constants 22 | */ 23 | export enum EnableDisableAsStringToggle { 24 | Enable = 'enable', 25 | Disable = 'disable' 26 | } 27 | 28 | /** 29 | * Represents the state for enabling, disabling, or setting a feature to automatic mode. 30 | * @category Constants 31 | */ 32 | export enum EnableDisableAutoToggle { 33 | Enable = 'enable', 34 | Disable = 'disable', 35 | Auto = 'auto' 36 | } -------------------------------------------------------------------------------- /src/common/constants/tests.ts: -------------------------------------------------------------------------------- 1 | export enum TestEnum { 2 | ValueA = 'value-a', 3 | ValueB = 'value-b', 4 | } 5 | -------------------------------------------------------------------------------- /src/common/errors/command.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Error class to be used when the command throws an error. 3 | * @category Errors 4 | */ 5 | export class CommandError extends Error { 6 | /** Code to identify the error in `catch` clauses. */ 7 | code = 'ERR_COMMAND_ERRORED'; 8 | 9 | /** Command line that triggered the command error. */ 10 | cmd: string; 11 | 12 | constructor(message: string, cmd: string) { 13 | // 'Error' breaks prototype chain here. 14 | super(message); 15 | // Fixing the break. 16 | Object.setPrototypeOf(this, CommandError.prototype); 17 | 18 | this.cmd = cmd; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/common/errors/parameters.ts: -------------------------------------------------------------------------------- 1 | import { ErrorObject } from 'ajv'; 2 | 3 | /** 4 | * Error class to be used when the provided options are invalid. 5 | * @category Errors 6 | */ 7 | export class ParametersError extends Error { 8 | /** Code to identify the error in `catch` clauses. */ 9 | code = 'ERR_INVALID_PARAMETERS'; 10 | 11 | /** 12 | * Detailed introspection on the encountered errors, useful to know exactly 13 | * what failed in the options. 14 | */ 15 | errors?: ErrorObject[] | null; 16 | 17 | static message: string = 'Invalid parameters. Catch `e.errors` for details.'; 18 | 19 | constructor(message: string, errors?: ErrorObject[] | null) { 20 | // 'Error' breaks prototype chain here. 21 | super(message); 22 | // Fixing the break. 23 | Object.setPrototypeOf(this, ParametersError.prototype); 24 | 25 | this.errors = errors; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/common/interfaces/monitor.ts: -------------------------------------------------------------------------------- 1 | import { MonitorObjects } from '../../commands/monitor.constants'; 2 | 3 | /** 4 | * The returned data emitted from {@link monitor} 5 | * @category Interfaces 6 | */ 7 | export interface MonitorEmittedData { 8 | /** The event timestamp in the format `--
T.`. */ 9 | timestamp: string; 10 | /** The namespace which the event originated from. */ 11 | nsid: string; 12 | /** The object that caused the update. */ 13 | object: MonitorObjects; 14 | /** The lines that `ip monitor` gave to `stdout` when an update came, parsed in interesting lines. */ 15 | lines: string[]; 16 | /** The original line emitted by the command. */ 17 | originalLine: string; 18 | // TODO: Add a parsed `data` in the future? It would be best if `iproute` team added `-json` option to `monitor` too. 19 | } -------------------------------------------------------------------------------- /src/common/interfaces/tests.ts: -------------------------------------------------------------------------------- 1 | import { TestEnum } from '../constants/tests'; 2 | import { GlobalOptions } from './common'; 3 | 4 | export interface ComplexIpCommandTestOptions extends ComplexIpCommandTestArgsOptions { 5 | nestedInvisibleKey: ComplexIpCommandTestArgsOptions; 6 | } 7 | 8 | export interface ComplexIpCommandTestArgsOptions { 9 | aString: string; 10 | aNumber: number; 11 | anEnum: TestEnum; 12 | 13 | aFlag: boolean; 14 | noaFlag: boolean; 15 | 16 | number?: number; 17 | 18 | aTuple: [number, number]; 19 | 20 | anArray: Array<{ 21 | aNumber: number; 22 | aStringWithDefaultValue?: string; 23 | }>; 24 | } 25 | 26 | export interface TestFixture { 27 | description: string; 28 | options: T_Options; 29 | globalOptions?: T_GlobalOptions; 30 | expectedCmd: Array; 31 | expectedCmdToExec: string; 32 | } 33 | 34 | export interface TestDefinition { 35 | [index: string]: Array<{ 36 | operator: string; 37 | testBattery: TestFixture[]; 38 | method: Function; 39 | skipOptions?: boolean; 40 | }>; 41 | } -------------------------------------------------------------------------------- /src/common/misc.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import ajv from './validator'; 4 | import { SchemaIds } from './constants/schemas'; 5 | import { ParametersError } from './errors/parameters'; 6 | 7 | /** @internal */ 8 | export function validate(schemaId: SchemaIds, 9 | schema: JSONSchemaType, 10 | options: T_Options) { 11 | 12 | const ajvValidate = ajv.getSchema(schemaId) || ajv.compile(schema); 13 | const isValid = ajvValidate(options); 14 | 15 | if (!isValid) { 16 | throw new ParametersError(ParametersError.message, ajvValidate.errors); 17 | } 18 | } -------------------------------------------------------------------------------- /src/common/validator.ts: -------------------------------------------------------------------------------- 1 | import Ajv, { _, KeywordCxt } from 'ajv'; 2 | import addFormats from 'ajv-formats'; 3 | 4 | import { 5 | ip, 6 | ipWithOptionalFamilyPrefix, 7 | ipWithOptionalMask, 8 | ipWithOptionalMaskAndAllAndDefaultValues, 9 | ipWithRequiredMask, 10 | ipWithRequiredMaskAndAllAndDefaultValues, 11 | slashSeparatedStrings, 12 | commaSeparatedIpv6Addresses, 13 | timeWithUnit, colonSeparatedNumbers, 14 | ipOrAny, slashSeparatedNumbers, mac, hex4Digits, tos 15 | } from './constants/regexes'; 16 | 17 | const ajv = new Ajv({ 18 | strict : true, 19 | useDefaults : true, 20 | coerceTypes : false, 21 | allowUnionTypes: true 22 | }); 23 | 24 | ajv.addKeyword({ 25 | keyword : 'keyless', 26 | schemaType: 'boolean', 27 | valid : true, 28 | code(cxt: KeywordCxt) { 29 | // Noop. 30 | } 31 | }); 32 | 33 | addFormats(ajv, [ 34 | 'ipv4', 35 | 'ipv6' 36 | ]); 37 | 38 | ajv.addFormat('mac', mac); 39 | ajv.addFormat('4-hex', hex4Digits); 40 | ajv.addFormat('filepath', /^(\/)?([^/\0]+(\/)?)+(\.\w+)?$/); 41 | ajv.addFormat('slash-separated-strings', slashSeparatedStrings); 42 | ajv.addFormat('slash-separated-numbers', slashSeparatedNumbers); 43 | ajv.addFormat('comma-separated-ipv6-addresses', commaSeparatedIpv6Addresses); 44 | ajv.addFormat('time-with-unit', timeWithUnit); 45 | ajv.addFormat('colon-separated-numbers', colonSeparatedNumbers); 46 | ajv.addFormat('tos', tos); 47 | 48 | // Since `ajv` doesn't support several formats for same property. 49 | ajv.addFormat('ip', new RegExp(ip, 'i')); 50 | ajv.addFormat('ip-with-optional-mask', new RegExp(ipWithOptionalMask, 'i')); 51 | ajv.addFormat('ip-with-required-mask', new RegExp(ipWithRequiredMask, 'i')); 52 | 53 | ajv.addFormat('ip-or-any', new RegExp(ipOrAny, 'i')); 54 | 55 | ajv.addFormat('ip-with-required-mask-and-all-and-default-values', new RegExp(ipWithRequiredMaskAndAllAndDefaultValues, 'i')); 56 | ajv.addFormat('ip-with-optional-mask-and-all-and-default-values', new RegExp(ipWithOptionalMaskAndAllAndDefaultValues, 'i')); 57 | ajv.addFormat('ip-with-optional-family-prefix', new RegExp(ipWithOptionalFamilyPrefix, 'i')); 58 | 59 | export default ajv; 60 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import * as ipForwardingModule from './ip-forwarding'; 2 | import ipForwardingDefaults from './ip-forwarding'; 3 | 4 | import * as routingTablesModule from './routing-tables'; 5 | import routingTablesDefaults from './routing-tables'; 6 | 7 | /** Manipulates IP forwarding. */ 8 | export { ipForwardingModule as ipForwarding }; 9 | /** Manipulates routing tables. */ 10 | export { routingTablesModule as routingTables }; 11 | 12 | export default { 13 | ipForwarding: ipForwardingDefaults, 14 | routingTables: routingTablesDefaults 15 | }; 16 | -------------------------------------------------------------------------------- /src/utils/ip-forwarding.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sysctl actions. 3 | * 4 | * @category Constants 5 | * @internal 6 | */ 7 | export enum SysctlActions { 8 | Enable = 'enable', 9 | Disable = 'disable', 10 | Status = 'status' 11 | } 12 | 13 | /** 14 | * Sysctl paths. 15 | * 16 | * @category Constants 17 | * @internal 18 | */ 19 | export enum SysctlPaths { 20 | Ipv4Forwarding = 'net.ipv4.ip_forward', 21 | Ipv6Forwarding = 'net.ipv6.conf.all.forwarding' 22 | } -------------------------------------------------------------------------------- /src/utils/routing-tables.constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Routing table file path. 3 | * 4 | * @category Constants 5 | * @internal 6 | */ 7 | export const tablesPath = '/etc/iproute2/rt_tables'; -------------------------------------------------------------------------------- /src/utils/routing-tables.interfaces.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Routing table. 3 | * @category Interfaces 4 | */ 5 | export interface RoutingTable { 6 | id: number; 7 | name: string; 8 | } 9 | 10 | /** 11 | * Routing table options 12 | * @category Interfaces 13 | */ 14 | export interface RoutingTableOptions { 15 | id?: number; 16 | name?: string; 17 | } -------------------------------------------------------------------------------- /src/utils/routing-tables.schemas.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchemaType } from 'ajv'; 2 | 3 | import { SchemaIds } from '../common/constants/schemas'; 4 | import { RoutingTableOptions } from './routing-tables.interfaces'; 5 | 6 | export const RoutingTableOptionsSchema: JSONSchemaType = { 7 | $id: SchemaIds.RoutingTablesOptions, 8 | type: 'object', 9 | required: [], 10 | properties: { 11 | id: { 12 | type: 'integer', 13 | minimum: 0, 14 | nullable: true 15 | }, 16 | name: { 17 | type: 'string', 18 | minLength: 1, 19 | nullable: true 20 | } 21 | } 22 | }; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "declaration": true, 8 | "outDir": "./lib", 9 | "strict": true, 10 | "strictNullChecks": true, 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "types": [ 15 | "node", 16 | "mocha", 17 | "chai" 18 | ] 19 | }, 20 | "include": ["src"], 21 | "exclude": ["node_modules", "**/__tests__/**"] 22 | } -------------------------------------------------------------------------------- /typedoc.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": [ 3 | "./src/index.ts" 4 | ], 5 | "out": "./docs", 6 | "entryPointStrategy": "resolve", 7 | "name": "node-iproute", 8 | "includeVersion": true, 9 | "theme": "default", 10 | "cacheBust": true, 11 | "hideParameterTypesInTitle": false, 12 | "searchInComments": false, 13 | "cleanOutputDir": true, 14 | "excludeInternal": false, 15 | "treatWarningsAsErrors": false, 16 | "navigationLinks": { 17 | "npm": "https://npmjs.com/iproute", 18 | "Github": "https://github.com/diosney/node-iproute", 19 | "Donate": "https://ko-fi.com/diosney" 20 | }, 21 | "sidebarLinks": { 22 | "Home": "/node-iproute", 23 | "Examples": "https://github.com/diosney/node-iproute/blob/master/EXAMPLES.md", 24 | "TODO": "https://github.com/diosney/node-iproute/blob/master/TODO.md", 25 | "Changelog": "https://github.com/diosney/node-iproute/blob/master/CHANGELOG.md" 26 | }, 27 | "navigation": { 28 | "includeCategories": true, 29 | "includeGroups": false 30 | }, 31 | "visibilityFilters": { 32 | "protected": true, 33 | "private": true, 34 | "inherited": true, 35 | "external": true 36 | }, 37 | "defaultCategory": "Misc", 38 | "categoryOrder": [ 39 | "IP Commands", 40 | "Errors", 41 | "Constants", 42 | "Interfaces", 43 | "Schemas", 44 | "Classes", 45 | "Regexes", 46 | "Misc" 47 | ] 48 | } 49 | --------------------------------------------------------------------------------