Αυτό το commit περιλαμβάνεται σε:
infl00p 2022-03-23 20:14:33 +02:00
commit 8ec8e9bee2
451 αρχεία άλλαξαν με 46736 προσθήκες και 0 διαγραφές

23
content/articles/32/01_editorial.md Κανονικό αρχείο

@ -0,0 +1,23 @@
+++
title = 'Editorial'
date = '2003-06-01T00:00:00Z'
description = ''
author = 'Ιατρού Μιχάλης iatrou ατ hellug.gr(mailto:iatrou%20%C3%A1%C3%B4%20hellug.gr)'
issue = ['Magaz 32']
issue_weight = 1
+++
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*Magaz\... reloaded.*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Έχουν περάσει σχεδόν δύο χρόνια από το προηγούμενο τεύχος του Magaz.\
Εύχομαι να μην περάσουν άλλα τόσα μέχρι το επόμενο\...\
Δυστυχώς, προσωπικά δεν μπορώ να κάνω και πολλά για να υλοποιηθεί η παραπάνω ευχή: είναι στο χέρι των φίλων/αναγνωστών του Magaz να συνεχίσει η λειτουργία του
περιοδικού. Χωρίς συντάκτες (έστω και περιστασιακούς) δεν υπάρχουν άρθρα, χωρίς άρθρα δεν υπάρχει Magaz. Τόσο απλά.
Να αναφέρω, για πολλοστή φορά, ότι δεν είναι ανάγκη να είστε Linux-guru για να γράψετε ένα άρθρο, αρκεί απλά να θέλετε να μοιραστείτε μια εμπειρία σας ή κάτι
που σας προβλημάτισε και κίνησε το ενδιαφέρον σας τέλος πάντων.
Ελπίζω να απολαύσετε το τεύχος \-- και ελπίζω να μην είναι το \"τελευταίο\".

105
content/articles/32/02_msvcd.md Κανονικό αρχείο

@ -0,0 +1,105 @@
+++
title = 'Μετατροπή DivX, DVD σε Video CD στο Linux'
date = '2003-04-01T00:00:00Z'
description = ''
author = 'Nick Apostolakis(mailto:nickapos@agriroot.aua.gr)'
issue = ['Magaz 32']
issue_weight = 2
+++
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*Ένας σύντομος οδηγός για το πώς μπορείτε να μετατρέψετε video, από DivX και DVD format, σε VCD, χρησιμοποιώντας τον mplayer.*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
**1. Εισαγωγή**
---------------------------------------
**2. Τα εργαλεία**
------------------------------------------
**3. Λίγα λόγια γενικά για τον MPlayer**
----------------------------------------------------------------
**4. Τα υλικά**
---------------------------------------
**5. Η διαδικασία**
-------------------------------------------
**6. Επίλογος**
---------------------------------------
### [1. Εισαγωγή]{#s1}
Κοιτάζοντας κανείς τον παραπάνω τίτλο μπορεί να αναρωτηθεί για ποίο λόγο κάποιος να θέλει να μετατρέψει ένα video από DivX ή από DVD σε Video CD τη στιγμή που
τα 2 πρώτα έχουν σαφώς καλύτερες δυνατότητες από πλευράς ποιότητας αλλά και από πλευράς συμπίεσης (το DivX). Η απάντηση είναι απλή. Το Video CD είναι ένα
βιομηχανικό πρότυπο το οποίο έχει υλοποιηθεί σε πληθώρα οικιακών αλλά και φορητών συσκευών ενώ η επεξεργαστική ισχύς που απαιτείται είναι μικρή. Επίσης,
χρησιμοποιεί, ως μέσο αποθήκευσης, απλά CD τα οποία είναι διαθέσιμα σε όλους με μικρό κόστος. Οι άλλες λύσεις υστερούν σε αυτούς τους δύο τομείς. Τα μεν DivX
είναι κάτι που μεταβάλλεται πολύ γρήγορα και δεν είναι ανοιχτό σε όλο το κόσμο, υπάρχουν δε ελάχιστες standalone συσκευές με δυνατότητα αναπαραγωγής των αρχείων
αυτών (και μάλιστα, μόνο συγκεκριμένες εκδόσεις). Το DVD είναι μια πολύ καλή λύση, μόνο που τα εγγράψιμα DVD είναι ακόμα σε βρεφικό στάδιο.
Το εμφανές μειονέκτημά των Video CD είναι η χαμηλή ποιότητα εικόνας και ήχου που έχουν. Σε αυτό το τομέα υστερούν σαφώς έναντι των DivX αλλά και των DVD. Εδώ
όμως θα πρέπει να παρατηρήσω ότι τα VCD έχουν φτιαχτεί για να παίζουν στις χαμηλές αναλύσεις των οικιακών τηλεοράσεων και όχι σε οθόνες υπολογιστών που είναι
σαφώς ανώτερες σε ποιότητα. Έτσι, όταν το video παρακολουθείται σε τηλεόραση η διαφορά στην απόδοση σε σχέση με τις άλλες δύο τεχνολογίες είναι μικρή. Τα VCD
είναι επίσης \"προβληματικά\" και στον ήχο αφού οι δυνατότητες του φτάνουν μόνο μέχρι τον στερεοφωνικό ενώ δεν υποστηρίζουν AC3. Δυστυχώς για αυτό δεν υπάρχει
λύση.
Παρόλα τα παραπάνω, το VCD παραμένει ένα πολύ καλό ψηφιακό format το οποίο ξεπερνάει σε απόδοση και την ποιότητα της λήψης της τηλεόρασης αλλά και των
αναλογικών μέσων (VHS).
### [2. Τα εργαλεία]{#s2}
Στο Linux υπάρχουν πολλά εργαλεία με τα οποία μπορείτε να κάνετε μετατροπές video μερικά αυτά είναι DVDrip, transcode, MPlayer, DVDx. Τα τρία πρώτα είναι native
Linux προγράμματα ενώ το τελευταίο είναι ένα open source πρόγραμμα για Windows το οποίο δουλεύει πολύ καλά και σε Linux μέσω του wine. Στο κείμενα που ακολουθεί
θα αναπτύξω την χρήση του MPlayer.
### [3. Λίγα λόγια γενικά για τον MPlayer]{#s3}
Ο MPlayer αποτελεί τον ελβετικό σουγιά για video στον χώρο του Linux, με λίγα λόγια τα κάνει όλα και συμφέρει. Μπορεί να παίξει σχεδόν όλες τις γνωστές μορφές
video, να κάνει encode και capture από κάρτες τηλεόρασης, να μετατρέψει videos από την μια μορφή στην άλλη, να παίξει stream από το δίκτυο, να διορθώσει
χαλασμένα αρχεία και διάφορα άλλα. Λίγοι είναι αυτοί που μπορούν να ισχυριστούν ότι γνωρίζουν τις λειτουργίες του MPlayer σε βάθος και εγώ δεν είμαι ένας από
αυτούς. Παρακάτω θα περιγράψω μια σχετικά απλή διαδικασία με την οποία μπορούμε να μετατρέψουμε ένα οποιοδήποτε αρχείο video που μπορεί να παίξει ο MPlayer σε
mpg αρχικά και τελικά σε Video CD.
### [4. Τα υλικά]{#s4}
Χρειαζόμαστε, προφανώς, τον ίδιο τον MPlayer (τον κώδικα του). Μέσα στο πακέτο του MPlayer υπάρχει ένα shell script το οποίο ονομάζεται mencvcd και το οποίο
χρησιμοποιεί τον MPlayer καθώς και τα mjpegtools για να κάνει την μετατροπή. Το παραγόμενο mpg το μετατρέπουμε σε bin/cue iso images με το πρόγραμμα vcdimager
και το γράφουμε με το cdrdao. Τα προγράμματα αυτά μπορούμε να τα αναζητήσουμε στο http://freshmeat.net και να ακολουθήσουμε τις οδηγίες εγκατάστασης τους.
### [5. Η διαδικασία]{#s5}
Η διαδικασία είναι αρκετά απλή. Έχοντας εγκαταστήσει τα παραπάνω πακέτα, είμαστε έτοιμοι να κάνουμε τις πρώτες δοκιμές. Η λογική πίσω από το mencvcd είναι η
εξής: Το καλούμε και του δίνουμε αρχικά τις παραμέτρους για το ίδιο. Μετά ακολουθούν οι παράμετροι που χρειάζεται το MPlayer για να παίξει την ταινία. Προσοχή,
δεν δέχεται όλες τις παραμέτρους που δέχεται το MPlayer, αφού για πολλές από αυτές δεν έχει νόημα η χρήση τους. Οι βασικές παράμετροι του mencvcd είναι τρεις.
Το -vnorm, το -vfr, και το -w. Το πρώτο καθορίζει ως τι θα μεταχειριστεί το mencvcd το εισαγόμενο video και μπορεί να έχει 3 τιμές p, n, s που αντιστοιχούν σε
PAL, NTSC, SECAM. Το δεύτερο και πολύ σημαντικό δηλώνει ποίο θα είναι το frame rate του παραγόμενου mpg και παίρνει ακέραιες τιμές από 0 μέχρι 8. Εάν θέλουμε να
καταλήξουμε σε ένα mpg με frame rate 24fps (NTSC) επιλέγουμε την τιμή 2, για 25fps (PAL) επιλέγουμε την τιμή 3. Τέλος, το -w, ασχέτως από το τι μορφής είναι το
εισαγόμενο video, κάνει το mencvcd να το μετατρέψει σε 16:9.
Έτσι, για να μετατρέψουμε το πρώτο τίτλο ενός DVD σε VCD δίνουμε:
mencvcd output -vnorm n -vfr 2 -dvd 1
και το mencvcd κάνει όλη την δουλειά μέχρι το σημείο του bin/cue image. Μετά γράφουμε το image σε ένα cd:
cdrdao write --device 0,0,0 --eject --speed videocd.cue.
Η αντίστοιχη εντολή για ένα DivX θα ήταν:
mencvcd output -vnorm n -vfr 2 video.avi
### [6. Επίλογος]{#s6}
Αυτή είναι η διαδικασία της μετατροπής. Οι πιθανοί συνδυασμοί των παραμέτρων είναι πάρα πολλοί και η αναφορά τους θα απαιτούσε την επεξήγηση του τρόπου που
δουλεύει το mencvcd πράγμα που ξεφεύγει από τον σκοπό αυτού του κειμένου. Πάντως, η συμβουλή είναι μια: κάντε πειράματα και για να μην χαλάτε πολλά CD καλό
είναι να έχετε 1-2 rewriteable κοντά σας.

400
content/articles/32/03_grlinux.md Κανονικό αρχείο

@ -0,0 +1,400 @@
+++
title = 'Ελληνικά στο Linux'
date = '2003-04-01T00:00:00Z'
description = ''
author = 'Κυρίτσης Αθανάσιος (aka DJ Art)'
issue = ['Magaz 32']
issue_weight = 3
+++
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*Η κατάσταση με τα Ελληνικά στο Linux είναι πλέον σε σχεδόν άριστη μορφή. Όλες οι μοντέρνες διανομές και εφαρμογές υποστηρίζουν Ελληνικά. Το μόνο που θα
χρειαστεί να κάνετε, είναι να τα επιλέξετε για χρήση. Η επιλογή αυτή γίνεται με σωστή ρύθμιση 2-3 παραμέτρων του συστήματος και από εκεί και πέρα, τα Ελληνικά
είναι θέμα της κάθε εφαρμογής. Με τις παρακάτω οδηγίες μπορείτε να εγκαταστήσετε \"σωστά\" (δηλαδή iso-8859-7) ελληνικά.*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Για να εγκαταστήσετε τα ελληνικά, Θα πρέπει να κάνετε τα εξής 3 απλά βήματα:
1. Να εγκαταστήσετε γραμματοσειρές στο σύστημά σας.
2. Να εγκαταστήσετε τα ελληνικά locales και να τα ενεργοποιήσετε.
3. Να ενημερώσετε τα αρχεία των Χ για το ελληνικό πληκτρολόγιο και να το ενεργοποιήσετε.
**1. Εγκατάσταση Γραμματοσειρών**
-----------------------------------------------------------
- [1.1 Graphis](#ss1.1)
- [1.2 Εγκατάσταση TrueType γραμματοσειρών](#ss1.2)
- [1.3 AntiAliasing](#ss1.3)
**2. Ενεργοποίηση των locales**
---------------------------------------------------------
- [2.1 Για το RedHat](#ss2.1)
- [2.2 Για το Mandrake](#ss2.2)
- [2.3 Για το Slackware](#ss2.3)
- [2.4 Για Debian](#ss2.4)
**3. Ρύθμιση των X-Windows**
------------------------------------------------------
- [3.1 Για X 4.3.0 και πάνω](#ss3.1)
- [3.2 Για Χ 4.1.0 ώς και X 4.2.1](#ss3.2)
- [3.3 Για Χ 4.0.2 και 4.0.3](#ss3.3)
- [3.4 Για Χ μικρότερα από 4.0.1](#ss3.4)
**4. Για την κονσόλα και μόνο**
---------------------------------------------------------
**5. Για GTK+ 2.x / GNOME 2.x εφαρμογές**
-------------------------------------------------------------------
**6. Για το Netscape της σειράς 4.x**
---------------------------------------------------------------
**7. \*BSD Compatibility**
----------------------------------------------------
**8. Credits**
----------------------------------------
### [1. Εγκατάσταση Γραμματοσειρών]{#s1}
Για να έχετε ελληνικά στο σύστημά σας, το πρώτο βήμα είναι να εγκαταστήσετε ελληνικές γραμματοσειρές. Εδώ έχετε 2 επιλογές: να εγκαταστήσετε τις δωρεάν
γραμματοσειρές του πακέτου Graphis ή/και επιπλέον TrueType γραμματοσειρές. Εμείς σας προτείνουμε να εγκαταστήσετε και τα δύο. Οι Truetype γραμματοσειρές είναι
αισθητικά πιο όμορφες και πιο προτεινόμενες για χρήση σε ένα desktop σύστημα.
### [1.1 Graphis]{#ss1.1}
Το Graphis είναι ένα project του Hellug, το οποίο έχει σαν στόχο την ομαδοποίηση των ήδη υπαρχόντων πακέτων γραμματοσειρών, αλλά και την επίλυση αρκετών
προβλημάτων τους. Η διεύθυνση του Graphis στο Internet είναι <http://graphis.hellug.gr>. Απο εκεί μπορείτε να κατεβάσετε τις γραμματοσειρές σε .rpm πακέτο ή σε
source μορφή (.tar.gz).
Στη συνέχεια, είναι απαραίτητες οι παρακάτω ενέργειες:
- Για να γίνει η εγκατάσταση αυτόματα είναι απαραίτητη η ύπαρξη της perl (γλώσσα προγραμματισμού), και να εισέλθετε στο μηχάνημά σας ως \"root\", όχι ως απλός
χρήστης. Χρησιμοποιούνται επίσης κάποιες άλλες εντολές, οι οποίες όμως ανήκουν στις standard εντολές, και θα πρέπει να είναι ήδη εγκατεστημένες (π.χ. οι
dirname και expr).
- Αρχικά πηγαίνετε στον φάκελο που έχετε σώσει τα RPM αρχεία. Στη συνέχεια εκτελέστε αυτήν την εντολή:\
rpm -Uvh xfntgr-\*.rpm\
Κανονικά θα δείτε τα πακέτα να εγκαθιστώνται το ένα μετά το άλλο.
- Αν το σύστημά σας δεν υποστηρίζει rpm πακέτα, τότε θα πρέπει να κάνετε την εγκατάσταση μόνοι σας: Αρχικά πρέπει να αποσυμπιέσετε το αρχείο
xfntgr-xx-xx.tar.gz, κάτι που μάλλον ήδη έχετε κάνει. Ως αποτέλεσμα θα πρέπει να έχετε ένα φάκελο με όνομα \"xfntgr-xx\" καθώς και πολλά αρχεία και
υποφακέλους μέσα σε αυτόν. Αυτόν τον κατάλογο θα πρέπει να τον μεταφέρετε, μετονομάζοντάς στον σε \"hellas\" στη θέση \"/usr/X11R6/lib/X11/fonts/\". Δηλαδή
θα πρέπει να υπάρχει ως \"/usr/X11R6/lib/X11/fonts/hellas/\". Στον φάκελο \"hellas\" θα βρείτε το αρχείο \"graphis\". Εκτελέστε το και οι γραμματοσειρές θα
εγκατασταθούν στο σύστημά σας (δηλαδή θα μπούν στο path στο XF86Config).
### [1.2 Εγκατάσταση TrueType γραμματοσειρών]{#ss1.2}
Truetype γραμματοσειρές μπορείτε να βρείτε οπουδήποτε. Το καλύτερο μέρος είναι ο φάκελος Fonts των Windows :-) (αρκεί να τα έχετε νόμιμα). Για όσους δεν έχουν
πρόσβαση σε μία Windows εγκατάσταση, μπορείτε να κατεβάσετε τα \"core fonts for the web\" στο <http://corefonts.sourceforge.net/>. Επίσης, μπορείτε να βρείτε
Truetype γραμματοσειρές σε διάφορα σημεία στο Internet, ενώ υπάρχουν και εμπορικές λύσεις, εμπορικά πακέτα που προσφέρουν ως προϊόν οικογένειες TrueType
γραμματοσειρών.
Για να εγκαταστήσετε και να χρησιμοποιήσετε truetype γραμματοσειρές, χρειάζεστε 2 πράγματα:
1. font server με υποστήριξη truetype. Αν χρησιμοποιείτε Χ-Windows της σειράς 4.0.x και πάνω, δεν χρειάζεται να ανησυχείτε γιατί τον έχουν ενσωματωμένο. Για Χ
κατώτερης έκδοσης, τον truetype font server (xfsft) θα τον βρείτε στο <http://www.dcs.ed.ac.uk/home/jec/programs/xfsft/>.\
\
2. Την εφαρμογή ttmkfdir. Αν δεν την έχετε στο σύστημά σας, μπορείτε να την βρείτε στο <http://www.joerg-pommnitz.de/TrueType/ttmkfdir.tar.gz>
Τώρα είστε έτοιμοι να εγκαταστήσετε τις γραμματοσειρές. Πηγαίντε στον κατάλογο /usr/X11R6/lib/X11/fonts και δημιουργείστε έναν καινούριο φάκελο με την ονομασία
π.χ. ttf. Μέσα σε αυτόν τον κατάλογο τοποθετήστε όσες truetype γραμματοσειρές επιθυμείτε. Σημειώστε πως τα filenames των γραμματοσειρών δεν θα πρέπει να
περιέχουν κενό. Επίσης, αν κάνατε copy τις γραμματοσειρές από το φάκελο fonts των Windows, τότε σιγουρευτείτε πως κάνατε copy μόνο όσα αρχεία έχουν την κατάληξη
.ttf, όλες οι άλλες γραμματοσειρές των Windows δεν είναι truetype και δεν θα δουλέψουν. Στη συνέχεια, μπείτε στον κατάλογο ttf και εκτελέστε τις εντολές
ttmkfdir -o fonts.dir και ttmkfdir -o fonts.scale. Θα δημιουργηθούν τα αρχεία fonts.dir και fonts.scale, τα οποίο θα περιέχουν όλες τις γραμματοσειρές που
εγκαταστήσατε. Τώρα θα πρέπει να προσθέσετε τον φάκελο /usr/X11R6/lib/X11/fonts/ttf στο Fontpath των X-Windows. Αυτό μπορείτε να το κάνετε με 2 τρόπους:
1. Αν χρησιμοποιείτε τον X font Server (xfs), πηγαίνετε στον κατάλογο /etc/X11/fs και ανοίξτε το αρχείο config με έναν text editor. Προσθέστε στο
\"catalogue=\" τον παραπάνω κατάλογο με τις truetype γραμματοσειρές και κάντε restart τον xfs.
2. Αν δεν χρησιμοποιείτε τον xfs, τότε ανοίξτε το κατάλληλο XF86Config (π.χ. /etc/X11/XF86Config ή /etc/X11/XF86Config-4) και προσθέστε την παρακάτω γραμμή στο
Section \"Files\":
FontPath "/usr/X11R6/lib/X11/fonts/ttf/"
Κάντε restart τα X-Windows
Στις καινούριες διανομές, είναι απαραίτητο ακόμα ένα βήμα. Έτσι, λοιπόν, αν έχετε μία από τις εξής διανομές: **RedHat έκδοσης 8.0 και πάνω, Mandrake έκδοσης 9.0
και πάνω, SuSE έκδοσης 8.0 και πάνω, Slackware έκδοσης 9.0 και πάνω ή οποιαδήποτε άλλη διανομή που χρησιμοποιεί το πακέτο fontconfig**, τότε αφού έχετε κάνει
όλα τα παραπάνω βήματα, εκτελέστε ως root την εντολή **fc-cache -fv**\
Το output αυτής της εντολής θα πρέπει να σας πληροφορήσει σχετικά με τον αριθμό των γραμματοσειρών που βρήκε στον κατάλογο με τις ttf γραμματοσειρές σας. Αν δεν
\"διάβασε\" τον συγκεκριμένο κατάλογο, τότε θα χρειαστεί να τον προσθέσετε κατάλληλα στο αρχείο: **/etc/fonts/fonts.conf**
Για το Debian, με την παρακάτω εντολή θα εγκατασταθούν αυτόματα οι core γραμματοσειρές της Microsoft:
\# apt-get install msttcorefonts
### [1.3 AntiAliasing]{#ss1.3}
Όσον αφορά το θέμα AntiAliasing στα fonts, απλά θα αναφέρω πως εδώ μιλάμε πλέον \*ΜΟΝΟ\* για truetype γραμματοσειρές (το ΑΑ δουλεύει μόνο πάνω σε αυτές).
Επίσης, θα πρέπει να είστε σίγουροι πως οι βιβλιοθήκες που έχετε, όπως το QT ή το GTK+/Glib και τα X-Windows/libfreetype, το υποστηρίζουν ή ότι τα έχετε κάνει
compile με ενεργοποιημένη την υποστήριξη ΑΑ.
Για τους πιο πολλούς, αν έχετε κάποια από τις τελευταίες διανομές, τότε το πιθανότερο είναι ότι δεν θα χρειαστεί να κάνετε τίποτα (π.χ. απλά επιλέξτε την
συγκεκριμένη δυνατότητα από το control center του KDE)
Σε κάθε άλλη περίπτωση, σας παραπέμπω στο πολύ καλό HowTo για το θέμα αυτό, το οποίο θα βρείτε στο <http://trolls.troll.no/~lars/fonts/qt-fonts-HOWTO.html>.
### [2. Ενεργοποίηση των locales]{#s2}
Το επόμενο βήμα που θα πρέπει να κάνετε είναι να ενεργοποιήσετε τα ελληνικά locales στο σύστημά σας. Για να το κάνετε αυτό, καλό θα ήταν να συμβουλευτείτε τις
οδηγίες που δίνει η διανομή σας. Και, φυσικά, να φροντίσετε (πρίν από οτιδήποτε) τα ελληνικά locales να είναι εγκατεστημένα. Προσέξτε πως αν δεν τα
ενεργοποιήσετε, τότε τίποτα από όλα αυτά που αναφέρουμε εδώ δεν πρόκειται να δουλέψει σωστά. (Συνοπτικά, έχω ακούσει ότι για SuSE θα πρέπει να κάνετε το
απαραίτητο βήμα μέσω του YAST, ενώ για Redhat/Mandrake, υπάρχει το αρχείο /etc/sysconfig/i18n όπου ορίζονται οι μεταβλητές των locales και η γλώσσα). Αν έχετε
αναλυτικές οδηγίες για κάποια διανομή, ευχαρίστως να τις συμπεριλάβω σε αυτό το κείμενο.
Αν είστε σίγουροι πως έχετε εγκατεστημένα τα locales και ξέρετε πώς να τα ενεργοποιήσετε, τότε πρέπει να ορίσετε το LC\_CTYPE ώς el ή el\_GR ή greek, ανάλογα με
τη διανομή που χρησιμοποιείτε. Για να έχετε ελληνικό πληκτρολόγιο η παραπάνω μεταβλητή είναι αρκετή. Αν θέλετε να χρησιμοποιείτε τα εξελληνισμένα προγράμματα
και να βλέπετε τα μενού στα παράθυρα στα ελληνικα, τότε πρέπει να ορίσετε την LC\_MESSAGES όπως και την LC\_CTYPE. Ένας manual τρόπος να ορίσετε τις δύο αυτές
μεταβλητές είναι να ανοίξετε το αρχείο εκίννησης του shell σας, π.χ. το .bash\_login ή το .bash\_profile ή το .bashrc (ανάλογα με τη διανομή που χρησιμοποιείτε)
που υπάρχει στο home directory σας και να γράψετε:
export LC_CTYPE=el_GR
export LC_MESSAGES=el_GR
### [2.1 Για το RedHat]{#ss2.1}
Aνοίγουμε το αρχείο /etc/sysconfig/i18n και φροντίζουμε ώστε να υπάρχουν οι εξής γραμμες:
LANG="el_GR"
SUPPORTED="en_US.UTF-8:en_US:en:el_GR.UTF-8:el_GR:el"
LC_CTYPE="el_GR"
Μετά το πείραγμα αυτού του αρχείου, θα πρέπει το RedHat με κάποιο τρόπο να ξαναδιαβάσει αυτό το αρχείο. Ένας γρήγορος τρόπος να το κάνετε αυτό είναι να βγείτε
σε init 1 με την εντολή **telinit 1** και ξανά σε init 3 με την εντολή **telinit 3**. Οι πιο αρχάριοι μπορούν να κάνουν ένα reboot (shutdown) του μηχανήματος αν
μπερδεύονται με τα inits.
### [2.2 Για το Mandrake]{#ss2.2}
Ανοίγουμε το αρχείο /etc/sysconfig/i18n και φροντίζουμε ώστε να μοιάζει κάπως έτσι:
LANG="el_GR"
SUPPORTED="en_US.UTF-8:en_US:en:el_GR.UTF-8:el_GR:el"
LC_CTYPE="el_GR"
Μετά το πείραγμα αυτού του αρχείου, θα πρέπει το Mandrake με κάποιο τρόπο να ξαναδιαβάσει αυτό το αρχείο. Ένας γρήγορος τρόπος να το κάνετε αυτό είναι να βγείτε
σε init 1 με την εντολή **telinit 1** και ξανά σε init 3 με την εντολή **telinit 3**. Οι πιο αρχάριοι μπορούν να κάνουν ένα reboot (shutdown) του μηχανήματος αν
μπερδεύονται με τα inits.
### [2.3 Για το Slackware]{#ss2.3}
Στο Slackware τα πράγματα είναι πολύ εύκολα. Προσθέστε τις παρακάτω γραμμές είτε στο /etc/profile ή στο \~/.bash\_login:
export LANG=el_GR
export LC_CTYPE=el_GR
export LC_NUMERIC=POSIX
export LC_TIME=POSIX
export LC_COLLATE=POSIX
export LC_MONETARY=POSIX
export LC_MESSAGES=POSIX
export LC_PAPER=POSIX
export LC_NAME=POSIX
export LC_ADDRESS=POSIX
export LC_TELEPHONE=POSIX
export LC_MEASUREMENT=POSIX
export LC_IDENTIFICATION=POSIX
Όσες επιπλέον μεταβλητές περιβάλλοντος θέλετε να δείχνουν σε el\_GR, αλλάξτε κατάλληλα στις παραπάνω γραμμές το POSIX με el\_GR.
### [2.4 Για Debian]{#ss2.4}
Στο Debian, τα locales εγκαθίστανται και ρυθμίζονται με τις εξής εντολές:
\# apt-get install locales\
\# dpkg-reconfigure locales
Στη συνέχεια επιλέγετε el\_GR.ISO8859-7 ή/και ότι άλλο χρειαζόσαστε.
### [3. Ρύθμιση των X-Windows]{#s3}
### [3.1 Για X 4.3.0 και πάνω]{#ss3.1}
Αν έχετε Χ 4.3.0 και πάνω, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ) και
στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας, π.χ.
το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η ενότητα
θα μοιάζει κάπως έτσι:
Option "XkbRules" "xfree86"
Option "XkbModel" "pc101"
Option "XkbLayout" "us,el"
Option "XkbOptions" "grp:alt_shift_toggle"
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
είναι προφανή).
### [3.2 Για Χ 4.1.0 ώς και X 4.2.1]{#ss3.2}
Αν έχετε Χ 4.1.0 έως και X 4.2.1, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ)
και στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας,
π.χ. το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η
ενότητα θα μοιάζει κάπως έτσι:
Option "XkbRules" "xfree86"
Option "XkbModel" "pc101"
Option "XkbLayout" "el"
Option "XkbOptions" "grp:alt_shift_toggle"
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
είναι προφανή).
### [3.3 Για Χ 4.0.2 και 4.0.3]{#ss3.3}
Αν έχετε είτε Χ 4.0.2 είτε 4.0.3, τότε για να έχετε ελληνικά, αρκεί να πάτε σε κάποιο εργαλείο ρύθμισης των Χ (όπως το xf86config, το xf86cfg, το XF86Setup κλπ)
και στην επιλογή για το πληκτρολόγιο να επιλέξετε το ελληνικό. Στη συνέχεια, θα πρέπει να ανοίξετε το κατάλληλο αρχείο XF86Config (ανάλογα με τη διανομή σας,
π.χ. το /etc/X11/XF86Config ή το /etc/X11/XF86Config-4) και να πάτε στην ενότητα του πληκτρολογίου ( Section \"Keyboard\" ) και να σιγουρευτείτε πως αυτή η
ενότητα θα μοιάζει κάπως έτσι:
Option "XkbRules" "xfree86"
Option "XkbModel" "pc101"
Option "XkbLayout" "gr"
Option "XkbOptions" "grp:ctrl_shift_toggle"
Η δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να την
κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι \"grp:toggle\"
(με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά τα τρία νομίζω
είναι προφανή).
### [3.4 Για Χ μικρότερα από 4.0.1]{#ss3.4}
Το επόμενο απαραίτητο βήμα είναι η ενημέρωση των αρχείων των Χ και η ενεργοποίηση του ελληνικού πληκτρολογίου. Θα πρέπει να κάνετε τις εξής ενέργειες:
Πρώτα θα πρέπει να έχετε τα αρχεία el και Compose. Μπορείτε να τα βρείτε συμπιεσμένα στο <http://members.hellug.gr/djart/files/el_Compose.tar.bz2>.
1. Αντιγράφετε το Compose στο /usr/X11R6/lib/X11/locale/iso8859-7/.
2. Προσθέτετε την παρακάτω γραμμή στο /usr/X11R6/lib/X11/locale/compose.dir:
iso8859-7/Compose el_GR.ISO8859-7
3. Αντιγράφετε το el στο /usr/X11R6/lib/X11/xkb/symbols/.
4. Προσθέτετε την παρακάτω γραμμή στο /usr/X11R6/lib/X11/xkb/symbols.dir:
-dp----- a------- el(basic)
5. Στο /etc/X11/XF86Config, στο section \"Keyboard\", σβήνετε όλες τις επιλογές του XKB, και στη θέση τους βάζετε τις εξής:
XkbRules "xfree86"
XkbModel "pc104"
XkbLayout "el"
XkbOptions "grp:toggle"
(Η παραπάνω σύνταξη είναι για Χ 3.3.x. Για Χ 4.x η σύνταξη είναι η εξής):
Option "XkbRules" "xfree86"
Option "XkbModel" "pc101"
Option "XkbLayout" "el"
Option "XkbOptions" "grp:ctrl_shift_toggle"
H δεύτερη γραμμή μπορεί να είναι διαφορετική, ανάλογα με πόσα πλήκτρα έχει το πληκτρολόγιό σας (προφανώς, αν υπάρχει ήδη γραμμή XkbModel μπορείτε απλά να
την κρατήσετε), ενώ η τέταρτη δηλώνει με ποιό συνδυασμό πλήκτρων μπορείτε να αλλάξετε από το αγγλικό στο ελληνικό πληκτρολόγιο, και μπορεί να είναι
\"grp:toggle\" (με AltGr), \"grp:shift\_toggle\" (τα δύο Shift μαζί), \"grp:ctrl\_shift\_toggle\", \"grp:ctrl\_alt\_toggle\" και \"grp:caps\_toggle\" (αυτά
τα τρία νομίζω είναι προφανή).
6. Ξαναξεκινάτε τον X server σας. Αυτό ήταν!
### [4. Για την κονσόλα και μόνο]{#s4}
- Σιγουρευόμαστε πως το αρχείο /etc/inputrc περιέχει τις εξής γραμμές:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
set meta-flag on
set convert-meta off
set output-meta on
----------------------------------------------------------------------------------------------------------------------------------------------------------------
- Εκτελούμε με τη σειρά τις εξής εντολές:
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
**\$ setfont iso07.16**\
**\$ loadkeys gr**
Τώρα χρησιμοποιώντας το Alt+Shift μπορούμε να αλλάξουμε σε ελληνικό πληκτρολόγιο και να γράψουμε ελληνικά.
Αν οι παραπάνω εντολές δεν δουλέψουν στο RedHat 8.0 και πάνω, δοκιμάστε τις εξής εντολές:
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
**\$ setfont iso07u-16.psfu.gz -u /lib/kbd/consoletrans/8859-7\_to\_uni.trans**\
**\$ loadkeys gr**
**Για το Debian**, θα χρειαστεί να χρησιμοποιήσετε την εντολή consolechars αντί της setfont, δηλαδή οι εντολές θα είναι κάπως έτσι:
**\$ echo -ne \"\\033(K\\033)K\" \>/dev/tty**\
**\$ consolechars -f /usr/share/consolefonts/iso07.f16.psf.gz**\
**\$ loadkeys gr**
### [5. Για GTK+ 2.x / GNOME 2.x εφαρμογές]{#s5}
Λόγω ενός bug στο gtk+ 2.x, δεν εμφανίζονται οι τόνοι στις εφαρμογές. Για να επιλύσετε το συγκεκριμένο πρόβλημα, θα χρειαστεί να προσθέσετε τις παρακάτω γραμμές
στο \~/.bashrc ή \~/.bash\_profile ή \~/.bash\_login (ή όποιο άλλο είναι το αρχείο εκκίνησης του shell σας):
export GTK_IM_MODULE=xim
### [6. Για το Netscape της σειράς 4.x]{#s6}
Για να εχουμε ελληνικά στη γραμμή που δίνουμε τις διευθύνσεις και παντού στο email, αντιγράφουμε το αρχείο Netscape.ad απο τον κατάλογο
/usr/doc/netscape-communicator-4.xx/ (αν ο netscape είναι εγκατεστημένος από μορφή .rpm ή από τον κατάλογο που τον εγκαταστήσατε, σε περίπτωση μορφής .tar.gz)
στο /usr/X11R6/lib/X11/app-defaults/ και το μετονομάζουμε σε Netscape. Το ανοίγουμε με τον joe ή με άλλον επεξεργαστή και στη γραμμή 5567, 5568, 5569 (σημειώστε
ότι οι αριθμοί των σειρών αλλάζουν από έκδοση σε έκδοση, θα τους βρείτε όμως γύρω στη γραμμή 5500+) όπου λέει adobe βάζουμε \* δηλ πρέπει να είναι:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*XmTextField.fontList: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
*XmText.fontlist: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
*XmList*fontlist: -*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Επίσης, στη γραμμή 5600,5601,5602 αντικαθιστούμε το -\*-helvetica με -greek-helvetica και το 100 με 120 δηλαδή πρέπει να είναι:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*XmLGrid*fontList:\
-greek-helvetica-medium-r-*-*-*-120-*-*-*-*-iso8859-*,\
-greek-helvetica-bold-r-*-*-*-120-*-*-*-*-iso8859-*=BOLD,\
-greek-helvetica-medium-o-*-*-*-120-*-*-*-*-iso8859-*=ITALIC
----------------------------------------------------------------------------------------------------------------------------------------------------------------
ΤΕΛΕΙΩΣΑΜΕ
Ξεκινάμε τον Netscape και απο το view -\> encoding επιλέγουμε το Greek (ISO-8859-7) και πάλι απο το ίδιο μενού το \"Set Default Encoding\" και στο
Εdit-\>Preferences-\>Appearance-\>fonts το \"Greek(iso-8859-7)\" και ορίζουμε ποιές γραμματοσειρές θέλουμε. Οι καλύτερες είναι οι Courier (Greek). Tο ίδιο
κάνουμε για το \"Western(iso-8859-1)\" έτσι ώστε να μπορούμε να γράψουμε ελληνικά στις φόρμες και στο mail τύπου text/plain.
### [7. \*BSD Compatibility]{#s7}
Ναι, καλά θα το καταλάβατε. Όλα αυτά για τα Χ ισχύουν σε οποιοδήποτε Unix σύστημα που τρέχει X-Windows (προσοχή, για τα Χ μόνο, όχι και για την κονσόλα). Οι
γραμματοσειρές Graphis εγκαθίστανται και σε FreeBSD και σε \*BSD. Παρόλα αυτά, αν σαν ενδιαφέρει το θέμα των ελληνικών στα \*BSD, τότε πρέπει οπωσδήποτε να
επισκεφτείτε το web site του [Greek BSD Project](http://www.bsd.gr) και να δείτε τις οδηγίες που προσφέρουν τα παιδιά για τα \*BSD τόσο για την κονσόλα, όσο και
για τα Χ, όσο και τις γραμματοσειρές που έχουν φτιάξει.
### [8. Credits]{#s8}
Τα παιδιά που εργάστηκαν ώστε εσείς να βλέπετε ελληνικά είναι οι:
- To Graphis team ( <http://graphis.hellug.gr>) και ιδιαιτέρως ο Παναγιώτης Κατσαλούλης.
- Βασίλης Βασαΐτης. Το section για τη ρύθμιση των Χ προέρχεται από δικό του e-mail στην i18n mailing list. Ο Παναγιώτης και ο Βασίλης είναι οι δημιουργοί των
el και Compose.
- Όλα τα παιδιά στην i18n mailing list.
- To Σίμο Ξενιτέλλη και όλο το team που μεταφράζει τα προγράμματα που βλέπετε και χρησιμοποιείτε στα ελληνικά.
- Τους Αλέξανδρο Παπαδόπουλο και Ιωάννη Παπαϊωάννου για τις Debian specific οδηγίες.
- Όλους όσους ξέχασα να αναφέρω, όσους κατά λάθος αδίκησα αναφέροντας λιγότερα από όσα έχουν κάνει και όσους απλά αγνοώ ότι έχουν προσφέρει. Καλά θα κάνουν να
μου στείλουν αμέσως ένα e-mail για να αποκαταστήσω την αλήθεια ;-)

250
content/articles/32/04_traffic.md Κανονικό αρχείο

@ -0,0 +1,250 @@
+++
title = 'Traffic Shaping - Queueing algorithms'
date = ''
description = ''
author = 'Στέφανος Χαρχαλάκης'
issue = ['Magaz 32']
issue_weight = 4
+++
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*Μία σύντομη εισαγωγή σε queueing algorithmsς και της εφαρμογής τους σε δίκτυα υπολογιστών.*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
**1. FIFO**
-------------------------------------
- [1.1 Γενικά](#ss1.1)
- [1.2 Λειτουργία](#ss1.2)
- [1.3 pfifo\_fast](#ss1.3)
- [1.4 Πλεονεκτήματα/Μειονεκτήματα](#ss1.4)
**2. Stochastic Fairness Queueing (SFQ)**
-------------------------------------------------------------------
- [2.1 Γενικά](#ss2.1)
- [2.2 Λειτουργία](#ss2.2)
**3. Random Early Detection (RED)**
-------------------------------------------------------------
- [3.1 Γενικά](#ss3.1)
- [3.2 Λειτουργία](#ss3.2)
**4. Αναφορές:**
------------------------------------------
### [1. FIFO]{#s1}
### [1.1 Γενικά]{#ss1.1}
Ο αλγόριθμος FIFO είναι ο ποιο απλός απ\' όσους μπορούν να εφαρμοστούν για την διαχείριση της ουράς σε έναν network interface. Είναι ιδιαίτερα απλός και συνήθως
αποτελεί την default αντιμετώπιση.
### [1.2 Λειτουργία]{#ss1.2}
Η λειτουργία του βασίζεται στα εξής χαρακτηριστικά:
- Υπάρχει μία ουρά με σταθερό μέγεθος σε bytes ή πακέτα.
- Όσο η ουρά δεν είναι γεμάτη, κάθε πακέτο που έρχεται τοποθετείται στο τέλος της ουράς.
- Όταν πρόκειται να σταλεί ένα πακέτο στο δίκτυο, επιλέγεται το πρώτο από την ουρά.
- Όταν η ουρά είναι γεμάτη, κάθε πακέτο που έρχεται απορρίπτεται. Ο τρόπος αυτός ονομάζεται tail-drop.
### [1.3 pfifo\_fast]{#ss1.3}
Ο pfifo\_fast αποτελεί μια παραλλαγή του FIFO. Ακολουθεί την ίδια λογική, αλλά χωρίζει την ουρά σε τρία bands. Στη συνέχεια, κάθε πακέτο που έρχεται
τοποθετείται σε ένα από τα τρία bands, ανάλογα με την τιμή του TOS πεδίου. Το πεδίο αυτό έχει μέγεθος 4 bits, κάθε ένα από τα οποία έχει και άλλη σημασία:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig1.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Η ταξινόμηση των πακέτων σε κάθε ένα από τα τρία bands γίνεται όπως φαίνεται στον πίνακα.
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig2.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Ποτέ δεν στέλνεται πακέτο από την band 1 όταν υπάρχει κάποιο στη band 0, ούτε από την band 2 όταν υπάρχει κάποιο στη band 1.
### [1.4 Πλεονεκτήματα/Μειονεκτήματα]{#ss1.4}
Το μόνο πλεονέκτημα του αλγόριθμου είναι η ταχύτητά και η απλότητά του. Στην πράξη δεν έχει καλά αποτελέσματα όταν υπάρχει συμφόρηση σε κάποια γραμμή, αλλά
χρησιμοποιείται με επιτυχία σε γρήγορα interfaces όπου δεν παρατηρείται συμφόρηση.
### [2. Stochastic Fairness Queueing (SFQ)]{#s2}
### [2.1 Γενικά]{#ss2.1}
Ο αλγόριθμος SFQ προσπαθεί να λύσει το πρόβλημα που δημιουργεί ο FIFO όταν κάποιο μηχάνημα του δικτύου προκαλεί υπερβολική κίνηση. Απευθύνεται κυρίως σε μικρά
τοπικά δίκτυα για τα σημεία όπου υπάρχει συμφόρηση.
### [2.2 Λειτουργία]{#ss2.2}
Ο SFQ δημιουργεί πολλά slots του ενός πακέτου, στα οποία ταξινομεί τα πακέτα και στη συνέχεια επιλέγει το επόμενο από αυτά που θα σταλεί στο δίκτυο με κυκλικό
(Round-Robin) τρόπο. Πιο συγκεκριμένα:
- Δημιουργεί 128 διαφορετικά slots του ενός πακέτου.
- Κάθε πακέτο το οποίο έρχεται κατευθύνεται ένα από αυτά.
- Αν το slot είναι κατειλημμένο τότε το πακέτο απορρίπτεται, αλλιώς τοποθετείται μέσα σε αυτό.
Στη συνέχεια, όταν πρόκειται να δρομολογήσει ένα πακέτο στο δίκτυο, παίρνει το πρώτο που υπάρχει στην \`\`επόμενη\'\' ουρά.
#### Hashing
Η τοποθέτηση του κάθε πακέτου σε κάθε ένα από τα 128 slots γίνεται με την βοήθεια ενός αλγόριθμου hashing. Για τον υπολογισμού του hash key λαμβάνονται υπόψη:
**Για IPv4 πακέτα:**
: Η source IP address, η destination IP address και το πρωτόκολλο (TCP,UDP, \...).
**Για IPv6 πακέτα:**
: Η source IP address, η destination IP address και η τιμή ενός εσωτερικού pointer.
**Για τα υπόλοιπα:**
: Οι τιμές τριών εσωτερικών pointers.
Επίσης χρησιμοποιείται και ένας τυχαίος αριθμός ο οποίος προέρχεται από το δίκτυο και ο οποίος αλλάζει κάθε 10 δευτερόλεπτα \-- το χρονικό διάστημα ονομάζεται
perturb \-- και είναι παραμετροποιήσιμο.
Ο σκοπός του hashing είναι να αναγνωρίζει flows και να τα διαχωρίζει, δίνοντας ίσες ευκαιρίες στους χρήστες του δικτύου, ακόμα και αν κάποιος δημιουργεί
υπερβολική κίνηση. Λόγω του ότι τα hash keys δεν είναι μοναδικά, χρησιμοποιείται ο τυχαίος αριθμός που αναφέρθηκε, ο οποίος ουσιαστικά μεταβάλει τον αλγόριθμο
κάθε 10 δευτερόλεπτα.
#### Αποστολή πακέτων
Η επιλογή του επόμενου πακέτου προς αποστολή γίνεται με κυκλικό τρόπο (Round-Robin), επιλέγοντας ένα πακέτο από την επόμενη στοίβα κάθε φορά. Με τον τρόπο αυτό,
τα flows τα οποία παρουσιάζουν κίνηση μπορούν να δημιουργήσουν 128 φορές μικρότερο πρόβλημα στο δίκτυο.
#### Παράδειγμα
Ο τρόπος λειτουργίας του SFQ φαίνεται στο σχήμα. Τη στιγμή όπου η ουρά των 128 πακέτων είναι γεμάτη, ένα πακέτο έχει φύγει για το δίκτυο ελευθερώνοντας χώρο για
ένα καινούριο το οποίο θα καταλάβει τη θέση του. Την ίδια στιγμή, ένα άλλο πακέτο θα απορριφθεί γιατί το slot για το οποίο προορίζονταν είναι κατειλημμένο.
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig7.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
#### Πλεονεκτήματα/Μειονεκτήματα
Όπως αναφέρθηκε, ο SFQ προορίζεται για μικρά τοπικά δίκτυα όπου μπορεί να εξασφαλίσει την ομαλή λειτουργία. Έχει το πλεονέκτημα της ταχύτητας και της απλότητας,
μιας και δεν απαιτεί ιδιαίτερους υπολογισμούς για τη λειτουργία του.
Το πρόβλημά του είναι το μικρό μήκος ουράς (μόλις 128 πακέτα), το οποίο οδηγεί σε πολύ μεγάλο αριθμό χαμένων πακέτων. Κάτι τέτοιο είναι αποδεκτό και ίσως και
επιθυμητό σε περιπτώσεις όπου ένα flow/slot αντιστοιχεί σε έναν μόνο υπολογιστή του τοπικού δικτύου, αλλά δημιουργεί προβλήματα σε μεγαλύτερα δίκτυα.
### [3. Random Early Detection (RED)]{#s3}
### [3.1 Γενικά]{#ss3.1}
Ο αλγόριθμος αυτός είναι μία άλλη αντιμετώπιση της FIFO ουράς. Σκοπός του είναι να μην αφήσει την FIFO ουρά να γεμίσει, απορρίπτοντας επιλεκτικά πακέτα όταν
χρειάζεται.
### [3.2 Λειτουργία]{#ss3.2}
Η απόρριψη των πακέτων γίνεται στατιστικά, όταν το **μέσο** μέγεθος της ουράς ξεπεράσει κάποιο όριο.
Ο αλγόριθμος δέχεται τις εξής παραμέτρους:
**Minimum queue length: (min\_q)**
: Το μέσο μέγεθος της ουράς το οποίο πρέπει να ξεπεραστεί πριν αρχίσει ο αλγόριθμος να εξετάζει πιθανή απόρριψη πακέτων.
**Maximum queue length: (max\_q)**
: Το μέσο μέγεθος της ουράς κάτω από το οποίο προσπαθεί να την κρατάει πάντα ο αλγόριθμος. Ονομάζεται και soft limit.
**Queue limit: (qlim)**
: Το απόλυτο μέγιστο μέγεθος της ουράς. Αν το φτάσει τότε ο αλγόριθμος μετατρέπεται σε FIFO. Ονομάζεται και hard limit.
**Average packet size: (avg\_p)**
: Το μέσο μέγεθος του κάθε πακέτου. Με βάση αυτό γίνεται ο υπολογισμός όλων των υπόλοιπων.
**Burst size: (burst)**
: Το μέγιστο επιτρεπόμενο μέγεθος των bursts , ώστε να μην απορρίπτονται πακέτα όταν δεν υπάρχει πραγματική συμφόρηση.
Ο αλγόριθμος δεν αναγνωρίζει flows όπως κάποιοι άλλοι και στηρίζεται στην τυχαία επιλογή πακέτων. Η λειτουργία του βασίζεται στο μέσο μέγεθος της ουράς
(avg\_q), το οποίο υπολογίζεται με την άφιξη κάθε νέου πακέτου σύμφωνα με τον τύπο:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig3.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
όπου cql είναι το τρέχον μέγεθος της ουράς (current queue length), m είναι ο χρόνος κατά τον οποίο η ουρά δεν είναι άδεια και W είναι μία τιμή που υπολογίζεται
ως συνάρτηση των burst, min\_q και avg\_p έτσι ώστε να ισχύει:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig4.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Το W ονομάζεται και βάρος της ουράς (Queue Weight) και υποδηλώνει το κατά πόσο επηρεάζουν το avg\_q οι νέες τιμές της. Όσο μεγαλύτερο είναι το W, τόσο
μεγαλύτερη σημασία έχουν προσωρινές αυξομειώσεις της ουράς \-- δηλώνει το κατά πόσο πρέπει να \`\`θυμάται\'\' ο αλγόριθμος τα παλαιότερα μεγέθη της ουράς.
Η μεταχείριση του κάθε πακέτου μεταβάλλεται ανάλογα με το avg\_q:
- **avg\_p \< min\_q**
Το πακέτο δεν επηρεάζεται.
- **min\_q \< avg\_q \< max\_q**
Στο πακέτο αποδίδεται μια πιθανότητα p\_b:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig5.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
όπου max\_p είναι η μέγιστη επιθυμητή τιμή του p\_b. Ταυτόχρονα υπάρχει ένας counter ο οποίος αυξάνεται με κάθε πακέτο όταν το avg\_q βρίσκεται σε αυτά τα
όρια. Στη συνέχεια υπολογίζεται η πιθανότητα απόρριψης p\_a:
---------------------------------------------------------------------------------------------------------------------------------------------------------------
\
![](/32/img/fig6.png)
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Τέλος χρησιμοποιείται ένας τυχαίος αριθμός R, μεταξύ των 0 και 1, σύμφωνα με τον οποίο απορρίπτεται το πακέτο αν ο R είναι μικρότερος του p\_a.
- **avg\_q \> max\_q**
Το πακέτο απορρίπτεται.
Επειδή η απόρριψη των πακέτων γίνεται με στατιστικό τρόπο, τα flows τα οποία δημιουργούν μεγαλύτερη κίνηση έχουν περισσότερες πιθανότητες να χάσουν πακέτα μιας
και στέλνουν δεδομένα ποιο συχνά στο δρομολογητή.
#### Πλεονεκτήματα/Μειονεκτήματα
Ο RED αποτελεί μια πολύ καλή λύση για την αντιμετώπιση της συμφόρησης του δικτύου ενώ ταυτόχρονα βοηθάει το TCP/IP να βρει σχετικά σύντομα το σωστό ρυθμό
αποστολής δεδομένων.
Λόγω του ότι δεν αναγνωρίζει flows δεν έχει τη δυνατότητα να παρέχει μεγάλη δικαιοσύνη κάτι το οποίο δεν αποτελεί και σκοπό του.
### [4. Αναφορές:]{#s4}
- Bert Hubert, Gregory Maxwell, Remco van Mook, Martijn van Oosterhout, Paul B Schroeder, Jasper Spaans, Pedro Larroy. Linux Advanced Routing & Traffic
Control HOWTO,
- Sally Floyd and Van Jacobson. Random Early Detection Gateways for Congestion Avoidance. University of California, 1993
- Linux kernel 2.4.20 sources

682
content/articles/32/05_rce1.md Κανονικό αρχείο

@ -0,0 +1,682 @@
+++
title = 'Reverse Engineering σε Περιβάλλον Linux, Μέρος 0'
date = '2003-04-01T00:00:00Z'
description = ''
author = 'Φραντζής Αλέξανδρος (aka Alf)'
issue = ['Magaz 32']
issue_weight = 5
+++
----------------------------------------------------------------------------------------------------------------------------------------------------------------
*Reverse Engineering, από τη σκοπιά του απλού χρήστη :-)*
----------------------------------------------------------------------------------------------------------------------------------------------------------------
**1. Μέρος 0 - Εισαγωγή στο Reverse Code Engineering**
-----------------------------------------------------------------------------
**2. Γιατί RCE**
---------------------------------------
**3. Tools of the trade.**
-------------------------------------------------
**4. GDB - Ο παρεξηγημένος debugger**
------------------------------------------------------------
- [4.1 GDB - Τα βασικά](#ss4.1)
**5. Πρόκληση 0**
----------------------------------------
### [1. Μέρος 0 - Εισαγωγή στο Reverse Code Engineering]{#s1}
\"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move.\"- HGG Book 2
Τη δεκαετία του \'60-\'70 τα προγράμματα άρχισαν να μεγαλώνουν και να γίνονται χαώδη (βλέπε ΙΒΜ OS/360). Ο Dikjstra προσπάθησε να βάλει τάξη αλλά ήταν ήδη αργά
:) Πολλοί προγραμματιστές βρέθηκαν στη δύσκολη κατάσταση να λαμβάνουν τόνους παρατημένου κώδικα (σε assembly βέβαια) που έπρεπε να χρησιμοποιήσουν. Τα σχόλια
που συνόδευαν τα προγράμματα ήταν συχνά λειψά και στη χειρότερη περίπτωση λανθασμένα(!). Οι επιλογές ήταν δύο· να ξαναγραφεί ο κώδικας από την αρχή ή να
χρησιμοποιηθεί (με τα χίλια ζόρια) όπως είναι. Οποιοσδήποτε, όμως, δρόμος απαιτούσε την πλήρη κατανόηση του ήδη υπάρχοντος κώδικα. Ήταν μια δύσκολη δουλειά αλλά
κάποιος έπρεπε να την κάνει. Έτσι λοιπόν γεννήθηκε το Reverse Code Engineering.
Σήμερα τα πράγματα είναι πολύ διαφορετικά από τη μεριά των developers. Οι εφαρμογές αναπτύσσονται σχεδόν αποκλειστικά σε γλώσσες υψηλού επιπέδου (και με
εργαλεία ακόμα πιο υψηλού επιπέδου). Οι ίδιοι οι προγραμματιστές, τις περισσότερες φορές, δεν έρχονται σε επαφή με τον object κώδικα που παράγουν οι compilers.
Τα έτοιμα modules, που καλούνται να χρησιμοποιήσουν, είναι σε μορφή πηγαίου κώδικα ή σε βιβλιοθήκες με καλά καθορισμένη διεπαφή.
Μπορεί η διαδικασία παραγωγής να έχει αλλάξει, ο τελικός χρήστης όμως έχει στα χέρια του ότι και παλιότερα: μια ακατανόητη, για την πλειονότητα, σειρά από bytes
(εξαιρούνται τα open source) κρυμμένα πίσω από στρώματα αφαιρετικότητας (πχ εικονίδιο). Τώρα πια η τέχνη του RCE εξασκείται κυρίως από περίεργους χρήστες και
σπάνια από developers.
Τώρα έφτασε η μαγική στιγμή για να ορίσουμε το Reverse Code Engineering. Σε ελεύθερη μετάφραση στα ελληνικά ονομάζεται Αντίστροφη Μηχανική Κώδικα και είναι η
διαδικασία κατά την οποία εξάγεται η λειτουργικότητα ενός προγράμματος από τον κώδικα του, ο οποίος συνήθως βρίσκεται σε κάποια \"δύσπεπτη\" (συνήθως assembly)
μορφή.
Σε αυτό το σημείο θα ήταν σκόπιμο να αναφερθούμε λίγο στη έννοια cracker. Σε κάποιον εκτός των πραγμάτων ίσως να θυμίζει τα μπισκότα που δίνουμε στους
παπαγάλους (Poly wanna cracker?). Συχνά συνδέεται με τον κόσμο των δικτύων και αναφέρεται στον κακόβουλο hacker ο οποίος σπέρνει την καταστροφή στο πέρασμα του
:) Στον σύμπαν του RCE το cracking αναφέρεται στη διαδικασία, κατά την οποία προσπαθούμε να ξεπεράσουμε ένα σύστημα ασφαλείας στο επίπεδο του λογισμικού (πχ
copy protection). Είναι ουσιαστικά υποκατηγορία του RCE διότι αν και χρησιμοποιεί τις ίδιες τεχνικές έχει πιο περιορισμένο σκοπό και σπάνια απαιτεί την πλήρη
κατανόηση του λογισμικού.
### [2. Γιατί RCE]{#s2}
- 1\. **Γνώση**: Η παρατήρηση της εσωτερικής δομής των προγραμμάτων οδηγεί σε καλύτερη κατανόηση της λειτουργίας τους αλλά και του υπολογιστή γενικότερα.
- 2\. **Σιγουριά**: Γνωρίζοντας την εσωτερική λειτουργία ενός προγράμματος είσαι πια σίγουρος πως το λογισμικό κάνει αυτό που λέει, τίποτα λιγότερο και τίποτα
περισσότερο.
- 3\. **Ευτυχία**: Η διαδικασία του RE είναι ένα πνευματικό παιχνίδι. Αν βγεις νικητής δεν μπορείς παρά να νιώσεις ευτυχισμένος.
### [3. Tools of the trade.]{#s3}
Βασική προϋπόθεση για την επιτυχία μιας προσπάθειας στο RCE είναι η γνώση των εργαλείων που υπάρχουν, των λεγόμενων tools of the trade. Τα εργαλεία χωρίζονται
σε δύο βασικές κατηγορίες ανάλογα με την προσέγγιση που χρησιμοποιούν. Από τη μία υπάρχουν τα εργαλεία που επιτρέπουν την παρακολούθηση της δυναμικής εκτέλεσης
του κώδικα και αποτελούν την live προσέγγιση. Τέτοια εργαλεία είναι οι debuggers με πιo χαρακτηριστικά παραδείγματα το πραγματικά πανίσχυρο Numega Softice για
Windows και το περιβόητο :) GDB για το linux. Από την άλλη υπάρχουν εργαλεία που παρουσιάζουν τον κώδικα σε στατική μορφή (dead listing). Αυτά είναι
disassemblers όπως w32Dasm, IDA (τρέχει σε windows αλλά υποστηρίζει και ELF-linux εκτελέσιμα) και biew, ldasm (linux). Στο linux οι περισσότεροι disassemblers
είναι scripts που χρησιμοποιούν την έξοδο του objdump, που περιέχεται στα binutils. Τέλος αξίζει να αναφερθούμε σε μια υβριδική κατηγορία εργαλείων τα οποία εγώ
ονομάζω undead. Αυτά παρουσιάζουν την δυναμική εκτέλεση του κώδικα αλλά δεν δίνουν τη δυνατότητα τροποποίησης της εξέλιξης του. Συνήθως οι πληροφορίες που
δίνουν είναι πιο υψηλού επιπέδου από assembly. Παράδειγμα τέτοιου εργαλείου είναι το strace που καταγράφει τα system calls που κλήθηκαν από ένα πρόγραμμα.
### [4. GDB - Ο παρεξηγημένος debugger]{#s4}
O GDB (GNU DeBugger) αποτελεί πνευματικό παιδί του Richard Stallman, ιδρυτή του FSF (Free Software Foundation). Υποστηρίζει πολλές αρχιτεκτονικές (x86, alpha,
MIPS\...) και γλώσσες υψηλού επιπέδου (C, C++, Fortran, Modula-2, Pascal, CHILL). Υποστηρίζει (conditional, hardware) breakpoints, remote debugging. Έχει,
λοιπόν, όλα εκείνα τα χαρακτηριστικά που τον καθιστούν έναν πολύ ισχυρό debugger. Ποίο είναι το πρόβλημα λοιπόν;
Όπως δηλώνει και ο τίτλος, ο GDB είναι ο ορισμός του παρεξηγημένου debugger. Κατά καιρούς έχει χαρακτηριστεί με επίθετα όπως \"brain-damaged\", άδικα κατά την
ταπεινή μου γνώμη. Το βασικό επιχείρημα των πολέμιων του GDB είναι το user interface. Και όντως, το UI καμία σχέση δεν έχει με το γραφικό περιβάλλον πχ του M\$
Visual Studio. Εδώ έχουμε να κάνουμε με command line σε όλο της το μεγαλείο! Όσοι έχουν ασχοληθεί με το Softice στα windows καταλαβαίνουν τι εννοώ. Βέβαια
πολλοί έσπευσαν να βελτιώσουν την κατάσταση και έτσι σήμερα υπάρχει μία πληθώρα από front-ends: το built-in Text User Interface (TUI) σε curses,
DataDisplayDebugger (DDD) για Χ11/Motif, Kdbg gia KDE κ.α. Στο κείμενο αυτό θα ασχοληθούμε με την απλή μορφή του GDB (άντε και με το TUI :) ). Θα αρχίσουμε με
source-code debugging\...
### [4.1 GDB - Τα βασικά]{#ss4.1}
Βασική δυνατότητα ενός debugger είναι η παρακολούθηση της εκτέλεσης ενός άλλου προγράμματος και η εν δυνάμει αλλαγή της εξέλιξης του είτε άμεσα, είτε έμμεσα
μέσω της αλλαγής των δεδομένων του. Στο κομμάτι αυτό θα χρησιμοποιηθεί ως παράδειγμα ο παρακάτω C κώδικας:
----------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
int main(int argc, char **argv)
{
int num;
if (argc < 2) {
printf("Usage: %s <number>\n",argv[0]);
exit(1);
}
num=alf(argv[1]);
if (num > 10)
printf("Ok!\n");
else
printf("Failed!\n");
}
int alf(char *s)
{
return atoi(s);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Κάντε compile με : gcc -g -o rce1 rce1.c
To flag -g λέει στον compiler να περιλάβει στο εκτελέσιμο αρχείο εκτός από το symbol table, πληροφορίες που χρειάζεται ο GDB για source-code debugging. Αν ένα
πρόγραμμα δεν έχει τέτοιες πληροφορίες τότε μπορούμε μόνο να δούμε τον assembly κώδικα (και τα σύμβολα).
Το παραπάνω (παντελώς άχρηστο) πρόγραμμα το μόνο που κάνει είναι να ελέγχει αν η πρώτη παράμετρος στη γραμμή εντολής είναι μεγαλύτερη από 10 και τυπώνει το
κατάλληλο μήνυμα.
#### Φόρτωμα προγράμματος
Καταρχάς πρέπει να φορτώσουμε το πρόγραμμα στο GDB:
> bash$ gdb -q rce1
> (gdb)
>
>
Το switch -q/\--quiet λέει στον gdb να μη δείχνει τα εισαγωγικά μηνύματα. Από εδώ και πέρα θα εννοείται ακόμα και αν δεν γράφεται (πχ alias gdb =\"gdb -q\").
Το (gdb) prompt δηλώνει πως ο debugger έχει σταματήσει το πρόγραμμα και είναι έτοιμος να δεχτεί εντολές. Παρατηρήστε πως ο GDB δεν έγραψε κάποιο μήνυμα
επιβεβαίωσης ότι έγινε σωστά το φόρτωμα του rce1. Εφόσον δεν υπάρχει μήνυμα λάθους η διαδικασία ολοκληρώθηκε επιτυχώς.
H έξοδος από τον debugger γίνεται με την \"quit\"/\"q\"
> (gdb) q
> bash$
>
>
Μια εναλλακτική μέθοδος για να φορτώνουμε αρχεία είναι με την εντολή **file** του GDB. Η **file** φορτώνει το εκτελέσιμο στη μνήμη ΚΑΙ το symbol table στον GDB.
Υπάρχει και η exec-file η οποία φορτώνει μόνο τo εκτελέσιμο στη μνήμη.
> bash$ gdb
> (gdb) file rce1
> Reading symbols from rce1...done.
> (gdb)
>
>
Σημείωση: Ο GDB περιλαμβάνει ένα αρκετά πλήρες σύστημα βοήθειας με την εντολή **help**.
> (gdb) help file
> Use FILE as program to be debugged.
> It is read for its symbols, for getting the contents of pure memory,
> and it is the program executed when you use the `run' command.
> If FILE cannot be found as specified, your execution directory path
> ($PATH) is searched for a command of that name.
> No arg means to have no executable file and no symbols.
> (gdb)
>
>
Για να δούμε τον κώδικα που έχουμε φορτώσει χρησιμοποιούμε τη εντολή **list**. Η εντολή έχει διάφορες μορφές. Χωρίς παραμέτρους εμφανίζει 10 γραμμές πηγαίου
κώδικα γύρω από την τρέχουσα ή τις πρώτες 10 γραμμές αν το πρόγραμμα δεν εκτελείται.
> (gdb) list
> 1 #include <stdio.h>
> 2
> 3 int main(int argc, char **argv)
> 4 {
> 5 int num;
> 6
> 7 if (argc<2) {
> 8 printf("Usage: %s <number>\n",argv[0]);
> 9 exit(1);
> 10 }
> (gdb)
>
>
Αν η **list** έχει μία παράμετρο τότε εμφανίζει 10 γραμμές κώδικα γύρω από αυτή ενώ μπορούμε να προσδιορίσουμε και ένα διάστημα ***list x,y***
> (gdb) list 8
> 3 int main(int argc, char **argv)
> 4 {
> 5 int num;
> 6
> 7 if (argc<2) {
> 8 printf("Usage: %s <number>\n",argv[0]);
> 9 exit(1);
> 10 }
> 11
> 12 num=alf(argv[1]);
> (gdb) list 9,14
> 9 exit(1);
> 10 }
> 11
> 12 num=alf(argv[1]);
> 13
> 14 if (num>10)
> (gdb)
>
>
#### Εκτέλεση
Αφού το πρόγραμμα έχει φορτωθεί μπορούμε να το εκτελέσουμε με την εντολή **run** ή **r**. Η **run** δέχεται ως παραμέτρους τα command-line arguments που θέλουμε
να περάσουμε στο πρόγραμμα.
> (gbd) r
> Starting program: /home/alf/temp/rce1
> Usage: /home/alf/temp/rce1 <number>Program exited with code 01.
> (gdb) r 42
> Starting program: /home/alf/temp/rce1 42
> Ok!
> Program exited with code 04.
> (gdb) r 3
> Starting program: /home/alf/temp/rce1 3
> Failed!
> Program exited with code 07.
> (gdb) r
> Starting program: /home/alf/temp/rce1 3
> Failed!
> Program exited with code 07.
>
>
Παρατηρήστε ότι στην απλή **r** τα command-line arguments παραμένουν από την προηγούμενη εκτέλεση. Αυτά είναι αποθηκευμένα στην εσωτερική μεταβλητή του GDB
\"args\". Υπάρχει μια πληθώρα από εσωτερικές μεταβλητές που μπορούν να προσπελαστούν με τις **show** και **set** (hint: μη ξεχνάτε το help\...).
> (gdb) show args
> Argument list to give program being debugged when it is started is "3".
> (gdb) set args 666 7
> (gdb) r
> Starting program: /home/alf/temp/rce1 666 7
> Ok!
> Program exited with code 04.
> (gdb)
>
>
Βέβαια ως εδώ το μόνο που έχουμε κάνει είναι\... τίποτα! Τα ίδια και με πιο απλό τρόπο θα μπορούσαν να γίνουν από τo command line ενώ εμείς θέλουμε να ελέγχουμε
το πρόγραμμα βήμα προς βήμα.
Για να γίνει αυτό, πρέπει να φροντίσουμε ο έλεγχος να επιστρέψει πίσω στον debugger όταν αρχίσει το πρόγραμμα. Για την ώρα δεχτείτε αυτή την εντολή χωρίς
εξηγήσεις (λίγο υπομονή βρε παιδιά!)
> (gdb) break main
> Breakpoint 1 at 0x8048466: file rce1.c, line 7.
> (gdb) r
> Starting program: /home/alf/projects/rce1
>
> Breakpoint 1, main (argc=1, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb)
>
>
Αυτό που κάναμε ήταν να πούμε στον GDB να σταματήσει την εκτέλεση του προγράμματος όταν μπει στη συνάρτηση main. Τώρα είμαστε πριν την εκτέλεση της πρώτης
εντολής της main και ο GDB περιμένει οδηγίες. Για να εκτελέσουμε την τρέχουσα εντολή χρησιμοποιούμε την εντολή **next** ή **n**:
> (gdb) next
> 8 printf("Usage: %s <number>\n",argv[0]);
> (gdb) n
> Usage: /home/alf/projects/rce1 <number>9 exit(1);
> (gdb) n
>
> Program exited with code 01.
>
>
Επειδή δεν περάσαμε παραμέτρους στο πρόγραμμα, το argc ήταν μικρότερο του 2 και εκτυπώθηκε ο τρόπος χρήσης του προγράμματος. Ας ξαναδοκιμάσουμε:
> (gdb) r 123
> Starting program: /home/alf/projects/rce1 123
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) n
> 12 num=alf(argv[1]);
> (gdb) n
> 14 if (num>10)
> (gdb) n
> 15 printf("Ok!\n");
> (gdb) n
> Ok!
> 18 }
> (gdb) n
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
> (gdb) n
> Single stepping until exit from function __libc_start_main,
> which has no line number information.
>
> Program exited with code 04.
> (gdb)
>
>
Παρατηρήστε ότι μετά τη γραμμή 18 το πρόγραμμα δεν κάνει exit αλλά επιστρέφουμε σε μια συνάρτηση που ανήκει στην libc.so.6. Επειδή δεν έχουμε debugging
πληροφορίες για αυτή, η **next** απλώς προχωράει μέχρι να τελειώσει η συνάρτηση. Αυτό που συμβαίνει ακριβώς είναι ότι με την **next** προχωράμε μια γραμμή
κώδικα αλλά o GDB δεν έχει πληροφορίες για ποίες εντολές assembly αντιστοιχούν σε κάθε γραμμή, οπότε δεν ξέρει πόσο να προχωρήσει. H \_\_libc\_start\_main()
είναι στην πραγματικότητα η πρώτη συνάρτηση που έχει κληθεί από το πρόγραμμα μας και έχει στόχο να αρχικοποιήσει την libc και μετά να καλέσει τη δική μας main
(περισσότερα για αυτό στο επόμενο μέρος, όταν θα ασχοληθούμε με την assembly μορφή του κώδικα).
Αν ενώ είμαστε στον GDB θέλουμε να συνεχίσει κανονικά η εκτέλεση του προγράμματος μπορούμε να χρησιμοποιήσουμε την εντολή **continue** ή **c**. To πρόγραμμα
συνεχίζει μέχρι να συναντήσει κάποιο breakpoint ή να τερματιστεί.
> (gdb) r 123
> Starting program: /home/alf/projects/rce1 123
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) n
> 12 num=alf(argv[1]);
> (gdb) c
> Continuing.
> Ok!
> Program exited with code 01.
> (gdb)
>
>
Εκτός από την **next** υπάρχει και η **step** ή **s** η οποία κάνει ότι και η **next** με τη διαφορά ότι αν η τρέχουσα εντολή είναι κλήση συνάρτησης η **step**
μπαίνει μέσα στον κώδικα της συνάρτησης.
> (gdb) r 123
> Starting program: /home/alf/projects/rce1 123
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) n
> 12 num=alf(argv[1]);
> (gdb) s
> alf (s=0xbffff94f "123") at rce1.c:25
> 25 return atoi(s);
> (gdb) n
> 26 }
> (gdb) n
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> (gdb) c
> Continuing.
> Ok!
> Program exited with code 01.
> (gdb)
>
>
Ας δοκιμάσουμε μερικές ακόμη εντολές:
> (gdb) r 123 abc
> Starting program: /home/alf/projects/rce1 123 abc
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) print argc
> $1 = 3
> (gdb) set argc=6
> (gdb) print argc
> $2 = 6
> (gdb) set argc=argc-2
> (gdb) print argc
> $3 = 4
>
>
Παραπάνω είδαμε δύο σημαντικές εντολές για να εξετάζουμε δεδομένα, την **print** και την **set** (η οποία όπως είδαμε χρησιμοποιείται και για εσωτερικές
μεταβλητές). Είναι πολύ βασικό να σημειωθεί πως ό,τι ακολουθεί τις **print** και **set** είναι έκφραση της C, γεγονός που μας δίνει ιδιαίτερη ευελιξία O GDB
αναγνωρίζει αυτόματα τον τύπο της έκφρασης και παρουσιάζει τα δεδομένα με τον κατάλληλο τρόπο.
> (gdb) print &argc
> $4 = (int *) 0xbffff790
> (gdb) print &argc + 1
> $5 = (int *) 0xbffff794
> (gdb) print (char *)&argc + 1
> $6 = 0xbffff791 ""
>
>
Στην πρώτη εντολή λέμε στον GDB να τυπώσει την διεύθυνση της μεταβλητής argc. Το αποτέλεσμα της δεύτερης εντολής ίσως να φαίνεται λίγο παράξενο. Πολλοί θα
περίμεναν να είναι 0xbffff791. Επειδή η argc είναι τύπου int που στη συγκεκριμένη περίπτωση είναι 4 bytes το &argc + 1 δείχνει 4 bytes μπροστά. Γενικά, αν p
είναι δείκτης σε τύπο Τ, το p + n δείχνει στη θέση μνήμης p+n\*sizeof(T) ( εδώ &argc + 1\*sizeof(int) ). Αν κάνουμε cast το &argc σε (char \*) το αποτέλεσμα
είναι το αναμενόμενο, διότι ο char είναι εξ ορισμού 1 byte.
> (gdb) print argv[1]
> $7 = 0xbffff94a "123"
> (gdb) print argv[2]
> $8 = 0xbffff94d "abc"
> (gdb) print argv[0]
> $9 = 0xbffff932 "/home/alf/projects/rce1"
>
>
Ο GDB αναγνωρίζει πως οι μεταβλητές πρόκειται για strings (char \*) και εμφανίζει το περιεχόμενο τους. Ας παίξουμε λίγο με τα strings :)
> (gdb) set argv[1]="555"
> (gdb) print argv[1]
> $10 = 0x8049588 "555"
>
>
Παρατηρείστε πως ο GDB έκανε μία σοφή κίνηση: δέσμευσε μόνος του χώρο για το καινούργιο string και άλλαξε τον δείκτη argv\[1\] να δείχνει στον καινούργιο χώρο.
O παλιός έμεινε όπως είναι:
> (gdb) print (char *)0xbffff94a
> $11 = 0xbffff94a "123"
>
>
#### Breakpoints
Μετά από όλα αυτά, ήρθε επιτέλους η ώρα να ασχοληθούμε με ένα από τα πιο σημαντικά στοιχεία ενός debugger, τα breakpoints. Όπως δηλώνει και το όνομα τους είναι
σημεία στον κώδικα όπου διακόπτεται η εκτέλεση και ο έλεγχος επιστρέφει στον debugger. H βασική εντολή στον GDB για να τεθεί ένα BP είναι η **break** ή **b**.
Δέχεται (στη βασική της μορφή) μία παράμετρο: το σημείο όπου θα διακοπεί η εκτέλεση. Η παράμετρος έχει τις εξής μορφές:
- 1\. Το αρχείο(προαιρετικά) και τη γραμμή του πηγαίου κώδικα \[file:\]line
- 2\. Το όνομα μιας συνάρτησης πχ main
- 3\. Μια θέση μνήμης πχ \*0x8048560 (προσέξτε το \'\*\')
Χρήσιμες εντολές για τα BPs είναι η **info break** η οποία είναι εμφανές τι κάνει :), η **delete \[n\]** η οποία σβήνει το BP \#n (η όλα αν δεν προσδιορίσουμε
αριθμό), η **disable \[n\]** η οποία απενεργοποιεί προσωρινά το BP \#n (η όλα\...) και η αντίθετη της, η **enable \[n\]**.
> bash$ gdb rce1
> (gdb) break main
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
> (gdb) break alf
> Breakpoint 2 at 0x804840c: file rce1.c, line 25.
> (gdb) info break
> Num Type Disp Enb Address What
> 1 breakpoint keep y 0x0804839c in main at rce1.c:7
> 2 breakpoint keep y 0x0804840c in alf at rce1.c:25
> (gdb) disable 1
> (gdb) info break
> Num Type Disp Enb Address What
> 1 breakpoint keep n 0x0804839c in main at rce1.c:7
> 2 breakpoint keep y 0x0804840c in alf at rce1.c:25
> (gdb) r 1
> Starting program: /home/alf/projects/rce1 1
>
> Breakpoint 2, alf (s=0xbffff951 "1") at rce1.c:25
> 25 return atoi(s);
> (gdb) n
> 26 }
> (gdb) n
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> (gdb) c
> Continuing.
> Failed!
>
> Program exited with code 01.
> (gdb)
>
>
Μια εναλλακτική (και πολύ χρήσιμη) μορφή της **break** είναι η **break \... if expr**, με τη οποία η εκτέλεση διακόπτεται μόνο αν η έκφραση *expr* είναι αληθής.
> bash$ gdb rce1
> (gdb) list 10
> 5 int num;
> 6
> 7 if (argc<2) {
> 8 printf("Usage: %s <number>\n",argv[0]);
> 9 exit(1);
> 10 }
> 11
> 12 num=alf(argv[1]);
> 13
> 14 if (num>10)
> (gdb) break 14 if (num==10)
> Breakpoint 1 at 0x80483d7: file rce1.c, line 14.
> (gdb) info break
> Num Type Disp Enb Address What
> 1 breakpoint keep y 0x080483d7 in main at rce1.c:14
> stop only if num == 10
> (gdb) r 4
> Starting program: /home/alf/projects/rce1 4
> Failed!
>
> Program exited with code 01.
> (gdb) r 10
> Starting program: /home/alf/projects/rce1 10
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> (gdb) c
> Continuing.
> Failed!
>
> Program exited with code 01.
> (gdb)
>
>
Για να αλλάξουμε τη συνθήκη ενός breakpoint υπάρχει η εντολή **cond n \[expr\]** η οποία αλλάζει τη συνθήκη του BP \#n σε *expr*(ή τίποτα).
Επίσης είναι δυνατόν να καθορίσουμε μια σειρά από ενέργειες που θα εκτελούνται όταν \"χτυπάει\" ένα BP. Αυτό γίνεται με την
> commands n
> list
> end
>
>
Ένα δείγμα του τι δυνατότητες μας δίνει το σύστημα:
> (gdb) break 14 if (numi<=10)
> Breakpoint 1 at 0x80483d7: file rce1.c, line 14.
> (gdb) commands 1
> Type commands for when breakpoint 1 is hit, one per line.
> End with a line saying just "end".
> >set num=13
> >c
> >end
> (gdb) r 20
> Starting program: /home/alf/projects/rce1 20
> Ok!
>
> Program exited with code 01.
> (gdb) r 3
> Starting program: /home/alf/projects/rce1 3
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> Ok!
>
> Program exited with code 01.
> (gdb)
>
>
Το breakpoint \"χτυπάει\" αλλά συνεχίζει αυτόματα, διότι η τελευταία εντολή στο command list είναι η **continue**. Καταφέραμε με αυτόν τον τρόπο να κάνουμε το
πρόγραμμα να τυπώνει πάντα Ok!, ανεξάρτητα από την τιμή της παραμέτρου στη γραμμή εντολής! Βέβαια, αυτό γίνεται μόνο όταν τρέχουμε το πρόγραμμα μέσα από το GDB.
Υπομονή μερικά τεύχη για μια καλύτερη λύση\...
Μια παραλλαγή είναι η **tbreak** (temporary breakpoint) που έχει ακριβώς την ίδια σύνταξη με την **break** αλλά εκτελείται μόνο μια φορά (γίνεται disabled
μετά). Πρακτικά είναι ισοδύναμη με την ακολουθία:
> break xyz
> commands 3 --> Αν υποθέσουμε πως το breakpoint είναι το #3
> disable 3
> end
>
>
#### Watchpoints
Τα watchpoints είναι breakpoints τα οποία δεν ενεργοποιούνται με κριτήριο την εκτέλεση μιας εντολής αλλά την αλλαγή μιας θέσης μνήμης. Για να θέσουμε ένα
watchpoint χρησιμοποιούμε την εντολή **watch**!
> (gdb) watch num
> No symbol "num" in current context.
> (gdb) break main
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
> (gdb) r 11
> Starting program: /home/alf/projects/rce1 11
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) watch num
> Hardware watchpoint 2: num
> (gdb) c
> Continuing.
> Hardware watchpoint 2: num
>
> Old value = 1075130932
> New value = 11
> main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> (gdb) c
> Continuing.
> Failed!
>
> Watchpoint 2 deleted because the program has left the block in
> which its expression is valid.
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
> (gdb) c
> Continuing.
>
> Program exited with code 01.
> (gdb)
>
>
Η πρώτη εντολή (**watch num**) απέτυχε διότι η *num* είναι τοπική μεταβλητή και έχει νόημα μόνο μέσα στη main(). Οπότε πρέπει να είμαστε στη main() για να
αναφερθούμε σε αυτή. Τελικά ο GDB μας ενημέρωσε πως η μεταβλητή num άλλαξε τιμή σε 11. Παρατηρήστε πως ο έλεγχος γύρισε σε εμάς αμέσως μετά την εντολή που
προκάλεσε την αλλαγή, η οποία προφανώς δεν είναι η if (num \< 10) αλλά η προηγούμενη num=alf(argv\[1\]) που δε φαίνεται πουθενά. Ύστερα ο GDB μας λέει πως το
watchpoint διαγράφηκε. Αυτό έγινε διότι η *num* ως τοπική μεταβλητή αποθηκεύεται στο σωρό (stack) και μετά την έξοδο από τη συνάρτηση στην οποία βρισκόταν (τη
main()) ο σωρός ελευθερώνεται (δε γίνεται ακριβώς έτσι, όταν εξετάσουμε τον κώδικα σε πιο χαμηλό επίπεδο θα δούμε την διαδικασία επακριβώς)
Παρόμοια με την **watch** είναι η **rwatch** η οποία ενεργοποιείται όχι σε αλλαγή της μνήμης αλλά σε απλή ανάγνωση.
> (gdb) break main
> Breakpoint 1 at 0x804839c: file rce1.c, line 7.
> (gdb) r 12
> Starting program: /home/alf/projects/rce1 12
>
> Breakpoint 1, main (argc=2, argv=0xbffff7e4) at rce1.c:7
> 7 if (argc<2) {
> (gdb) rwatch num
> Hardware read watchpoint 2: num
> (gdb) c
> Continuing.
> Hardware read watchpoint 2: num
>
> Value = 12
> 0x080483db in main (argc=2, argv=0xbffff7e4) at rce1.c:14
> 14 if (num>10)
> (gdb) c
> Continuing.
> Ok!
>
> Watchpoint 2 deleted because the program has left the block in
> which its expression is valid.
> 0x4003abb4 in __libc_start_main () from /lib/libc.so.6
> (gdb) c
> Continuing.
>
> Program exited with code 01.
>
>
Ουφφ! Τελειώσαμε\... για την ώρα :)\
Αυτό το πρώτο άρθρο δεν είναι και πολύ hardcore RCE αλλά ήταν απαραίτητο ώστε να τεθούν κάποιες βάσεις για αυτά που θα ακολουθήσουν. Στο επόμενο άρθρο θα
ασχοληθούμε με τη χρήση του GDB για assembly debugging και θα ρίξουμε μια πιο προσεκτική ματιά στα υπόλοιπα εργαλεία. Επίσης θα μιλήσουμε λίγο περισσότερο για
τα breakpoints και πιο συγκεκριμένα για το πως αυτά υλοποιούνται σε χαμηλό επίπεδο.
### [5. Πρόκληση 0]{#s5}
Σε κάθε άρθρο θα υπάρχει ένα πρόβλημα-πρόκληση για να ασχοληθούν όσοι επιθυμούν. Εδώ τα πράγματα είναι κάπως απλά (αλλά όχι πολύ) αφού το εκτελέσιμο είναι
compiled με το -g flag, πρακτικά σας δίνω τον πηγαίο κώδικα δηλαδή. Πάντως είναι μια καλή ευκαιρία να ακονίσετε τα GDB skills και να πάρετε μια πρώτη γεύση από
RCE!
Σκοπός της πρόκλησης είναι να βρείτε ποίος κωδικός αντιστοιχεί στο όνομα/ψευδώνυμο σας. Όποιοι θέλουν ας μου στείλουν τις απαντήσεις τους για να αναγραφούν στο
hall of fame στο επόμενο άρθρο! Οι πρώτοι τρεις παίρνουν δώρο μια ετήσια συνδρομή στο magaz :P
πχ
> bash$ challenge0 -h
> Magaz RCE Challenge 0
> Use '-g' to load it into gdb
>
> bash$ challenge0 -g
> (gdb)
>
> bash$ challenge0
> Name: alf82
> Password: 089s33k4das
> Authentication failed!
>
> bash$ challenge0
> Name: alf82
> Password: 09d12iie78722
> Authentication successful!
>
>
Μπορείτε να κατεβάσετε το εκτελέσιμο από [εδώ](./challenge0.bz2).
Στείλτε απαντήσεις, σχόλια, διορθώσεις, προσθήκες στο alf82 at freemail.gr. Καλό θα ήταν το subject του email να είναι της μορφής magaz-rce-\... ή κάτι τέτοιο,
για να τα ξεχωρίζω εύκολα!
Καλό RCE!