Bug 123255

Summary: mistake in ng_bpf(4) manpage
Product: Documentation Reporter: Eugenio Maffione <eugenio.maffione>
Component: Books & ArticlesAssignee: Giorgos Keramidas <keramida>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Latest   
Hardware: Any   
OS: Any   

Description Eugenio Maffione 2008-04-30 12:50:01 UTC
I'm writing to you because I think to have found a little mistake in the ng_bpf man page.

Actually the mistake is in the script proposed in the manpage.

I notice that in some cases the statement 
printf " { code=%d jt=%d jf=%d k=%d }", \$1, \$2, \$3, \$4; 
causes an incorrect programming of the bpf filter.

This happens when the "k" value exceed the MAX_INTEGER value as when, for example, the tcpdump expression refers a network where the the first octect is greater than 128.

In that case the awk generates a negative value for "k" and the bpf matches always (I don't understand why, but it happens).

Fix: 

I tried to change the printf statement changing the format for using a conversion to unsigned (%u) but  the poor result is to have the absolute value of "k" (so just deleting the minus) [this probably is a problem in awk].

Finallly, I've found that the working one format for the printg in the manpage is " { code=%d jt=%d jf=%d k=%s }" that preserves the right unsigned integer values.

Hopefully  this help some other novice...
How-To-Repeat: This happens when the "k" value exceed the MAX_INTEGER value as when, for example, the tcpdump expression refers a network where the the first octect is greater than 128. (e.g . PATTERN="udp and dst net 255.255.0.0/16")
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2008-04-30 15:21:59 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-doc

reclassify.
Comment 2 Giorgos Keramidas freebsd_committer freebsd_triage 2008-07-30 05:14:30 UTC
On Wed, 30 Apr 2008 11:41:57 GMT, Eugenio Maffione <eugenio.maffione@telecomitalia.it> wrote:
> I'm writing to you because I think to have found a little mistake in
> the ng_bpf man page.
>
> Actually the mistake is in the script proposed in the manpage.

Good catch :)

> I notice that in some cases the statement
> printf " { code=%d jt=%d jf=%d k=%d }", \$1, \$2, \$3, \$4;
> causes an incorrect programming of the bpf filter.
>
> This happens when the "k" value exceed the MAX_INTEGER value as when,
> for example, the tcpdump expression refers a network where the the
> first octect is greater than 128.
>
> In that case the awk generates a negative value for "k" and the bpf
> matches always (I don't understand why, but it happens).

ACK.  I can reproduce this here.

> This happens when the "k" value exceed the MAX_INTEGER value as when,
> for example, the tcpdump expression refers a network where the the
> first octect is greater than 128. (e.g . PATTERN="udp and dst net
> 255.255.0.0/16")

We don't really need awk for that.  A simple shell script will also do:

: $ sudo tcpdump -s 8192 -ddd "udp and dst net 255.255.0.0/16" | \
:     ( read len ; \
:       echo "bpf_prog_len=$len" ; \
:       echo "bpf_prog=[" ; \
:       while read code jt jf k ; do \
:           echo "{ code=$code jt=$jt jf=$jf k=$k }" ; \
:       done ; \
:       echo "]" )

This yields:

: bpf_prog_len=10
: bpf_prog=[
: { code=40 jt=0 jf=0 k=12 }
: { code=21 jt=7 jf=0 k=34525 }
: { code=21 jt=0 jf=6 k=2048 }
: { code=48 jt=0 jf=0 k=23 }
: { code=21 jt=0 jf=4 k=17 }
: { code=32 jt=0 jf=0 k=30 }
: { code=84 jt=0 jf=0 k=4294901760 }
: { code=21 jt=0 jf=1 k=4294901760 }
: { code=6 jt=0 jf=0 k=8192 }
: { code=6 jt=0 jf=0 k=0 }
: ]

I'll replace the awk version with the shell code, if there are no
objections in the next few days.

Thank you for reporting what you noticed, and the for excellent analysis
of why it happens :-)
Comment 3 Giorgos Keramidas freebsd_committer freebsd_triage 2008-07-30 05:14:47 UTC
State Changed
From-To: open->analyzed

I'll handle this. 


Comment 4 Giorgos Keramidas freebsd_committer freebsd_triage 2008-07-30 05:14:47 UTC
Responsible Changed
From-To: freebsd-doc->keramida
Comment 5 Giorgos Keramidas freebsd_committer freebsd_triage 2009-01-30 19:33:17 UTC
State Changed
From-To: analyzed->patched

Fixed in head.  I will merge the new example to the stable/6 
and stable/7 branches in a few days.
Comment 6 dfilter service freebsd_committer freebsd_triage 2009-01-30 19:33:22 UTC
Author: keramida (doc committer)
Date: Fri Jan 30 19:33:04 2009
New Revision: 187935
URL: http://svn.freebsd.org/changeset/base/187935

Log:
  Sometimes, depending on the bpf filter rules used in $PATTERN,
  the example script of the manpage feeds awk(1) with values larger
  than UINT32_MAX.  Then awk prints a negative value, and this
  messes up $BPFPROG.  Trying to load the resulting bpf byte codes
  with ngctl then fails.
  
  For example, the output for PATTERN="udp and dst net 255.255.0.0/16"
  should be (all in one line):
  
      bpf_prog_len=10
      bpf_prog=[
        { code=40 jt=0 jf=0 k=12 }
        { code=21 jt=7 jf=0 k=34525 }
        { code=21 jt=0 jf=6 k=2048 }
        { code=48 jt=0 jf=0 k=23 }
        { code=21 jt=0 jf=4 k=17 }
        { code=32 jt=0 jf=0 k=30 }
        { code=84 jt=0 jf=0 k=4294901760 }
        { code=21 jt=0 jf=1 k=4294901760 }
        { code=6 jt=0 jf=0 k=8192 }
        { code=6 jt=0 jf=0 k=0 }
      ]
  
  The two k=4294901760 values are displayed as k=-2147483648 by awk.
  
  Replace the awk script of the manpage example with a slower but
  safer version, that doesn't really attempt to convert the byte
  code printed by tcpdump from string to number and back.
  
  PR:		docs/123255
  Submitted by:	Eugenio Maffione, eugenio.maffione at telecomitalia.it
  MFC after:	3 days

Modified:
  head/share/man/man4/ng_bpf.4

Modified: head/share/man/man4/ng_bpf.4
==============================================================================
--- head/share/man/man4/ng_bpf.4	Fri Jan 30 18:34:54 2009	(r187934)
+++ head/share/man/man4/ng_bpf.4	Fri Jan 30 19:33:04 2009	(r187935)
@@ -156,21 +156,14 @@ INHOOK="hook1"
 MATCHHOOK="hook2"
 NOTMATCHHOOK="hook3"
 
-cat > /tmp/bpf.awk << xxENDxx
-{
-  if (!init) {
-    printf "bpf_prog_len=%d bpf_prog=[", \\$1;
-    init=1;
-  } else {
-    printf " { code=%d jt=%d jf=%d k=%d }", \\$1, \\$2, \\$3, \\$4;
-  }
-}
-END {
-  print " ]"
-}
-xxENDxx
-
-BPFPROG=`tcpdump -s 8192 -ddd ${PATTERN} | awk -f /tmp/bpf.awk`
+BPFPROG=$( tcpdump -s 8192 -ddd ${PATTERN} | \\
+           ( read len ; \\
+             echo -n "bpf_prog_len=$len" ; \\
+             echo -n "bpf_prog=[" ; \\
+             while read code jt jf k ; do \\
+                 echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \\
+             done ; \\
+             echo " ]" ) )
 
 ngctl msg ${NODEPATH} setprogram { thisHook=\\"${INHOOK}\\" \\
   ifMatch=\\"${MATCHHOOK}\\" \\
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 7 dfilter service freebsd_committer freebsd_triage 2009-02-02 04:57:56 UTC
Author: keramida (doc committer)
Date: Mon Feb  2 04:57:36 2009
New Revision: 187999
URL: http://svn.freebsd.org/changeset/base/187999

Log:
  MFC 187935 from /head
  
  Sometimes, depending on the bpf filter rules used in $PATTERN,
  the example script of the manpage feeds awk(1) with values larger
  than UINT32_MAX.  Then awk prints a negative value, and this
  messes up $BPFPROG.  Trying to load the resulting bpf byte codes
  with ngctl then fails.
  
  For example, the output for PATTERN="udp and dst net 255.255.0.0/16"
  should be (all in one line):
  
      bpf_prog_len=10
      bpf_prog=[
        { code=40 jt=0 jf=0 k=12 }
        { code=21 jt=7 jf=0 k=34525 }
        { code=21 jt=0 jf=6 k=2048 }
        { code=48 jt=0 jf=0 k=23 }
        { code=21 jt=0 jf=4 k=17 }
        { code=32 jt=0 jf=0 k=30 }
        { code=84 jt=0 jf=0 k=4294901760 }
        { code=21 jt=0 jf=1 k=4294901760 }
        { code=6 jt=0 jf=0 k=8192 }
        { code=6 jt=0 jf=0 k=0 }
      ]
  
  The two k=4294901760 values are displayed as k=-2147483648 by awk.
  
  Replace the awk script of the manpage example with a slower but
  safer version, that doesn't really attempt to convert the byte
  code printed by tcpdump from string to number and back.
  
  PR:           docs/123255
  Submitted by: Eugenio Maffione, eugenio.maffione at telecomitalia.it

Modified:
  stable/7/share/man/man4/   (props changed)
  stable/7/share/man/man4/igb.4   (props changed)
  stable/7/share/man/man4/ng_bpf.4

Modified: stable/7/share/man/man4/ng_bpf.4
==============================================================================
--- stable/7/share/man/man4/ng_bpf.4	Mon Feb  2 04:53:39 2009	(r187998)
+++ stable/7/share/man/man4/ng_bpf.4	Mon Feb  2 04:57:36 2009	(r187999)
@@ -156,21 +156,14 @@ INHOOK="hook1"
 MATCHHOOK="hook2"
 NOTMATCHHOOK="hook3"
 
-cat > /tmp/bpf.awk << xxENDxx
-{
-  if (!init) {
-    printf "bpf_prog_len=%d bpf_prog=[", \\$1;
-    init=1;
-  } else {
-    printf " { code=%d jt=%d jf=%d k=%d }", \\$1, \\$2, \\$3, \\$4;
-  }
-}
-END {
-  print " ]"
-}
-xxENDxx
-
-BPFPROG=`tcpdump -s 8192 -ddd ${PATTERN} | awk -f /tmp/bpf.awk`
+BPFPROG=$( tcpdump -s 8192 -ddd ${PATTERN} | \\
+           ( read len ; \\
+             echo -n "bpf_prog_len=$len" ; \\
+             echo -n "bpf_prog=[" ; \\
+             while read code jt jf k ; do \\
+                 echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \\
+             done ; \\
+             echo " ]" ) )
 
 ngctl msg ${NODEPATH} setprogram { thisHook=\\"${INHOOK}\\" \\
   ifMatch=\\"${MATCHHOOK}\\" \\
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 8 dfilter service freebsd_committer freebsd_triage 2009-02-02 04:59:21 UTC
Author: keramida (doc committer)
Date: Mon Feb  2 04:59:00 2009
New Revision: 188000
URL: http://svn.freebsd.org/changeset/base/188000

Log:
  MFC 187935 from /head
  
  Sometimes, depending on the bpf filter rules used in $PATTERN,
  the example script of the manpage feeds awk(1) with values larger
  than UINT32_MAX.  Then awk prints a negative value, and this
  messes up $BPFPROG.  Trying to load the resulting bpf byte codes
  with ngctl then fails.
  
  For example, the output for PATTERN="udp and dst net 255.255.0.0/16"
  should be (all in one line):
  
      bpf_prog_len=10
      bpf_prog=[
        { code=40 jt=0 jf=0 k=12 }
        { code=21 jt=7 jf=0 k=34525 }
        { code=21 jt=0 jf=6 k=2048 }
        { code=48 jt=0 jf=0 k=23 }
        { code=21 jt=0 jf=4 k=17 }
        { code=32 jt=0 jf=0 k=30 }
        { code=84 jt=0 jf=0 k=4294901760 }
        { code=21 jt=0 jf=1 k=4294901760 }
        { code=6 jt=0 jf=0 k=8192 }
        { code=6 jt=0 jf=0 k=0 }
      ]
  
  The two k=4294901760 values are displayed as k=-2147483648 by awk.
  
  Replace the awk script of the manpage example with a slower but
  safer version, that doesn't really attempt to convert the byte
  code printed by tcpdump from string to number and back.
  
  PR:           docs/123255
  Submitted by: Eugenio Maffione, eugenio.maffione at telecomitalia.it

Modified:
  stable/6/share/man/man4/   (props changed)
  stable/6/share/man/man4/ng_bpf.4
  stable/6/share/man/man4/xl.4   (props changed)

Modified: stable/6/share/man/man4/ng_bpf.4
==============================================================================
--- stable/6/share/man/man4/ng_bpf.4	Mon Feb  2 04:57:36 2009	(r187999)
+++ stable/6/share/man/man4/ng_bpf.4	Mon Feb  2 04:59:00 2009	(r188000)
@@ -156,21 +156,14 @@ INHOOK="hook1"
 MATCHHOOK="hook2"
 NOTMATCHHOOK="hook3"
 
-cat > /tmp/bpf.awk << xxENDxx
-{
-  if (!init) {
-    printf "bpf_prog_len=%d bpf_prog=[", \\$1;
-    init=1;
-  } else {
-    printf " { code=%d jt=%d jf=%d k=%d }", \\$1, \\$2, \\$3, \\$4;
-  }
-}
-END {
-  print " ]"
-}
-xxENDxx
-
-BPFPROG=`tcpdump -s 8192 -ddd ${PATTERN} | awk -f /tmp/bpf.awk`
+BPFPROG=$( tcpdump -s 8192 -ddd ${PATTERN} | \\
+           ( read len ; \\
+             echo -n "bpf_prog_len=$len" ; \\
+             echo -n "bpf_prog=[" ; \\
+             while read code jt jf k ; do \\
+                 echo -n " { code=$code jt=$jt jf=$jf k=$k }" ; \\
+             done ; \\
+             echo " ]" ) )
 
 ngctl msg ${NODEPATH} setprogram { thisHook=\\"${INHOOK}\\" \\
   ifMatch=\\"${MATCHHOOK}\\" \\
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 9 Giorgos Keramidas freebsd_committer freebsd_triage 2009-02-02 05:00:46 UTC
State Changed
From-To: patched->closed

Thanks for submitting the original problem to Gnats, and 
for being patient while I pondered about a good way to 
solve this. 

I have merged the fix to the stable/6 [r188000] and the 
stable/7 [r187999] branches now.