Løsningsforslag til eksamen høst 2003, Operativsystemer og UNIX
OBS! Ikke korrekturlest; muligheten for trykkfeil er foreløpig stor......

Oppgave 1

a) cd /usr/bin

b) cp * ~/www # Kataloger blir da utelatt

c) echo $PATH

d) traceroute gnu.org

e) /usr/bin/emacs

f) /etc/alternatives/emacs # Awk splitter på mellomrom, $NF er siste element

g) Dette har å gjøre med i hvilken rekkefølge bash ekspanderer ~ og variabler og at doble apostrofer gjør at ekspandering av ~ hoppes over. Shellet substituerer verdien til en variabel etter at det substituerer hjemmekatalogen for ~. Dermed utføres cd '~/deleted' og det finnes ikke noen katalog som begynner med ASCII-tegnet ~. Man kan istedet sette:

dir=~/deleted # Her substitueres ~ med hjemmekatalogen
$ echo $dir
/iu/nexus/ud/haugerud/deleted
$ cd $dir
og da går det som ønsket. Et alternativ er
$  dir="~/deleted"
$ eval cd $dir
eval sender sine argumenter gjennom en evalueringsrunde og resultatet, cd ~/deleted sendes til bash for evaluering og da blir ~ ekspandert.

Oppgave 2

a)

#! /bin/bash

if [ $# -ne 1 ]
then
        echo "Gi ett argument"
        exit
fi

prog=$1
IFS=:
for dir in $PATH
do
   if [ -x $dir/$prog ]
   then
        echo "$dir/$prog"
        exit
   fi
done

b)

#! /bin/bash
link=$1
dypere="true"
while [ $dypere ]
do
   if [ -L $link ]
   then
      dir=`dirname $link`
      base=`basename $link`
      cd $dir               # I fall linken er gitt med relativ path
      ls -l `pwd`/$base
      link=`ls -l $base | awk '{print $NF}'` # Alt. for-løkke gjennom ls-output
   else
      dypere=""             # Nå er det ikke flere linker
   fi
done

if [ -f $link ] # Hvis det er en katalog er scriptet ferdig allerede
then
      dir=`dirname $link`
      base=`basename $link`
      cd $dir
      ls -l `pwd`/$base
fi

c)

#! /bin/bash

if [ $# -ne 1 ]
then
        echo "Gi ett argument"
        exit
fi

prog=`where $1`
if [ $prog ]
then
    delink $prog
else
    echo "$1 er ikke i PATH ($PATH)"
fi

Oppgave 3

a) Et kritisk avsnitt er kode som må fullføres av prosessen som utfører den uten at andre prosesser bruker samme felles ressurs.

b) En semafor er et heltall S som signaliserer om en ressurs er tilgjengelig. Verdien på semaforen viser om den er ledig eller i bruk og eventuelt hvor mange som venter i kø.

c) Semaforen kan ha verdiene S = 1, 0, -1 og -2. Hvis alle de tre prosessene gjør et wait-kall før den som gjorde det først har kaldt signal, vil S minke med 1 for hvert kall og ende på -2.

d) nice kan brukes til å senke prosessens egen prioritet. Antall ticks som deles ut før hver epoke blir da færre og prosessen kjører kortere enn de andre prosessene hver gang det er dens tur i Round Robin køen.

e) HUB'en sender alle pakkene til alle maskinene i nettet og du kan dermed lese trafikk til naboen. Applikasjonene ftp og telnet sender passord i klartekst og du kan lese disse. ssh derimot, krypterer alle data som sendes og du kan ikke lese naboens passord i dette tilfellet.

f) En switch sender normalt kun data til den maskinen som har den MAC-adressen som står på pakken. Derfor vil du ikke kunne se noe av naboens trafikk. Det finnes metoder for å lure en switch til å sende deg pakkene likevel, så helt sikker kan naboen likevel ikke være.

g) Ja. IP-adressen står i IP-headeren og er med hele veien helt til mottageren.

h) Nei. Pakkene går via en gateway og den vil sette på MAC-adressen til det nettverkskortet den er koblet til nexus sitt nettverk med.

i) cadeler30-gw.uninett.no er gatewayen eller routeren som er bindeleddet mellom cubes og nexus' nettverk.

Oppgave 4

a)

sub writeLog()
  {
    my $info = $_[0];
    my $LOGFILE = "honeypot.log";
    my $date = localtime();
    open (LOG,">>$LOGFILE");
    print LOG "$date $info\n";
    close(LOG);
  }

b)

sub getServiceNames()
  {
    my $min = $_[0];
    my $max = $_[1];
    my @services;
    open(SERV,"/usr/bin/lynx -source http://www.iana.org/assignments/port-numbers | ");
    while($line = <SERV>)
      {
        if($line =~ m/^(.*?)\s+(\d+)\/tcp\s+(.*?)$/)
          {
            if($2 >= $min and $2 <= $max)
              {
                $comment = $3;
                chop($comment);
                $services[$2] = "$1 ($comment)";
              }
          }
      }
    close(SERV);
    return(@services);
  }

Oppgave 5

#! /bin/perl

use IO::Socket::INET;
$min = 1025;
$max = 1027;
@services = getServiceNames($min,$max);

print "Starting servers on TCP-ports\n\n";

for($port = $min;$port <= $max;$port++)
  {
      print "Forking for port $port\n";
      $pid = fork();
      if($pid == 0)
      {
          if($server = IO::Socket::INET->new(LocalPort => $port,
                                Reuse    => 1,
                                Listen   => 1))
          {
              print "Listens at TCP-port $port $services[$port]\n";
              $BUFFSIZE = 1000;
              while("true")
              {
                  $client = $server->accept;
                  $host   = $client->peerhost();
                  $info = "Connection at TCP-port $port ($services[$port]) from $host. ";
                  $client->recv($buffer,$BUFFSIZE,"0");
                  $client->close;
                  writeLog("$info $buffer");
              }
          }
          else
          {
              warn "Can't start tcp-server at port $port ($!)\n";
          }
          exit(); # exit of child
      }
  }
Om man skal lytte på 1000 porter, vil fork-metoden ta for mye ressurser siden den starter en ny prosess for hver port og på de fleste systemer ikke være overkommelig. En fordel med fork-metoden, er at ikke alle port-lytterene crasher om en av dem skulle crashe.

Hårek Haugerud 2003-12-12