0

I am working on a script that detects CDP information from the network card. The script currently works on my computer, but i would like to make it available for other people. The script currently runs because in the code it has the name of my network card. I would like to make it ask for the network card name (perhaps list the ones available) before running the script. My code is:

#!/usr/bin/awk -f

function red(s) {
    printf "\033[1;31m" s "\033[0m "
}

function green(s) {
     printf "\033[1;32m" s "\033[0m "
}

function blue(s) {
    printf "\033[1;34m" s "\033[0m "
}

BEGIN{

cmd = "tcpdump -nvi enp0s25 -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1"
while ((cmd | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")

for(i=1;i<=length(s);i++){
    if ($0 ~ s[i] && s[i]){

            if (i==1){            
            print "\n"; 
            print red("Device Name: ") green($7);
            }   

            else if (i==2){                          
            print red("Software Version: ") green($0) ;
                }

            else if (i==3){                      /*Port*/
            print red($1 ": ") green($7);
                }
        else if (i==4){                             
            print red($1 " " $2 " " $3 ": ") green($9);
                }

            else if (i==5){                             
            print red("IP Address: ") green($9);
                }

        else if (i==6){                                 
            print red("VLAN: ") green($9);
                }

        else if (i==7){                                
            print red("DUPLEX: ") green($7);
                }

            else if (i==8){                                 
            print red("Voice VLAN: ") green($13);
                }

        else{ 
                s[i]=0;print "   "}
                }  
            }
        }
}       

As you can see, it runs the command with my NIC which is enp0s25. I need to make this a variable, that is entered by the user (maybe only once). the best approach would be to enumerate the cards and have the user pick the card he wants using a number. I have NO IDEA how to do this.

2
  • 1
    Why are you bypassing awks normal mode of operation (e.g. tcpdump args | awk 'script') and hard-coding a getline loop instead? Commented Jul 20, 2017 at 12:52
  • 1
    I'll come back to your actual question later, but you're using printf wrong: if the string contains % sequences, you'll get an error. You need to keep the parameter out of the format string. I would do function colorize(s, n) { printf "\033[1;%dm%s\033[0m ", n, s } then function red(s) {colorize(s, 31)}, etc Commented Jul 20, 2017 at 13:03

2 Answers 2

1

You're making life harder for youself by trying to use awk as a shell by encoding the call to tcpdump inside awk. Think about that - you're writing a shell script to call awk to call shell to call tcpdump instead of just having shell call tcpdump and pipe the output to awk.

Just write your shell script as:

tcpdump ... enp0s25 ... | awk 'script'

and then you can tweak it in the obvious way:

echo "enter a nic: "
IFS= read -r nic
tcpdump ... "$nic" ... | awk 'script'
Sign up to request clarification or add additional context in comments.

Comments

0
#!/usr/bin/awk -f 

function red(s) {
printf "\033[1;31m" s "\033[0m "
 }

function green(s) {
printf "\033[1;32m" s "\033[0m "
}

function blue(s) {
  printf "\033[1;34m" s "\033[0m "
 }

 function detectNic( ) {
    printf "Enter the Ethernet card to listen or press enter to listen 
         to Default:";getline nic<"/dev/tty"
      if (nic == ""){

        command = "cat /var/defaultnic"

        nic = command | getline
    print "Default network card to listen: " $nic       
    return $nic

        }
    else{   
    return nic
    }

 }
BEGIN{

nic = detectNic();
cmd = "tcpdump -nv -s 1500 ether dst 01:00:0c:cc:cc:cc -c 1 -i"

while ((cmd nic | getline) > 0) {
str="Device-ID:Cisco IOS Software:Port-ID:VTP:Address:VLAN:Duplex:VoIP:"
split(str,s,":")

for(i=1;i<=length(s);i++){
    if ($0 ~ s[i] && s[i]){

    #DEVICE ID
            if (i==1){            
            print "\n"; 
            print red("Device Name: ") green($7);
            }   

#SOFTWARE VERSION      
            else if (i==2){                          
            print red("Software Version: ") green($0) ;
                }

 #PORT      
            else if (i==3){                      
            print red($1 ": ") green($7);
                }
     #VTP DOMAIN    
        else if (i==4){                             
            print red($1 " " $2 " " $3 ": ") green($9);
                }

     #IP ADDRESS
            else if (i==5){                             
            print red("IP Address: ") green($9);
                }

    #CURRENT VLAN     
        else if (i==6){                                 
            print red("VLAN: ") green($9);
                }

       #DUPLEX
        else if (i==7){                                
            print red("DUPLEX: ") green($7);
                }

      #VOICE VLAN
            else if (i==8){                                 
            print red("Voice VLAN: ") green($13);
                }

        else{ 
                s[i]=0;print "   "}
                }  
            }
        }
}       

1 Comment

nic = command | getline; return $nic sets nic to the result status of (i.e. NOT the value detected by) the getline call (-1, 0, or 1) and then returns the field or record at that position ($-1, or $0, or $1). Probably not what you're trying to do. And catting the file to a pipe to getline instead of just reading the file with getline like you did a couple of lines earlier (getline nic<"/dev/tty") doesn't make sense. Check for errors on the getline calls to avoid obscure, silent failures. See awk.freeshell.org/AllAboutGetline. Finally - don't do it this way at all, awk is not shell

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.