summaryrefslogtreecommitdiff
path: root/wiki/Using-3144.wiki
blob: 9ac484e67d39fe88b2141204bb9474e9473ee4f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
= Using ipaddr =

What follows is an introducion to using ipaddr-py. These exmples use the version
from branches/3144.

== Creating Address/Network/Interface objects ==

  Since ipaddr-py is library for inspecting and manipulating IP address, the
first thing you'll want to do is create some objects. You can use ipaddr to
create objects from strings, integers or other ipaddr objects.

  * Creating Addresses.

  Addresses are the most basic unit. They are indivisable.

  IPv4 Address:

  {{{
  # string constructor.
  >>> ipaddr.IPv4Address('192.0.2.1')
  IPv4Address('192.0.2.1')

  # integer constructor.
  >>> ipaddr.IPv4Address(3221225985)
  IPv4Address('192.0.2.1')

  # copy constructor.
  >>> addr = ipaddr.IPv4Address('192.0.2.1')
  >>> ipaddr.IPv4Address(addr)
  IPv4Address('192.0.2.1')
  }}}

  IPv6 Address:

  {{{
  # string constructor.
  >>> ipaddr.IPv6Address('2001:DB8::1')
  IPv6Address('2001:db8::1')

  # integer constructor - this one's a mouthful.
  >>> ipaddr.IPv6Address(42540766411282592856903984951653826561L)
  IPv6Address('2001:db8::1')

  # copy constructor
  >>> ipaddr.IPv6Address(addr)
  IPv6Address('2001:db8::1')
  }}}

  * Creating Networks.

  Addresses are usually grouped together in Networks, so ipaddr provides a way
to create, inspect and maniuplate those as well. The constructors look identical
to their corresponding address constructor.

  IPv4 Network:
  {{{
  >>> ipaddr.IPv4Network('192.0.2.0/24')
  IPv4Network('192.0.2.0/24')
  >>> ipaddr.IPv4Network(3221225984)
  IPv4Network('192.0.2.0/32')
  >>> addr = ipaddr.IPv4Network('192.0.2.0/24')
  >>> ipaddr.IPv4Network(addr)
  IPv4Network('192.0.2.0/24')
  }}}

  IPv6 Network:
  {{{
  >>> ipaddr.IPv6Network('2001:db8::0/96')
  IPv6Network('2001:db8::/96')
  >>> ipaddr.IPv6Network(42540766411282592856903984951653826560L)
  IPv6Network('2001:db8::/128')
  >>> addr = ipaddr.IPv6Network('2001:db8::0/96')
  >>> ipaddr.IPv6Network(addr)
  IPv6Network('2001:db8::/96')
  }}}

  Network objects cannot have any host bits set. The practical effect of this is
that, '192.0.2.1/24' does not describe a network. It's referred to as an
interface object since the ip-on-a-network notation is commonly used to describe
network interfaces of a computer on a given network.

Note: when creating a network object from an integer, the prefix length
(netmask) is assumed to be all ones. So IPv4 networks will have a /32 netmask
and IPv6 networks will have a /128 netmask.

  * Creating hybrid objects.

  As mentioned just above, if you need to describe an address on a particular
network, neither the address nor the network classes is appropriate. Since the
notation 192.0.2.1/24 is so common among network engineers and the people who
write tools for firewalls and routers, ipaddr provides a set of hybrid classes.
By now, the constructor syntax should look familair.

  IPv4Interface:
  {{{
  >>> ipaddr.IPv4Interface('192.0.2.1/24')
  IPv4Interface('192.0.2.1/24')
  >>> ipaddr.IPv4Interface(3221225985)
  IPv4Interface('192.0.2.1/32')
  >>> addr = ipaddr.IPv4Interface('192.0.2.1/24')
  >>> ipaddr.IPv4Interface(addr)
  IPv4Interface('192.0.2.1/24')
  }}}

  IPv6Interface:
  {{{
  >>> ipaddr.IPv6Interface('2001:db8::1/96')
  IPv6Interface('2001:db8::1/96')
  >>> ipaddr.IPv6Interface(42540766411282592856903984951653826561L)
  IPv6Interface('2001:db8::1/128')
  >>> addr = ipaddr.IPv6Interface('2001:db8::1/96')
  >>> ipaddr.IPv6Interface(addr)
  IPv6Interface('2001:db8::1/96')
  }}}

Note: Just like with the network objects, when you create an interface object
with an integer, the netmask is assumed to be all ones.

  Finally, if you don't know at the time coding what type of addresses you might
be handling, or you don't really care and you'd like the same code to handle both,
ipaddr provides generic factory functions which look at the address and try to
return an object of the correct for you.

  * Addresses
  {{{
  >>> ipaddr.ip_address('192.0.2.1')
  IPv4Address('192.0.2.1')
  >>> ipaddr.ip_address('2001:db8::1')
  IPv6Address('2001:db8::1')
  >>> ipaddr.ip_address(1)
  IPv4Address('0.0.0.1')
  >>> addr = ipaddr.ip_address('2001:db8::1')
  >>> ipaddr.ip_address(addr)
  IPv6Address('2001:db8::1')
  }}}

  * Networks
  {{{
  >>> ipaddr.ip_network('192.0.2.0/24')
  IPv4Network('192.0.2.0/24')
  >>> addr = ipaddr.ip_network('192.0.2.0/24')
  >>> ipaddr.ip_network(addr)
  IPv4Network('192.0.2.0/24')
  >>> ipaddr.ip_network('2001:db8::0/96')
  IPv6Network('2001:db8::/96')
  }}}

  * Interfaces
  {{{
  >>> ipaddr.ip_interface('192.0.2.1/24')
  IPv4Interface('192.0.2.1/24')
  >>> ipaddr.ip_interface('2001:db8::1/96')
  IPv6Interface('2001:db8::1/96')
  }}}

Note: Since IPv4 addresses are 2^32 bits and IPv6 addresses are 2^128 bits,
all integers <= 2^32 - 1 are assumed to be IPv4. If you know that an address
is an IPv6 address, you should pass version=6 to ip_address().

  * explicit versioning
  {{{
  >>> ipaddr.ip_address(3221225985)
  IPv4Address('192.0.2.1')
  >>> ipaddr.ip_address(3221225985, version=6)
  IPv6Address('::c000:201')
  }}}

== Inspecting Address/Network/Interface Objects ==

  You've gone to the trouble of creating an IPv(4|6)(Address|Network|Interface)
object, so you probably want to get information about it. ipaddr tries to make
doing this easy and intuitive.

  {{{
  >>> addr4 = ipaddr.ip_address('192.0.2.1')
  >>> addr6 = ipaddr.ip_address('2001:db8::1')
  >>> addr6.version
  6
  >>> addr4.version
  4
  }}}

  * Network/Interface
  {{{
  >>> net4 = ipaddr.ip_network('192.0.2.0/24')
  >>> net6 = ipaddr.ip_network('2001:db8::0/96')
  }}}

  * finding out how many individual addresses are in a network.
  {{{
  >>> net4.numhosts
  256
  >>> net6.numhosts
  4294967296L
  }}}

  * iterating through the 'usable' addresses on a network.
  {{{
  >>> for x in net4.iterhosts(): print x
  192.0.2.1
  192.0.2.2
  192.0.2.3
  192.0.2.4
  [snip]
  192.0.2.252
  192.0.2.253
  192.0.2.254
  }}}

  * host/netmask
  {{{
  >>> net6.netmask
  IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')
  >>> net6.hostmask
  IPv6Address('::ffff:ffff')
  }}}

  * Exploding or compressing the address
  {{{
  >>> net6.exploded
  '2001:0000:0000:0000:0000:0000:0000:0000/96'
  >>> addr6.exploded
  '2001:0000:0000:0000:0000:0000:0000:0001'
  }}}

== Networks/Interfaces as lists ==

  It's sometimes useful to treat networks (and interfaces) as lists. This allows
us to index them like this:

  {{{
  >>> net6[1]
  IPv6Address('2001::1')
  >>> net6[-1]
  IPv6Address('2001::ffff:ffff')
  >>> ipaddr.ip_interface('192.0.2.1/24')[-1]
  IPv4Address('192.0.2.255')
  }}}

This also means that network and interface objects lend themselves to using the
list membership test syntax {{{ in }}} like this:

  {{{
  if address in netork:
    # do something
  }}}

  Address, Network and Interface objects can be 'in' a network or an interface
object.

  {{{
  >>> net4 = ipaddr.ip_network('192.0.2.0/25')
  >>> net4 in ipaddr.ip_network('192.0.2.0/24')
  True
  >>> net4 in ipaddr.ip_interface('192.0.2.0/25')
  True
  net4 in ipaddr.ip_interface('192.0.2.0/26')
  }}}

== Comparisons ==

  ipaddr provides some simply, hopefully intuitive ways to compare objects,
where it makes sense.

  {{{
  >>> ipaddr.ip_address('192.0.2.1') < ipaddr.ip_address('192.0.2.2')
  True
  }}

  A TypeError exception is raised if you try to compare objects of different
versions or different types.

== Exceptions raised by ipaddr ==

  If you try to create an address/network/interface object with an invalid value
for either the address or netmask, ipaddr will raise an AddressValueError or
NetmaskValueError respectively. Both of these exceptions have ValueError as
their parent class, so if you're not concerned with the particular type of
error, you can do the following:

  {{{
  try:
    ipaddr.ip_address(address)
  except ValueError:
    print 'address/netmask is invalid: %s' % address
  }}}