Skip to content

Commit

Permalink
feat(plc4go/plc4xpcapanalyzer): added more options to cbus
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Jul 12, 2022
1 parent 56160bf commit 95c80a8
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 60 deletions.
46 changes: 13 additions & 33 deletions plc4go/tools/plc4xpcapanalyzer/cmd/analyze.go
Expand Up @@ -20,9 +20,9 @@
package cmd

import (
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/config"
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/internal/analyzer"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"math"
"os"

Expand All @@ -34,16 +34,6 @@ var validProtocolType = map[string]interface{}{
"c-bus": nil,
}

// flags here
var (
filter string
noFilter, onlyParse, noBytesCompare bool
client string
bacnetFilter string
startPackageNumber uint
packageNumberLimit uint
)

// analyzeCmd represents the analyze command
var analyzeCmd = &cobra.Command{
Use: "analyze [protocolType] [pcapfile]",
Expand All @@ -67,33 +57,23 @@ TODO: document me
Run: func(cmd *cobra.Command, args []string) {
protocolType := args[0]
pcapFile := args[1]
if !noFilter {
switch protocolType {
case "bacnet":
if filter != "" && bacnetFilter != "" {
log.Debug().Str("filter", filter).Msg("Setting bacnet filter")
filter = bacnetFilter
}
}
} else {
log.Info().Msg("All filtering disabled")
}
analyzer.Analyze(pcapFile, protocolType, filter, onlyParse, noBytesCompare, client, startPackageNumber, packageNumberLimit, verbosity)
analyzer.Analyze(pcapFile, protocolType)
println("Done")
},
}

func init() {
rootCmd.AddCommand(analyzeCmd)

analyzeCmd.Flags().StringVarP(&filter, "filter", "f", "", "BFF filter to apply")
analyzeCmd.Flags().BoolVarP(&noFilter, "no-filter", "n", false, "disable filter")
analyzeCmd.Flags().BoolVarP(&onlyParse, "onlyParse", "o", false, "only parse messaged")
analyzeCmd.Flags().BoolVarP(&noBytesCompare, "noBytesCompare", "b", false, "don't compare original bytes with serialized bytes")
analyzeCmd.Flags().StringVarP(&client, "client", "c", "", "The client ip (this is useful for protocols where request/response is different e.g. modbus, cbus)")
analyzeCmd.Flags().UintVarP(&startPackageNumber, "startPackageNumber", "s", 0, "Defines with what package number should be started")
analyzeCmd.Flags().UintVarP(&packageNumberLimit, "packageNumberLimit", "l", math.MaxUint, "Defines how many packages should be parsed")
// TODO: maybe it is smarter to convert this into subcommands because this option is only relevant to bacnet
analyzeCmd.PersistentFlags().StringVarP(&bacnetFilter, "default-bacnet-filter", "", "udp port 47808 and udp[4:2] > 29", "Defines the default filter when bacnet is selected")
// TODO: support other protocols
addAnalyzeFlags(analyzeCmd)
}

func addAnalyzeFlags(command *cobra.Command) {
command.Flags().StringVarP(&config.AnalyzeConfigInstance.Filter, "filter", "f", "", "BFF filter to apply")
command.Flags().BoolVarP(&config.AnalyzeConfigInstance.NoFilter, "no-filter", "n", false, "disable filter")
command.Flags().BoolVarP(&config.AnalyzeConfigInstance.OnlyParse, "onlyParse", "o", false, "only parse messaged")
command.Flags().BoolVarP(&config.AnalyzeConfigInstance.NoBytesCompare, "noBytesCompare", "b", false, "don't compare original bytes with serialized bytes")
command.Flags().StringVarP(&config.AnalyzeConfigInstance.Client, "client", "c", "", "The client ip (this is useful for protocols where request/response is different e.g. modbus, cbus)")
command.Flags().UintVarP(&config.AnalyzeConfigInstance.StartPackageNumber, "startPackageNumber", "s", 0, "Defines with what package number should be started")
command.Flags().UintVarP(&config.AnalyzeConfigInstance.PackageNumberLimit, "packageNumberLimit", "l", math.MaxUint, "Defines how many packages should be parsed")
}
70 changes: 70 additions & 0 deletions plc4go/tools/plc4xpcapanalyzer/cmd/bacnet.go
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package cmd

import (
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/config"
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/internal/analyzer"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"os"

"github.com/spf13/cobra"
)

// bacnetCmd represents the bacnet command
var bacnetCmd = &cobra.Command{
Use: "bacnet [pcapfile]",
Short: "analyzes a pcap file using a bacnet driver",
Long: `Analyzes a pcap file using a bacnet driver
TODO: document me
`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("requires exactly one arguments")
}
pcapFile := args[0]
if _, err := os.Stat(pcapFile); errors.Is(err, os.ErrNotExist) {
return errors.Errorf("Pcap file not found %s", pcapFile)
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
pcapFile := args[0]
if !config.BacnetConfigInstance.NoFilter {
if config.BacnetConfigInstance.Filter != "" && config.BacnetConfigInstance.BacnetFilter != "" {
log.Debug().Str("filter", config.BacnetConfigInstance.Filter).Msg("Setting bacnet filter")
config.BacnetConfigInstance.Filter = config.BacnetConfigInstance.BacnetFilter
}
} else {
log.Info().Msg("All filtering disabled")
}
analyzer.Analyze(pcapFile, "bacnet")
println("Done")
},
}

func init() {
analyzeCmd.AddCommand(bacnetCmd)

bacnetCmd.PersistentFlags().StringVarP(&config.BacnetConfigInstance.BacnetFilter, "default-bacnet-filter", "", "udp port 47808 and udp[4:2] > 29", "Defines the default filter when bacnet is selected")

addAnalyzeFlags(bacnetCmd)
}
80 changes: 80 additions & 0 deletions plc4go/tools/plc4xpcapanalyzer/cmd/cbus.go
@@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package cmd

import (
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/config"
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/internal/analyzer"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"os"

"github.com/spf13/cobra"
)

// cbusCmd represents the cbus command
var cbusCmd = &cobra.Command{
Use: "c-bus [pcapfile]",
Short: "analyzes a pcap file using a c-bus driver",
Long: `Analyzes a pcap file using a c-bus driver
TODO: document me
`,
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("requires exactly one arguments")
}
pcapFile := args[0]
if _, err := os.Stat(pcapFile); errors.Is(err, os.ErrNotExist) {
return errors.Errorf("Pcap file not found %s", pcapFile)
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
pcapFile := args[0]
if !config.CBusConfigInstance.NoFilter {
if config.CBusConfigInstance.Filter != "" && config.CBusConfigInstance.CBusFilter != "" {
log.Debug().Str("filter", config.CBusConfigInstance.Filter).Msg("Setting cbus filter")
config.CBusConfigInstance.Filter = config.CBusConfigInstance.CBusFilter
}
} else {
log.Info().Msg("All filtering disabled")
}
analyzer.Analyze(pcapFile, "c-bus")
println("Done")
},
}

func init() {
analyzeCmd.AddCommand(cbusCmd)

cbusCmd.PersistentFlags().StringVarP(&config.CBusConfigInstance.CBusFilter, "default-cbus-filter", "", "udp port 10001", "Defines the default filter when c-bus is selected")

cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Connect, "cbus-connect", "", false, "Defines that SAL messages can occur at any time")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Smart, "cbus-smart", "", false, "Disable echo of characters. When used with connect SAL have a long option. Select long from of most CAL replies")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Idmon, "cbus-idmon", "", false, "only works with smart. Select long form of CAL messages")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Exstat, "cbus-exstat", "", false, "useful with smart. Select long form, extended format for all monitored and initiated status requests")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Monitor, "cbus-monitor", "", false, "monitors all traffic for status requests. Status requests will be returned as CAL. Replies are modified by exstat. Usually used in conjunction with connect.")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Monall, "cbus-monall", "", false, "Same as connect. In addition it will return remote network SAL")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Pun, "cbus-pun", "", false, "Serial interface will emit a power up notification")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Pcn, "cbus-pcn", "", false, "causes parameter change notifications to be emitted.")
cbusCmd.Flags().BoolVarP(&config.CBusConfigInstance.Srchk, "cbus-srchk", "", false, "enabled the crc checks")

addAnalyzeFlags(cbusCmd)
}
24 changes: 10 additions & 14 deletions plc4go/tools/plc4xpcapanalyzer/cmd/root.go
Expand Up @@ -21,6 +21,7 @@ package cmd

import (
"fmt"
"github.com/apache/plc4x/plc4go/tools/plc4xpcapanalyzer/config"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog/pkgerrors"
Expand All @@ -30,11 +31,6 @@ import (
"github.com/spf13/viper"
)

var cfgFile string
var logType string
var logLevel string
var verbosity int

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "plc4xpcapanalyzer",
Expand All @@ -57,19 +53,19 @@ func Execute() {
func init() {
cobra.OnInitialize(initConfig)

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.plc4xpcapanalyzer.yaml)")
rootCmd.PersistentFlags().StringVar(&logType, "log-type", "text", "define how the log will be evaluated")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "off", "define the log Level")
rootCmd.PersistentFlags().CountVarP(&verbosity, "verbose", "v", "counted verbosity")
rootCmd.PersistentFlags().StringVar(&config.RootConfigInstance.CfgFile, "config", "", "config file (default is $HOME/.plc4xpcapanalyzer.yaml)")
rootCmd.PersistentFlags().StringVar(&config.RootConfigInstance.LogType, "log-type", "text", "define how the log will be evaluated")
rootCmd.PersistentFlags().StringVar(&config.RootConfigInstance.LogLevel, "log-level", "off", "define the log Level")
rootCmd.PersistentFlags().CountVarP(&config.RootConfigInstance.Verbosity, "verbose", "v", "counted verbosity")

rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
if config.RootConfigInstance.CfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
viper.SetConfigFile(config.RootConfigInstance.CfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
Expand All @@ -89,7 +85,7 @@ func initConfig() {
}

zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
if logType == "text" {
if config.RootConfigInstance.LogType == "text" {
log.Logger = log.
//// Enable below if you want to see the filenames
//With().Caller().Logger().
Expand All @@ -99,9 +95,9 @@ func initConfig() {
}

func parseLogLevel() zerolog.Level {
level, err := zerolog.ParseLevel(logLevel)
level, err := zerolog.ParseLevel(config.RootConfigInstance.LogLevel)
if err != nil {
log.Fatal().Err(err).Msgf("Unknown log level %s", logLevel)
log.Fatal().Err(err).Msgf("Unknown log level %s", config.RootConfigInstance.LogLevel)
}
return level
}
35 changes: 35 additions & 0 deletions plc4go/tools/plc4xpcapanalyzer/config/AnalyzeConfig.go
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package config

type AnalyzeConfig struct {
*RootConfig
Filter string
NoFilter, OnlyParse, NoBytesCompare bool
Client string
StartPackageNumber uint
PackageNumberLimit uint
}

var AnalyzeConfigInstance = AnalyzeConfig{}

func init() {
AnalyzeConfigInstance.RootConfig = &RootConfigInstance
}
31 changes: 31 additions & 0 deletions plc4go/tools/plc4xpcapanalyzer/config/BacnetConfig.go
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package config

type BacnetConfig struct {
*AnalyzeConfig
BacnetFilter string
}

var BacnetConfigInstance = BacnetConfig{}

func init() {
BacnetConfigInstance.AnalyzeConfig = &AnalyzeConfigInstance
}

0 comments on commit 95c80a8

Please sign in to comment.