1 ====================
  2  Your First Packets
  3 ====================
  4 
  5 Introduction 
  6 ============
  7 
  8 This tutorial is meant for everybody who wants to start using UMPA.
  9 You will learn how to build and send your packets.
 10 
 11 Examples
 12 --------
 13 
 14 Check examples/* directory for already written full code examples.
 15 
 16 They are also available on http://trac.umitproject.org/browser/branch/UMPA/examples/
 17 
 18 ..2, 3...GO!
 19 ============
 20 
 21 import UMPA
 22 -----------
 23 
 24 Ok, at the beginning we need to import UMPA.
 25 
 26 .. code-block:: python
 27 
 28     In r1: import umit.umpa
 29     In r2:
 30 
 31 Pretty easy, isn't it? ;-)
 32 
 33 After that, we have 2 classes provided: @@Packet@@ and @@Socket@@.
 34 The former one is a protocol container. If you want to build new packet,
 35 you have to create a Packet's object. We will use it everytime when we would
 36 like to build packets.
 37 
 38 @@Socket@@ is needed at the end of the process. We will back
 39 to this point later.
 40 
 41 security issue
 42 --------------
 43 
 44 To create RAW_SOCKET we need SUID (root priviliges), but for normal usage
 45 usually it's not necessary (depends what you are doing with your application).
 46 
 47 So, it's recommended to drop the priviliges and up them only if needed.
 48 @@umit.umpa.utils@@ package provides some useful modules, and
 49 the @@umit.umpa.utils.security@@ module provides functions which are usefull
 50 in this case.
 51 
 52 All we need is to import the module and call the function. Later when we need
 53 to create a new socket (or to do something other what rely on SUID) we call
 54 another function from the module (it will be describe later).
 55 
 56 .. code-block:: python
 57 
 58     In r2: import umit.umpa.utils.security
 59     In r3: umit.umpa.utils.security.drop_priviliges()
 60     In r4: 
 61 
 62 Please note that our process has to be run as a root. Otherwise, an excaption
 63 will raise:
 64 
 65 .. code-block:: python
 66 
 67     In r1: import umit.umpa.utils.security
 68     In r2: umit.umpa.utils.security.drop_priviliges()
 69 
 70     Run the program with root-priviliges.
 71 
 72     ---------------------------------------------------------------------------
 73     <type 'exceptions.OSError'>               Traceback (most recent call last)
 74 
 75     /home/xsx/UMPA/<ipython console> in <module>()
 76 
 77     /home/xsx/UMPA/umpa/utils/security.py in drop_priviliges()
 78          48     nobody_id = pwd.getpwnam('nobody')r2
 79          49     try:
 80     ---> 50         os.seteuid(nobody_id)
 81          51     except OSError:
 82          52         print >> sys.stderr, "Run the program with root-priviliges.\n" 
 83 
 84     <type 'exceptions.OSError'>: [Errno 1] Operation not permitted
 85 
 86     In r3: 
 87 
 88 protocols
 89 ---------
 90 
 91 Let's build our first packet. There are several ways to do that. We can include
 92 each protocols as an arguments in @@Packet()@@ constructor, or just build
 93 them independent. The second case is more interesting.
 94 
 95 First, we need to import the @@umit.umpa.protocols@@ package. If we don't know
 96 which protocols are available, we can simple check it.
 97 
 98 .. code-block:: python
 99 
100     In r4: import umit.umpa.protocols
101 
102     In r5: umit.umpa.protocols.get_all()
103     Outr5: 
104     {'IP': <class 'umit.umpa.protocols.IP.IP'>,
105      'Payload': <class 'umit.umpa.protocols.Payload.Payload'>,
106      'TCP': <class 'umit.umpa.protocols.TCP.TCP'>,
107      'UDP': <class 'umit.umpa.protocols.UDP.UDP'>}
108 
109     In r6:
110 
111 There are two more functions (@@get_globals()@@ and @@get_locals()@@). We will
112 talk about them in next tutorials. But @@get_all()@@ is what you usually need.
113 
114 OK, in our example we would like to build TCP/IP packet and UDP/IP.
115 Both packets with the same IP header.
116 
117 IP protocol
118 -----------
119 
120 .. code-block:: python
121 
122     In r6: ip = umit.umpa.protocols.IP(source_address="127.0.0.1")
123 
124     In r7: ip.destination_address = (67,205,14,183)
125 
126     In r8: list(ip.get_fields_keys())
127     Outr8: 
128     ['_version',
129      '_ihl',
130      'type_of_service',
131      '_total_length',
132      '_identification',
133      'flags',
134      '_fragment_offset',
135      'time_to_live',
136      '_protocol',
137      '_header_checksum',
138      'source_address',
139      'destination_address',
140      'options',
141      '_padding']
142 
143 Ok, We've just created the IP instance. As you see, we can pass values directly
144 to constructor (@@In r6@@) or pass them later (@@In r7@@). Also, IP addresses
145 can be passed in two ways as a string or tuple (or list). To get list of
146 headers just call @@get_fields_key()@@ method. But this method is a generator,
147 so in this case we need to cast it. Names convention is pretty simple.
148 Those names are taken from the RFCs documents.
149 
150 .. note::
151 
152     Some fields are started with the underscrored prefix. This has a special
153     meaning. These fields may auto-generate values. So usually, we don't need
154     to care about them. But if you want to modify them - feel free to break
155     your packets ;)
156 
157 TCP and Payload protocols
158 -------------------------
159 
160 What next? TCP header and some payload for it..
161 
162 .. code-block:: python
163 
164     In r9: tcp = umit.umpa.protocols.TCP()
165 
166     In r10: tcp.source_port = 2958
167 
168     In r11: tcp.destination_port = 0
169 
170     In r12: tcp.set_flags('control_bits', syn=True)
171 
172     In r13: payload = umit.umpa.protocols.Payload()
173 
174     In r14: payload.data = "this is umpa!" 
175 
176     In r15: 
177 
178 Completely simple so far, isn't it?
179 
180 protocols container
181 -------------------
182 
183 Ok, let's build a packet...
184 
185 .. code-block:: python
186 
187     In r15: first_packet = umit.umpa.Packet(ip, tcp)
188 
189     In r16: first_packet.include(payload)
190 
191 So, we passed 2 protocols into constructor, and included another one with the
192 @include()@ method.
193 
194 Please remember that including order is important. By default, we can't break
195 the OSI model, so protocols need to be packed in the proper order. Otherwise,
196 the @@UMPAStrictException@@ will raise. If you want to break this rule, please
197 read about @@strict@@ attribute of the Packet's object in later tutorials.
198 
199 print statement
200 ---------------
201 
202 If we take a coffe break (longer than 5 hours) now, perhaps we will forget what
203 we built. Just print it!
204 
205 .. code-block:: python
206 
207     In r17: print first_packet
208     Packet contains 3 protocols
209     +-< IP                          >
210     | \
211     | +-[ Version                   ]        4 (auto - 4)
212     | +-[ IHL                       ]        None (auto - 5)
213     | +-[ TOS                       ]
214     | | \
215     | |  -{ precedence0             }        0
216     | |  -{ precedence1             }        0
217     | |  -{ precedence2             }        0
218     | |  -{ delay                   }        0
219     | |  -{ throughput              }        0
220     | |  -{ relibility              }        0
221     | |  -{ reserved0               }        0
222     | |  -{ reserved1               }        0
223     | | /
224     | \-[ TOS                       ]        contains 8 bit flags
225     | +-[ Total Length              ]        None (auto - 0)
226     | +-[ Identification            ]        0 (auto - 0)
227     | +-[ Flags                     ]
228     | | \
229     | |  -{ reserved                }        0
230     | |  -{ df                      }        0
231     | |  -{ mf                      }        0
232     | | /
233     | \-[ Flags                     ]        contains 3 bit flags
234     | +-[ Fragment Offset           ]        0 (auto - 0)
235     | +-[ TTL                       ]        64 (auto - 64)
236     | +-[ Protocol                  ]        None (auto - 0)
237     | +-[ _Header Checksum          ]        0 (auto - 0)
238     | +-[ Source Address            ]        127.0.0.1
239     | +-[ Destination Address       ]        (67, 205, 14, 183)
240     | +-[ Options                   ]
241     | | \
242     | | /
243     | \-[ Options                   ]        contains 0 bit flags
244     | +-[ Padding                   ]        0 (auto - 0)
245     \-< IP                          >        contains 14 fields
246     <umit.umpa.protocols.IP.IP object at 0xb78c2a4c>
247     +-< TCP                         >
248     | \
249     | +-[ Source Port               ]        2958
250     | +-[ Destination Port          ]        0
251     | +-[ Sequence Number           ]        None (auto - 0)
252     | +-[ Acknowledgment Number     ]        None (auto - 1)
253     | +-[ [[DataOffset]]                ]        None (auto - 5)
254     | +-[ Reserved                  ]        0 (auto - 0)
255     | +-[ Control Bits              ]
256     | | \
257     | |  -{ urg                     }        0
258     | |  -{ ack                     }        0
259     | |  -{ psh                     }        0
260     | |  -{ rst                     }        0
261     | |  -{ syn                     }        1
262     | |  -{ fin                     }        0
263     | | /
264     | \-[ Control Bits              ]        contains 6 bit flags
265     | +-[ Window                    ]        None (auto - 512)
266     | +-[ Checksum                  ]        None (auto - 0)
267     | +-[ Urgent Pointer            ]        None (auto - 0)
268     | +-[ Options                   ]
269     | | \
270     | | /
271     | \-[ Options                   ]        contains 0 bit flags
272     | +-[ Padding                   ]        0 (auto - 0)
273     \-< TCP                         >        contains 12 fields
274     <umit.umpa.protocols.TCP.TCP object at 0xb78e774c>
275     +-< Payload                     >
276     | \
277     | +-[ Data                      ]        this is umpa!
278     \-< Payload                     >        contains 1 fields
279     <umit.umpa.protocols.Payload.Payload object at 0xb78e794c>
280     <umit.umpa._packets.Packet object at 0xb78e798c>
281 
282     In r18: 
283 
284 sockets
285 -------
286 
287 Now, we are ready to send the packet!
288 To create a new socket, we will use @@umit.umpa.Socket@@ class.
289 Please remember, that we dropped our priviliges so we need to get them
290 back now.
291 
292 We can do it in 2 ways.
293 1. atomic way (*recommended*)
294 
295 .. code-block:: python
296 
297     In r18: sock = umit.umpa.utils.security.super_priviliges(umit.umpa.Socket)
298 
299     In r19: 
300 
301 2. normal way
302 
303 .. code-block:: python
304 
305     In r18: umit.umpa.utils.security.drop_priviliges()
306 
307     In r19: umit.umpa.utils.security.super_priviliges()
308 
309     In r20: sock = umit.umpa.Socket()
310 
311     In r21: umit.umpa.utils.security.drop_priviliges()
312 
313     In r22: 
314 
315 Both are correct. But the former is recommended. How does it work?
316 
317 We pass arguments into @@super_priviliges()@@ function, the first has to
318 be callable, others are just arguments for the first one.
319 Result of the callable argument is returned by the @@super_priviliges()@@
320 function.
321 
322 Internally in the @@super_priviliges()@@ function:
323  1. change EUID to the 0 (root)
324  2. call the first argument from passed arguments
325  3. change EUID to nobody (call @@drop_priviliges()@@)
326  4. return the result of the calling from point 2
327 
328 Ok, actually we have a socket object, so let's send the packet!
329 
330 .. code-block:: python
331 
332     In r19: sock.send(first_packet)
333     Out r19: r53
334 
335     In r20:
336 
337 @@Socket.send()@@ method returns a list with sent bytes of each packets (we can
338 pass more than one packet at the same time).
339 
340 UDP protocol
341 ------------
342 
343 Ok, let's create another packet with a UDP header just in single line!
344 
345 .. code-block:: python
346 
347     In r20: udp = umit.umpa.protocols.UDP(source_port=0, destination_port=7)
348 
349     In r21:
350 
351 ttl aka enumfield
352 -----------------
353 
354 Now, we can simple create a new packet and use already created @@sock@@ object
355 to send it out, but before we will do that, lets change TTL field of
356 the IP protocol.
357 
358 Some common fields like TTL or ports in TCP/UDP headers are @@EnumField@@
359 objects. What does it mean? Well, this is a simple numeric field but with
360 special behaviour.
361 We can pass common names instead of numbers (what is easier to remember).
362 Let's do it on the TTL example.
363 
364 .. code-block:: python
365 
366     In r21: ip.get_field("time_to_live").enumerable
367     Outr21: 
368     {'aix': 60,
369      'dec': 30,
370      'freebsd': 64,
371      'irix': 60,
372      'linux': 64,
373      'macos': 60,
374      'os2': 64,
375      'solaris': 255,
376      'sunos': 60,
377      'ultrix': 60,
378      'windows': 128}
379 
380     In r22: ip.time_to_live = "windows" 
381 
382     In r23: 
383 
384 Why can't we use @@ip.time_to_live.enumerable@@ in the first line?
385 Well, attributes like object._name_of_field_ are reserved only to get/set
386 values of them. They handle only with values. To get a reference to the field's
387 object we need to use @@get_field()@@ method.
388 
389 print statement is sooo cool
390 ----------------------------
391 
392 Don't forget about checking if everything is correct :-)
393 
394 .. code-block:: python
395 
396     In r23: print second_packet
397     Packet contains 2 protocols
398     +-< IP                          >
399     | \
400     | +-[ Version                   ]        4 (auto - 4)
401     | +-[ IHL                       ]        None (auto - 5)
402     | +-[ TOS                       ]
403     | | \
404     | |  -{ precedence0             }        0
405     | |  -{ precedence1             }        0
406     | |  -{ precedence2             }        0
407     | |  -{ delay                   }        0
408     | |  -{ throughput              }        0
409     | |  -{ relibility              }        0
410     | |  -{ reserved0               }        0
411     | |  -{ reserved1               }        0
412     | | /
413     | \-[ TOS                       ]        contains 8 bit flags
414     | +-[ Total Length              ]        None (auto - 28)
415     | +-[ Identification            ]        0 (auto - 0)
416     | +-[ Flags                     ]
417     | | \
418     | |  -{ reserved                }        0
419     | |  -{ df                      }        0
420     | |  -{ mf                      }        0
421     | | /
422     | \-[ Flags                     ]        contains 3 bit flags
423     | +-[ Fragment Offset           ]        0 (auto - 0)
424     | +-[ TTL                       ]        128 (auto - 128)
425     | +-[ Protocol                  ]        None (auto - 17)
426     | +-[ _Header Checksum          ]        0 (auto - 0)
427     | +-[ Source Address            ]        127.0.0.1
428     | +-[ Destination Address       ]        (67, 205, 14, 183)
429     | +-[ Options                   ]
430     | | \
431     | | /
432     | \-[ Options                   ]        contains 0 bit flags
433     | +-[ Padding                   ]        0 (auto - 0)
434     \-< IP                          >        contains 14 fields
435     <umit.umpa.protocols.IP.IP object at 0xb78c8b6c>
436     +-< UDP                         >
437     | \
438     | +-[ Source Port               ]        0
439     | +-[ Destination Port          ]        7
440     | +-[ Length                    ]        None (auto - 8)
441     | +-[ Checksum                  ]        None (auto - 0)
442     \-< UDP                         >        contains 4 fields
443     <umit.umpa.protocols.UDP.UDP object at 0xb78c8b0c>
444     <umit.umpa._packets.Packet object at 0xb78c8ecc>
445 
446     In r24: 
447 
448 As you see, TTL is "in Windows mode".
449 
450 packing and sending again
451 -------------------------
452 
453 .. code-block:: python
454 
455     In r24: second_packet = umit.umpa.Packet(ip, udp)
456 
457     In r25: sock.send(first_packet, second_packet)
458     Out r25: [53, 28]
459 
460     In r26:
461 
462 We sent 2 packets. 53 bytes first for the first packet and 28 for the second.
463 
464 Now, just make some exercises to get more practice!