network traffic packet enumeration with tshark - networking

Although it sounds easy, I cannot find an answer around..
I just need to enumerate certain packets in a certain pcap file (with tshark).
e.g.:
how many packets are ipv6.ack?
how many packets are udp?
and tshark has to print just a number...

You can use the -z io,stat,0 option, e.g.:
tshark -r capture.pcap -q -z io,stat,0,"udp"
... however this will produce an IO Statistics table, not a single number.
If you have tools like wc, grep and cut available to you, you could try one or more of these solutions:
tshark -r capture.pcap -q -z io,stat,0,"udp" | grep "<>" | cut -d ' ' -f 8
tshark -r capture.pcap -Y "udp" | wc -l
If you're on Windows, and you don't have any of these tools, you could try wrapping this in a batch file, such as:
#ECHO OFF
SETLOCAL
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
IF "%1" == "" GOTO :USAGE
IF "%2" == "" (
SET TSHARK_CMD=tshark.exe -r %1 -z io,stat,0
) ELSE (
SET TSHARK_CMD=tshark.exe -r %1 -z io,stat,0,"%2"
)
FOR /F "TOKENS=6 DELIMS= " %%A in ('!TSHARK_CMD! ^| FINDSTR "^<^>"') DO (
ECHO %%A
)
GOTO :END
:USAGE
ECHO usage: printframes ^<file^> ^[filter^]
ENDLOCAL
:END

Related

Issues with iconv command in script

I am trying to create a script which detects if files in a directory have not UTF-8 characters and if they do, grab the file type of that particular file and perform the iconv operation on it.
The code is follows
find <directory> |sed '1d'><directory>/filelist.txt
while read filename
do
file_nm=${filename%%.*}
ext=${filename#*.}
echo $filename
q=`grep -axv '.*' $filename|wc -l`
echo $q
r=`file -i $filename|cut -d '=' -f 2`
echo $r
#file_repair=$file_nm
if [ $q -gt 0 ]; then
iconv -f $r -t utf-8 -c ${file_nm}.${ext} >${file_nm}_repaired.${ext}
mv ${file_nm}_repaired.${ext} ${file_nm}.${ext}
fi
done< <directory>/filelist.txt
While running the code, there are several files that turn into 0 byte files and .bak gets appended to the file name.
ls| grep 'bak' | wc -l
36
Where am I making a mistake?
Thanks for the help.
It's really not clear what some parts of your script are supposed to do.
Probably the error is that you are assuming file -i will output a string which always contains =; but it often doesn't.
find <directory> |
# avoid temporary file
sed '1d' |
# use IFS='' read -r
while IFS='' read -r filename
do
# indent loop body
file_nm=${filename%%.*}
ext=${filename#*.}
# quote variables, print diagnostics to stderr
echo "$filename" >&2
# use grep -q instead of useless wc -l; don't enter condition needlessly; quote variable
if grep -qaxv '.*' "$filename"; then
# indent condition body
# use modern command substitution syntax, quote variable
# check if result contains =
r=$(file -i "$filename")
case $r in
*=*)
# only perform decoding if we can establish encoding
echo "$r" >&2
iconv -f "${r#*=}" -t utf-8 -c "${file_nm}.${ext}" >"${file_nm}_repaired.${ext}"
mv "${file_nm}_repaired.${ext}" "${file_nm}.${ext}" ;;
*)
echo "$r: could not establish encoding" >&2 ;;
esac
fi
done
See also Why is testing “$?” to see if a command succeeded or not, an anti-pattern? (tangential, but probably worth reading) and useless use of wc
The grep regex is kind of mysterious. I'm guessing you want to check if the file contains non-empty lines? grep -qa . "$filename" would do that.

Get Return Code of SFTP command

I have the snippet below inside my ksh script. Is there a way that I can have a return code whether the sftp executed successfully and copied the files from source to target destination?
echo "sftp start" >> /test/logfile.log
sftp user#server <<EOF >> /test/logfile.log
cd /tgt/files
lcd /src/files
rm *.csv
put -p *.csv
exit
EOF
echo "sftp end" >> /test/logfile.log
The solution of Gilles Quenot will only work with the following three improvements. Without those improvement the exit status will always be 0 regardless the result of the sftp commands.
sftp option -b - needs to be added to the sftp command. Only then will sftp exit with status 1 if some sftp command goes wrong. Otherwise the exit status is always 0.
I've added 2>&1 | tee to log also the errors (it redirects stderr to stdout)
You must use ${PIPESTATUS[0]} to read the exit status of sftp. $? gives the exit status of the last command and that is the redirect to the logfile.
echo "sftp start" >> /test/logfile.log
sftp -b - user#server <<EOF 2>&1 | tee /test/logfile.log
cd /tgt/files
lcd /src/files
rm *.csv
put -p *.csv
exit
EOF
exit_code=${PIPESTATUS[0]}
if [[ $exit_code != 0 ]]; then
echo "sftp error" >&2
exit 1
fi
echo "sftp end" >> /test/logfile.log
Regards,
Maarten
What I would do :
echo "sftp start" >> /test/logfile.log
sftp user#server <<EOF >> /test/logfile.log
cd /tgt/files
lcd /src/files
rm *.csv
put -p *.csv
exit
EOF
exit_code=$?
if [[ $exit_code != 0 ]]; then
echo "sftp error" >&2
exit 1
fi
echo "sftp end" >> /test/logfile.log
Instead of using sftp and writing so many intermediate commands in order to move to the proper folders, remove files etc before your transfer, you could use the following way more compact commands:
echo "file transfer started" >> /test/logfile.log
ssh user#server 'rm /tgt/files/*.csv' >> /test/logfile.log 2>&1 && scp /src/files/*.csv user#server:/tgt/files/ >> /test/logfile.log 2>&1
rc=$?
if [[ $rc != 0 ]]; then
echo "ERROR: transfer failed" >> /test/logfile.log
exit 1
fi
echo "file transfer completed" >> /test/logfile.log
Explanations:
ssh user#server 'rm /tgt/files/*.csv' >> /test/logfile.log 2>&1 && scp /src/files/*.csv user#server:/tgt/files/ >> /test/logfile.log 2>&1 if the files are properly removed from the target folder than and only than (&&) the transfer will be done!! Intermediate errors are also redirected to the output log files.

Creating directories from an input file

I have below mentioned directories in an input file and i need them to create in a loop.
data/app_rt_ws/Request/2017_06_27
data/app_rt_ws/Response/2017_06_19
data/app_rt_ws/RTWS
data/app_rt_ws/SDP
data/edge/response/9-20-2016
data/edge/response/9-22-2016
Problem is that i don't need the directories in the yyyy_mm_dd or dd-mm-yyyy format which get created at run time on the server. I need them to be discarded and have the rest of the static path of the directories created.
I am using below mentioned code but can't seem to figure out how to omit the above mentioned part
for i in `cat /tmp/inputfile.txt`
do
echo $i
cd /opt/app/app
awk '/date_year/{print $1}' (need to filter out the entries with date)
mkdir -p $i ( need to create rest of the directories)
done
You may modify your script as followed,
for i in `awk '$0 !~ (/[0-9]{1,2}-[0-9]{1,2}-20[0-9]{2}/ && /20[0-9]{2}_[0-9]{1,2}_[0-9]{1,2}/){print}' inputfile.txt`;
do
echo $i
cd /opt/app/app
mkdir -p $i
done
And the output of the awk command is like this,
$ awk '$0 !~ (/[0-9]{1,2}-[0-9]{1,2}-20[0-9]{2}/ && /20[0-9]{2}_[0-9]{1,2}_[0-9]{1,2}/){print}' inputfile.txt
data/app_rt_ws/RTWS
data/app_rt_ws/SDP
With bash for regexp matching:
$ cat tst.sh
while IFS= read -r path; do
if [[ $path =~ /([0-9]{4}(_[0-9]{2}){2}|([0-9]{1,2}-){2}[0-9]{4})$ ]]; then
path="${path%/*}"
fi
echo mkdir -p "$path"
done < "$1"
$ ./tst.sh file
mkdir -p data/app_rt_ws/Request
mkdir -p data/app_rt_ws/Response
mkdir -p data/app_rt_ws/RTWS
mkdir -p data/app_rt_ws/SDP
mkdir -p data/edge/response
mkdir -p data/edge/response
Remove the echo once you've tested and are happy with the result. Check the regexp - you said you wanted to match dd-mm-yyyy but then your input contained dates as d-mm-yyyy so idk what you really wanted and so I guessed you'd be happy with 1 or 2 digits, hence [0-9]{1,2}.
With other shells use a case statement or similar to match the date at the end of line as a globbing pattern. You do NOT need to call an external tool to do this check.
Using:
for i in `some command`
is always to be avoided because it breaks when the output of some command contains spaces and it's using deprecated backticks instead of modern notation $(some command), and doing:
echo $i
is always to be avoided because you should ALWAYS quote your shell variables (echo "$i") unless you have a specific reason not to so as to avoid accidental word splitting and file name generation.
You could use the bash string substitutions to get rid of the date.
for i in `cat /tmp/inputfile.txt`
do
echo $i
cd /opt/app/app
if [[ $i =~ [0-9] ]]; then
mkdir -p ${i%/*}
else
mkdir -p $i
fi
done
The substitution cuts off everything after the last / so the date is gone.
However if you just want all the ones without numbers then you could do:
for i in `cat /tmp/inputfile.txt`
do
echo $i
cd /opt/app/app
if [[ $i =~ [0-9] ]]; then
:
else
mkdir -p $i
fi
done
Output of the second version:
data/app_rt_ws/RTWS
data/app_rt_ws/SDP
I hope this is what you looked for :)

.zshrc unrecognized condition on $-

I'm attempting to port over some functionality from my old .bashrc into my .zshrc and I'm having trouble with a condition that worked in bash.
Whenever I remote log in to my computer, I had bash check the $- variable to see if it was interactive. If it was, I would start up an emacs server if one wasn't already running and change to my code directory. Otherwise (if I was getting a file with scp, for example), I wouldn't do anything.
Here's the bit of code:
if [[ $- -regex-match "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
And here's the error zsh gives me: .zshrc:125: unrecognized condition:$-'`
Does anyone know how to get around this error when using $- ? I've tried quoting it, wrapping it in $(echo $-) but none have worked. Thanks in advance.
Edit: If I switch my code to:
if [[ $- =~ "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
I now get: .zshrc:125: condition expected: =~ I'm not sure exactly what zsh is interpreting incorrectly here as I'm not very familiar with the semantics of zsh's shell scripts. Could someone point me in the right direction on how to express this condition in zsh?
In zsh, you don't need to bother with $-, which is--I think--intended primarily for POSIX compatibility.
if [[ -o INTERACTIVE ]]; then
if ps -u myusername | grep -q emacs; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
-regex-match is only available if tho module zsh/regex (man 1 zshmodules) is loaded. (The error message depends on the version: I get zsh: unknown condition: -regex-match if it is not loaded on 4.3.17, but zsh:1: unknown condition: -$- on 4.3.10).
You can try [[ $- =~ "i" ]] which is not dependend on additional modules.

How to determine if a specific module is loaded in linux kernel

I am just curious is there any way to determine if a particular module is loaded/installed.
$ lsmod lists all modules (device driver loaded).
Is there any way to check or a command that returns true/false boolean output if a module name is polled. For eg. if keyboard.o exists return true else false. I need this tip to complete my driver auto refresh program.
PS: tried modinfo. I am using busybox client in my test DUT so can you give some alternatives other than modinfo?
The modinfo module method does not work well for me. I prefer this method that is similar to the alternative method proposed:
#!/bin/sh
MODULE="$1"
if lsmod | grep -wq "$MODULE"; then
echo "$MODULE is loaded!"
exit 0
else
echo "$MODULE is not loaded!"
exit 1
fi
not sure if modinfo modname and checking $? will work for you, just a suggestion.
/tmp$ sudo modinfo e1000
/tmp$ echo $?
0
/tmp$ sudo modinfo keyboard
ERROR: modinfo: could not find module keyboard
/tmp$ echo $?
1
alternatively you also grep /proc/modules
The --first-time flag causes modprobe to fail if the module is already loaded. That in conjunction with the --dry-run (or the shorthand -n) flag makes a nice test:
modprobe -n --first-time $MODULE && echo "Not loaded" || echo "Loaded"
Edit 1: As #Nobody pointed out this also prints Loaded if the module does not exist. We can fix this by combining it with modinfo:
modinfo $MODULE >/dev/null 2>/dev/null &&
! modprobe -n --first-time $MODULE 2>/dev/null &&
echo "Loaded" || echo "Not loaded"
Edit 2: On some systems modprobe lives in /usr/sbin, which is not in the $PATH unless you are root. In that case you have to substitute modprobe for /usr/sbin/modprobe in the above.
I wrote this:
MODULE=snd_aloop # for example
test -n "$(grep -e "^$MODULE " /proc/modules)" && echo "Loaded" || echo "Not loaded"
It checks in /proc/modules. If the module is mentioned there, it's assumed to be loaded, otherwise not.
The others seemed too long to me (the other short one requires root, this does not). Of course it's just written out what was already mentioned as "alternatives".
Caution: modprobe accepts some variants of module names other than the primary listed in /proc/modules. For example loading snd-aloop works, but the module is named snd_aloop and is listed as such in /proc/modules and when using rmmod that's also the only name that will work.
My short way to find if a given module is actually loaded:
cat /proc/modules | grep -c nfnetlink
which outputs
2
That 2 (TWO) means the module is LOADED. The actual output without -c shows all loaded modules with MODULENAME - -c counts the lines that contain MODULENAME. So if you have 0 (ZERO) lines as output then the module is not loaded
The better idea is to create a bash function:
#!/bin/sh
function moduleExist(){
MODULE="$1"
if lsmod | grep "$MODULE" &> /dev/null ; then
return 0
else
return 1
fi
}
if moduleExist "module name"; then
#do somthing
fi
!/bin/sh
# Module
MODULE="scsi_dh_rdac"
#Variables check if module loaded or not
MODEXIST=/sbin/lsmod | grep "$MODULE"
if [ -z "$MODEXIST" ]; then
/sbin/modprobe "$MODULE" >/dev/null 2>&1
fi
module list
Returns:
Currently Loaded Modulefiles:
1) /coverm/0.3.0 2) /parallel/20180222
grep -wEq "^${module%.o}" /proc/modules
returns true (e.g. can be used in an if) whether you ask for keyboard or keyboard.o
grep -q $pattern against lsmod or /proc/modules, which are available on most systems and a standard "source of truth"
lsmod | grep -q $pattern
$ lsmod | grep -q msr
$ echo $?
0
$ lsmod | grep -q duediligencemuch
$ echo $?
1

Resources