\documentclass{ictlab}

% Copyright (c) 2003 by Nick Urbanik <nicku(at)nicku.org>.
% This material may be distributed only subject to the terms and
% conditions set forth in the Open Publication License, v1.0 or later
% (the latest version is presently available at
% http://www.opencontent.org/openpub/).

\RCS $Revision: 1.1 $

\usepackage{verbatim,alltt,key,biganswerbox}
\usepackage[hang,bf,nooneline]{caption2}
\ifx\pdftexversion\undefined \else
  \usepackage[pdfpagemode=None,pdfauthor={Nick Urbanik}]{hyperref}
\fi

%\externaldocument[s3-]{../../lectures/snmp-v3/snmp-v3}

\newcommand*{\labTitle}{Perl Net::SNMP, and more on VACM and USM}
\providecommand*{\SNMP}{\acro{SNMP}\xspace}
\providecommand*{\MIB}{\acro{MIB}\xspace}
\providecommand*{\ID}{\acro{ID}\xspace}
\providecommand*{\OID}{\acro{OID}\xspace}
\providecommand*{\USM}{\acro{USM}\xspace}
\providecommand*{\VACM}{\acro{VACM}\xspace}
\renewcommand{\floatpagefraction}{0.75} % default is .5, to increase
% density.
\renewcommand*{\bottomfraction}{0.6} % default is 0.3
\renewcommand*{\topfraction}{0.85} % default is 0.7
\renewcommand*{\textfraction}{0.1} % default is 0.2


\begin{document}

\section{Aims}
\label{sec:aims}

The main aims of the activities today are:
\begin{itemize}
\item To understand how to write a Perl program to retrieve simple
  values from an \SNMP agent, using:
  \begin{itemize}
  \item a community security model
  \item the \USM security model
  \end{itemize}
\item To understand \VACM and \SNMP access control more fully through
  discussion
\end{itemize}


\newlength{\BW}
\setlength{\BW}{50mm}

\section{Questions about VACM for Discussion}
\label{sec:questions-for-discussion}

\RFC 3415 describes the view obtained when using a \emph{family
    mask} as a \emph{family of view subtrees}.
\begin{enumerate}
\item \label{que:family-of-view-subtrees}Why do the authors of the
  standard use the term \emph{family of view subtrees}?
  \begin{biganswerbox}[\BW]%
    \begin{solution}
      A view using a family mask, such as that given in the next
      question, is equivalent to a set of subtrees, one for each
      element in the row, i.e., one for each column in the row.  They
      all have a similar format, so they can be expressed with one
      structure represented by one subtree and a \emph{family mask}.

      In the example shown in
      question~\ref{que:example-of-family-of-view-subtrees}, there are
      22 columns in the table, so that the family of view subtrees
      represents 22 subtrees, each containing one element, i.e., one
      \MIB variable.
    \end{solution}
  \end{biganswerbox}
    
  \bigskip

  \begin{flushright}
    \textbf{Questions are continued on the next page\ldots}
  \end{flushright}
\clearpage
\item \label{que:example-of-family-of-view-subtrees}Illustrate your
  answer to question~\ref{que:family-of-view-subtrees} by creating a
  view \emph{without using a family mask} equivalent to that given by
  the following Net-\SNMP \texttt{view} statement:
\begin{verbatim}
view view1 included IF-MIB::ifIndex.4 ff.a0
\end{verbatim}
  \begin{biganswerbox}[2.8\BW]%
  %\begin{biganswerbox}[1.8\BW]%
    \begin{solution}
\begin{alltt}
view view1 included IF-MIB::ifIndex.4
view view1 included IF-MIB::ifDescr.4
view view1 included IF-MIB::ifType.4
view view1 included IF-MIB::ifMtu.4
view view1 included IF-MIB::ifSpeed.4
view view1 included IF-MIB::ifPhysAddress.4
view view1 included IF-MIB::ifAdminStatus.4
view view1 included IF-MIB::ifOperStatus.4
view view1 included IF-MIB::ifLastChange.4
view view1 included IF-MIB::ifInOctets.4
view view1 included IF-MIB::ifInUcastPkts.4
view view1 included IF-MIB::ifInNUcastPkts.4
view view1 included IF-MIB::ifInDiscards.4
view view1 included IF-MIB::ifInErrors.4
view view1 included IF-MIB::ifInUnknownProtos.4
view view1 included IF-MIB::ifOutOctets.4
view view1 included IF-MIB::ifOutUcastPkts.4
view view1 included IF-MIB::ifOutNUcastPkts.4
view view1 included IF-MIB::ifOutDiscards.4
view view1 included IF-MIB::ifOutErrors.4
view view1 included IF-MIB::ifOutQLen.4
view view1 included IF-MIB::ifSpecific.4
\end{alltt}
Here is a command line that will print this answer:
\begin{alltt}
$ \textbf{for ((i=1; i <= 22; ++i)); do \bs
snmptranslate .1.3.6.1.2.1.2.2.1.$i.4 |
sed 's/^/view view1 included /'; done}
\end{alltt}
% for ((i=1; i <= 22; ++i)); do snmptranslate .1.3.6.1.2.1.2.2.1.$i.4 |
% sed 's/^/view view1 included /'; done
    \end{solution}
  \end{biganswerbox}
\end{enumerate}

\section{Procedure}
\label{sec:procedure}
Refer to the lecture notes about \texttt{Net::SNMP} while doing this
activity.  Refer also to the manual for \texttt{Net::SNMP}, which
contains many examples.
\begin{enumerate}
\item Configure \CPAN (you only need do this once):
  \begin{enumerate}
  \item 
\begin{alltt}
$ \textbf{sudo perl -MCPAN -e shell}
\end{alltt}%$
\item The shell will begin its interactive configuration process.
  Accept all defaults by pressing \key{Enter}, \textbf{\emph{except
      for the following}}:
  \begin{itemize}
  \item When prompted ``\texttt{CPAN build and cache directory?}''
    enter: \texttt{/var/cache/cpan} \ Do not accept the default in
    your home directory; it will not work, since the \texttt{root}
    user has no right to write to your \acro{NFS} mounted home
    directory.
  \item When asked to choose a Policy on building prerequisites,
  choose ``\texttt{follow}'':
\begin{alltt}
Policy on building prerequisites (follow, ask or ignore)? [ask] \textbf{follow}
\end{alltt}
  \begin{explanation}
    Some Perl modules depend on others.  When installing a module that
    depends on others, a selection of ``\texttt{ask}'' here means the
    \CPAN shell will prompt you and require you to press \key{Enter}
    to install the prerequisite module.  The selection
    ``\texttt{follow}'' means, ``Don't ask me; just go ahead, download
    and install any modules that are needed to install this one''.
  \end{explanation}

  \item For ``\texttt{Your http\_proxy?}'' enter
    \texttt{http://hqproxy.vtc.edu.hk:8080/}

  \item When asked to pick a nearby continent, enter \texttt{5} to
    select \texttt{(5) North America}
  \item When asked to ``\texttt{Select your country}'', enter \texttt{3}
    to select \texttt{(3) United States}.
  \item When asked ``\texttt{Select as many URLs as you like}'', I
    suggest just enter the first few numbers (corresponding to the
    first few \URL{}s); I put ``\texttt{1 2 3 4 5 6 7}''.  The numbers
    are just separated by spaces.
  \end{itemize}
\end{enumerate}
\item Install \texttt{Net::SNMP} using \CPAN, as described in the
  notes, with:
\begin{alltt}
cpan> install Net::SNMP Net::SNMP::Interfaces Net::SNMP::HostInfo
\end{alltt}
\item Write a program to read outgoing network traffic from your
  loopback network interface, and print it as a single number of
  bytes.
  \begin{solution}
    \par\medskip\par%
\begin{verbatim}
#! /usr/bin/perl

use strict;
use Net::SNMP;
my ($session, $error) = Net::SNMP->session(
                                           -hostname  => shift || 'localhost',
                                           -community => shift || 'public',
                                           -port      => shift || 161
                                          );

if (!defined($session)) {
    printf("ERROR: %s.\n", $error);
    exit 1;
}

my $ifOutOctets = '.1.3.6.1.2.1.2.2.1.16';
my $loopback_instance = '.1';
my $loopback_if_out = $ifOutOctets . $loopback_instance;
my $sysUpTime = '1.3.6.1.2.1.1.3.0';
my $result = $session->get_request(
                                   -varbindlist => [ $loopback_if_out ]
                                  );

if (!defined($result)) {
    printf("ERROR: %s.\n", $session->error);
    $session->close;
    exit 1;
}
printf("bytes output from loopback interface for host '%s' is %s\n",
       $session->hostname, $result->{$loopback_if_out}
      );

$session->close;
exit 0;
\end{verbatim}%$
  \end{solution}
\item Verify that the number given matches that read using
  \path{/sbin/ifconfig}, and making an \SNMP query using
  \texttt{snmpget}.
  \begin{solution}
    /par/medskip/par%
    We can compare the output with \texttt{/sbin/ifconfig} or with
    \texttt{/sbin/ip -s link show lo}.  Here we run them one after teh
    other to try to get readings that are made close together:
\begin{alltt}
$ \textbf{ip -s link ls lo;./snmpget-loopback-bytes}
1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    RX: bytes  packets  errors  dropped overrun mcast
    2024216    19758    0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    2024216    19758    0       0       0       0
bytes output from loopback interface for host 'localhost' is 2024287
\end{alltt}%$
Okay, let's do it again with \texttt{ifconfig}:
\begin{alltt}
$ \textbf{ifconfig lo;./snmpget-loopback-bytes}
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:20581 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20581 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2094493 (1.9 Mb)  TX bytes:2094493 (1.9 Mb)

bytes output from loopback interface for host 'localhost' is 2094564
\end{alltt}%$
They match closely enough.  A more accurate measurement would
calculate the rate of network traffic, and use accurate time
measurements to compare the results.
  \end{solution}
\item Ensure that your agent is properly configured with at least one
  \USM account, as required by the \SNMP{}v3 tutorial.
  \begin{solution}
    /par/medskip/par%
    This is all covered in detail in the solutions to the tutorial.
    Make sure you read it, and try it out yourself.
  \end{solution}
\item Write a second program to read outgoing network traffic on the
  loopback network interface using \USM.  Again, verify that the
  output of your program is consistent with other ways of obtaining
  the same information.
  \begin{solution}
    /par/medskip/par%
    Note that this program assumes that the \USM user \textbf{usera}
    was created exactly as I showed in the solution to the \SNMP{}v3
    tutorial.
\begin{verbatim}
#! /usr/bin/perl

use strict;
use Net::SNMP;
my ($session, $error) = Net::SNMP->session(
                                           -authpassword => shift
                                                            || 'my_password1',
                                           -hostname  => shift || 'localhost',
                                           -username  => shift || 'usera',
                                           -version   => 'snmpv3',
                                          );

if (!defined($session)) {
    printf("ERROR: %s.\n", $error);
    exit 1;
}

my $ifOutOctets = '.1.3.6.1.2.1.2.2.1.16';
my $loopback_instance = '.1';
my $loopback_if_out = $ifOutOctets . $loopback_instance;
my $sysUpTime = '1.3.6.1.2.1.1.3.0';
my $result = $session->get_request(
                                   -varbindlist => [ $loopback_if_out ]
                                  );

if (!defined($result)) {
    printf("ERROR: %s.\n", $session->error);
    $session->close;
    exit 1;
}
printf("bytes output from loopback interface for host '%s' is %s\n",
       $session->hostname, $result->{$loopback_if_out}
      );

$session->close;
exit 0;
\end{verbatim}%$
We can check it in the same way as before:
\begin{alltt}
$ \textbf{ip -s link ls lo;./snmpget-loopback-bytes-usm}
1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    RX: bytes  packets  errors  dropped overrun mcast
    2098022    20629    0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    2098022    20629    0       0       0       0
bytes output from loopback interface for host 'localhost' is 2098667
\end{alltt}%$
  \end{solution}
\end{enumerate}

\end{document}
