Linux Ipv6 Howto (En)
Linux Ipv6 Howto (En)
org/HOWTO/html_single/Linux+IPv6-HOWTO/
pb at bieringer dot de
Revision History
Revision 0.61 2007-10-06 Revised by: PB
Revision 0.60 2007-05-31 Revised by: PB
Revision 0.51 2006-11-08 Revised by: PB
The goal of the Linux IPv6 HOWTO is to answer both basic and advanced questions about
IPv6 on the Linux operating system. This HOWTO will provide the reader with enough
information to install, configure, and use IPv6 applications on Linux machines.
Intermediate releases of this HOWTO are available at mirrors.bieringer.de or
mirrors.deepspace6.net. See also revision history for changes.
Table of Contents
1. General
1.1. Copyright, license and others
1.2. Category
1.3. Version, History and To-Do
1.4. Translations
1.5. Technical
1.6. Preface
1.7. Used terms, glossary and shortcuts
1.8. Requirements for using this HOWTO
2. Basics
2.1. What is IPv6?
2.2. History of IPv6 in Linux
2.3. What do IPv6 addresses look like?
2.4. FAQ (Basics)
3. Address types
3.1. Addresses without a special prefix
3.2. Network part, also known as prefix
3.3. Address types (host part)
3.4. Prefix lengths for routing
4. IPv6-ready system check
4.1. IPv6-ready kernel
4.2. IPv6-ready network configuration tools
4.3. IPv6-ready test/debug programs
4.4. IPv6-ready programs
4.5. IPv6-ready client programs (selection)
4.6. IPv6-ready server programs
4.7. FAQ (IPv6-ready system check)
5. Configuring interfaces
5.1. Different network devices
5.2. Bringing interfaces up/down
Chapter 1. General
Information about available translations you will find in section Translations.
1.1.2. License
This Linux IPv6 HOWTO is published under GNU GPL version 2:
The Linux IPv6 HOWTO, a guide how to configure and use IPv6 on Linux systems.
This documentation is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this
program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
1993: I got in contact with the Internet using console based e-mail and news client
(e.g. look for “e91abier” on groups.google.com, that's me).
1996: I got a request for designing a course on IPv6, including a workshop with the
Linux operating system.
1997: Started writing a guide on how to install, configure and use IPv6 on Linux
systems, called IPv6 & Linux - HowTo (see IPv6 & Linux - HowTo/History for more
information).
1.1.3.2. Contact
The author can be contacted via e-mail at <pb at bieringer dot de> and also via his
homepage.
He's currently living in Munich [northern part of Schwabing] / Bavaria / Germany (south) /
Europe (middle) / Earth (surface/mainland).
1.2. Category
This HOWTO should be listed in category “Networking/Protocols”.
1.3.2. History
1.3.2.1. Major history
2002-01-02: A lot of content completed, first public release of chapter 1 (version 0.10).
2002-01-14: More completed, some reviews, public release of the whole document (version
0.14).
1.3.3. To-Do
Fill in missing content
1.4. Translations
Translations always have to contain the URL, version number and copyright of the
original document (but yours, too). Pls. don't translate the original changelog, this is not
very useful - also do not translate the full section about available translations, can be run
out-of-date, add an URL to this section here in the English howto.
Looks like the document's change frequency is mostly less than once per month. Since
version 0.27 it looks like that most of the content contributed by me has been written.
Translations always have to use the English version as source.
1.4.1. To language
Note: an overview with URLs can be found at http://www.bieringer.de/linux/IPv6/.
1.4.1.1. Chinese
1.4.1.2. Polish
Since 2002-08-16 a Polish translation was started and is still in progress by Lukasz Jokiel
<Lukasz dot Jokiel at klonex dot com dot pl>. Taken source: CVS-version 1.29 of LyX file,
which was source for howto version 0.27. Status is still work-in-progress (2004-08-30).
1.4.1.3. German
With 2002-11-10 a German translation was started by Georg Käfer <gkaefer at gmx dot at>
and the first public version was published 2003-02-10. It's originally available on Deep
Space 6 at http://mirrors.deepspace6.net/Linux+IPv6-HOWTO-de/ (mirrored e.g. on
http://mirrors.bieringer.de/Linux+IPv6-HOWTO-de/). This version will stay up-to-date as
much as possible.
1.4.1.4. French
With 2003-04-09 a French translation was started by Michel Boucey <mboucey at free dot
fr> and the first public version was published 2003-05-09. It's originally available on Deep
Space 6 at http://mirrors.deepspace6.net/Linux+IPv6-HOWTO-fr/ (mirrored e.g. on
http://mirrors.bieringer.de/Linux+IPv6-HOWTO-fr/).
1.4.1.5. Spanish
The first try of a Spanish translations ran into ressource problem, currently I got two other
ones, status will be updated when more information is available.
1.4.1.6. Italian
With 2003-10-16 a Italian translation was started by Michele Ferritto <m dot ferritto at
virgilio dot it> for the ILDP (Italian Linux Documentation Project) and the first public
version was published 2004-03-12. It's originally available on the ILDP at http://it.tldp.org
/HOWTO/Linux+IPv6-HOWTO/.
1.4.1.7. Japanese
On 2003-05-14 Shino Taketani <shino_1305 at hotmail dot com> send me a note that he
planned to translate the HowTo into Japanese.
1.4.1.8. Greek
On 2004-06-18 Nikolaos Tsarmpopoulos <ntsarb at uth dot gr> send me a note that he
planned to translate the HowTo into Greek.
1.4.1.9. Turkish
On 2005-07-18 Necdet Yucel <nyucel at comu dot edu dot tr> send me a note that a
Turkish translation is available. It's a snapshot translation and can be found at
http://www.belgeler.org/howto/ipv6-howto.html.
1.4.1.10. Portuguese-Brazil
On 2007-03-28 Claudemir da Luz <claudemir dot daluz at virtuallink dot com dot br> send
me a note that he planned to translate the HowTo in Portuguese-Brazil.
1.5. Technical
1.5.1. Original source of this HOWTO
This HOWTO is currently written with LyX version 1.5.1 on a Fedora Core 7 system with
template SGML/XML (DocBook book). It's available on TLDP-CVS / users / Peter-Bieringer
for contribution.
Code line wrapping is done using selfmade utility “lyxcodelinewrapper.pl”, you can get it
from CVS for your own usage: TLDP-CVS / users / Peter-Bieringer
Because the HTML pages are generated out of the SGML file, the HTML filenames turn out
to be quite random. However, some pages are tagged in LyX, resulting in static names.
These tags are useful for references and shouldn't be changed in the future.
If you think that I have forgotten a tag, please let me know, and I will add it.
1.6. Preface
Some things first:
The first IPv6 related document was written by Eric Osborne and called Linux IPv6
FAQ/HOWTO (please use it only for historical issues). Latest version was 3.2.1 released
July, 14 1997.
Please help: if someone knows the date of birth of this HOWTO, please send me an e-mail
(information will be needed in “history”).
There exists a second version called IPv6 & Linux - HowTo written by me (Peter Bieringer)
in pure HTML. It was born April 1997 and the first English version was published in June
1997. I will continue to maintain it, but it will slowly fade (but not full) in favour of the
Because the IPv6 & Linux - HowTo is written in pure HTML it's not really compatible with
the The Linux Documentation Project (TLDP). I (Peter Bieringer) got a request in late
November 2001 to rewrite the IPv6 & Linux - HowTo in SGML. However, because of the
discontinuation of that HOWTO (Future of IPv6 & Linux - HowTo), and as IPv6 is
becoming more and more standard, I decided to write a new document covering basic and
advanced issues which will remain important over the next few years. More dynamic and
some advanced content will be still found further on in the second HOWTO (IPv6 & Linux -
HowTo).
Well known decimal number system, represent any value with digit 0-9.
Base 16
Base 85
Bit
Byte
Mostly a collection of 8 (but not really a must - see older computer systems) bits
Device
A dual homed host is a node with two network (physical or virtual) interfaces on two
different links, but does not forward any packets between the interfaces.
Host
Generally a single homed host on a link. Normally it has only one active network
interface, e.g. Ethernet or (not and) PPP.
Interface
IP Header
Link
A link is a layer 2 network packet transport medium, examples are Ethernet, Token
Ring, PPP, SLIP, ATM, ISDN, Frame Relay,...
Node
Octet
Port
Protocol
Each network layer contains mostly a protocol field to make life easier on
dispatching transported information to upper layer, seen in layer 2 (MAC) and 3 (IP)
Router
A router is a node with two or more network (physical or virtual) interfaces, capable
of forwarding packets between the interfaces.
Socket
Stack
Subnetmask
IP networks uses bit masks to separate local networks from remote ones
Tunnel
1.7.1.1. Shortcuts
ACL
API
ASIC
BSD
CAN-Bus
ISP
KAME
Project - a joint effort of six companies in Japan to provide a free IPv6 and IPsec (for
both IPv4 and IPv6) stack for BSD variants to the world www.kame.net
LIR
NIC
RFC
Request For Comments - set of technical and organizational notes about the Internet
USAGI
UniverSAl playGround for Ipv6 Project - works to deliver the production quality IPv6
protocol stack for the Linux system.
The special character “¬” is used for signaling that this code line is wrapped for better
viewing in PDF and PS files.
1.7.2.2. Placeholders
<myipaddress>
For real use on your system command line or in scripts this has to be replaced with
relevant content (removing the < and > of course), the result would be e.g.
1.2.3.4
$ whoami
# whoami
You should be familiar with the major Unix tools e.g. grep, awk, find, ... , and know about
their most commonly used command-line options.
You should know about layers, protocols, addresses, cables, plugs, etc. If you are new to
this field, here is one good starting point for you: http://www.rigacci.org/docs/biblio
/online/intro_to_networking/book1.htm
You should definitely have some experience in IPv4 configuration, otherwise it will be
Also you should understand what the Domain Name System (DNS) is, what it provides
and how to use it.
You should at least understand how to use tcpdump and what it can show you. Otherwise,
network debugging will very difficult for you.
Chapter 2. Basics
2.1. What is IPv6?
IPv6 is a new layer 3 protocol (see linuxports/howto/intro_to_networking/ISO - OSI Model)
which will supersede IPv4 (also known as IP). IPv4 was designed long time ago (RFC 760 /
Internet Protocol from January 1980) and since its inception, there have been many
requests for more addresses and enhanced capabilities. Latest RFC is RFC 2460 / Internet
Protocol Version 6 Specification. Major changes in IPv6 are the redesign of the header,
including the increase of address size from 32 bits to 128 bits. Because layer 3 is
responsible for end-to-end packet transport using packet routing based on addresses, it
must include the new IPv6 addresses (source and destination), like IPv4.
For more information about the IPv6 history take a look at older IPv6 related RFCs listed
e.g. at SWITCH IPv6 Pilot / References.
2.2.1. Beginning
The first IPv6 related network code was added to the Linux kernel 2.1.8 in November 1996
by Pedro Roque. It was based on the BSD API:
The shown lines were copied from patch-2.1.8 (e-mail address was blanked on
copy&paste).
2.2.2. In between
Because of lack of manpower, the IPv6 implementation in the kernel was unable to follow
the discussed drafts or newly released RFCs. In October 2000, a project was started in
Japan, called USAGI, whose aim was to implement all missing, or outdated IPv6 support
in Linux. It tracks the current IPv6 implementation in FreeBSD made by the KAME project.
From time to time they create snapshots against current vanilla Linux kernel sources.
Until kernel development series 2.5.x was started, the USAGI patch was so big, that Linux
networking maintainers were unable to include it completly in the production source of
the Linux kernel 2.4.x series.
During kernel development series 2.5.x, USAGI tried to insert all of their current
extensions into this.
Some, but not all of them were backpported to series 2.4.x and therefore missing some
(many) extensions and also does not confirm to all current drafts and RFCs (see IP
Version 6 Working Group (ipv6) Charter). This can cause some interoperability problems
with other operating systems.
2.2.3. Current
Many of the long-term developed IPv6 related patches by USAGI and others are integrated
into vanilla kernel series 2.6.x.
2.2.4. Future
USAGI and others are still working on implementation of newer features like mobililty and
others. From time to time, new extension patches are released and also integration into
2^128-1: 340282366920938463463374607431768211455
Such numbers are not really addresses that can be memorized. Also the IPv6 address
schema is bitwise orientated (just like IPv4, but that's not often recognized). Therefore a
better notation of such big numbers is hexadecimal. In hexadecimal, 4 bits (also known as
“nibble”) are represented by a digit or character from 0-9 and a-f (10-15). This format
reduces the length of the IPv6 address to 32 characters.
2^128-1: 0xffffffffffffffffffffffffffffffff
This representation is still not very convenient (possible mix-up or loss of single
hexadecimal digits), so the designers of IPv6 chose a hexadecimal format with a colon as
separator after each block of 16 bits. In addition, the leading "0x" (a signifier for
hexadecimal values used in programming languages) is removed:
2^128-1: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
2001:0db8:0100:f101:0210:a4ff:fee3:9566
2001:0db8:0100:f101:0210:a4ff:fee3:9566 ->
¬ 2001:db8:100:f101:210:a4ff:fee3:9566
One sequence of 16 bit blocks containing only zeroes can be replaced with “::“. But not
more than one at a time, otherwise it is no longer a unique representation.
There is also a so-called compact (base85 coded) representation defined RFC 1924 / A
Compact Representation of IPv6 Addresses (published on 1. April 1996), never seen in the
wild, probably an April fool's joke, but here is an example:
Info: ipv6calc is an IPv6 address format calculator and converter program and
can be found here: ipv6calc homepage (Mirror)
5: is reserved for the Stream Protocol (STP, RFC 1819 / Internet Stream Protocol
Version 2) (which never really made it to the public)
So designers have chosen 128 bits, 4 times more in length than in IPv4 today.
The usable size is smaller than it may appear however. This is because in the currently
defined address schema, 64 bits are used for interface identifiers. The other 64 bits are
used for routing. Assuming the current strict levels of aggregation (/48, /32, ...), it is still
possible to “run out” of space, but hopefully not in the near future.
See also for more information RFC 1715 / The H Ratio for Address Assignment Efficiency
and RFC 3194 / The Host-Density Ratio for Address Assignment Efficiency.
While, there are (possibly) some people (only know about Jim Fleming...) on the Internet
who are thinking about IPv8 and IPv16, their design is far away from acceptance and
implementation. In the meantime 128 bits was the best choice regarding header overhead
and data transport. Consider the minimum Maximum Transfer Unit (MTU) in IPv4 (576
octets) and in IPv6 (1280 octets), the header length in IPv4 is 20 octets (minimum, can
increase to 60 octets with IPv4 options) and in IPv6 is 48 octets (fixed). This is 3.4 % of
MTU in IPv4 and 3.8 % of MTU in IPv6. This means the header overhead is almost equal.
More bits for addresses would require bigger headers and therefore more overhead. Also,
consider the maximum MTU on normal links (like Ethernet today): it's 1500 octets (in
special cases: 9k octets using Jumbo frames). Ultimately, it wouldn't be a proper design if
10 % or 20 % of transported data in a Layer-3 packet were used for addresses and not for
payload.
IPv4 has shown that sometimes it would be nice, if more than one IP address can be
assigned to an interface, each for a different purpose (aliases, multi-cast). To remain
extensible in the future, IPv6 is going further and allows more than one IPv6 address to be
assigned to an interface. There is currently no limit defined by an RFC, only in the
implementation of the IPv6 stack (to prevent DoS attacks).
Using this large number of bits for addresses, IPv6 defines address types based on some
leading bits, which are hopefully never going to be broken in the future (unlike IPv4 today
and the history of class A, B, and C).
Also the number of bits are separated into a network part (upper 64 bits) and a host part
(lower 64 bits), to facilitate auto-configuration.
0000:0000:0000:0000:0000:0000:0000:0001
or compressed:
::1
Packets with this address as source or destination should never leave the sending host.
0000:0000:0000:0000:0000:0000:0000:0000
or:
::
These addresses are mostly used/seen in socket binding (to any IPv6 address) or routing
tables.
These addresses are defined with a special prefix of length 96 (a.b.c.d is the IPv4
address):
0:0:0:0:0:ffff:a.b.c.d/96
or in compressed format
::ffff:a.b.c.d/96
::ffff:1.2.3.4
Used for automatic tunneling (RFC 2893 / Transition Mechanisms for IPv6 Hosts and
Routers), which is being replaced by 6to4 tunneling.
0:0:0:0:0:0:a.b.c.d/96
or in compressed format
::a.b.c.d/96
Now lets take a look at the different types of prefixes (and therefore address types):
They begin with ( where “x” is any hex character, normally “0”)
An address with this prefix is found on each IPv6-enabled interface after stateless
auto-configuration (which is normally always the case).
Another advantage: because it's possible to assign more than one address to an interface
with IPv6, you can also assign such a site local address in addition to a global one.
It begins with:
fefx:
This address type is now deprecated RFC 3879 / Deprecating Site Local Addresses, but for
a test in a lab, such addresses are still a good choice in my humble opinion.
It begins with:
fdxx:
fcxx:
A part of the prefix (40 bits) are generated using a pseudo-random algorithm and it's
improbable, that two generated ones are equal.
Example for a prefix (generated using a web-based tool: Goebel Consult / createLULA):
fd0f:8b72:ac90::/48
2xxx:
3xxx:
Note: the prefix “aggregatable” is thrown away in current drafts. There are some further
subtypes defined, see below:
These were the first global addresses which were defined and in use. They all start with
3ffe:
Example:
3ffe:ffff:100:f102::1
A special 6bone test address which will never be globally unique begins with
3ffe:ffff:
and is mostly shown in older examples. The reason for this is, if real addresses are are
shown, it's possible for someone to do a copy & paste to their configuration files, thus
inadvertently causing duplicates on a globally unique address. This would cause serious
problems for the original host (e.g. getting answer packets for request that were never
sent). Because IPv6 is now in production, this prefix is no longer be delegated and is
removed from routing after 6.6.2006 (see RFC 3701 / 6bone Phaseout for more).
These addresses, designed for a special tunneling mechanism [RFC 3056 / Connection of
IPv6 Domains via IPv4 Clouds and RFC 2893 / Transition Mechanisms for IPv6 Hosts and
Routers], encode a given IPv4 address and a possible subnet and begin with
2002:
2002:c0a8:0101:5::1
A small shell command line can help you generating such address out of a given IPv4
one:
See also tunneling using 6to4 and information about 6to4 relay routers.
These addresses are delegated to Internet service providers (ISP) and begin currently with
2001:
Prefixes to major (backbone owning) ISPs (also known as LIRs) are delegated by local
registries and currently have a prefix with length 32 assigned.
Currently, two address ranges are reserved for examples and documentation RFC 3849 /
IPv6 Address Prefix Reserved for Documentation:
3fff:ffff::/32
2001:0DB8::/32 EXAMPLENET-WF
These address ranges should be filtered based on source addresses and should NOT be
routed on border routers to the internet, if possible.
ffxy:
Multicast scope is a parameter to specify the maximum distance a multicast packet can
travel from the sending entity.
ffx2: link-local, packets are never forwarded by routers, so they never leave the
specified link.
There are many types already defined/reserved (see RFC 4291 / IP Version 6 Addressing
Architecture for details). Some examples are:
All Nodes Address: ID = 1h, addresses all hosts on the local node (ff01:0:0:0:0:0:0:1)
All Routers Address: ID = 2h, addresses all routers on the local node
(ff01:0:0:0:0:0:0:2), on the connected link (ff02:0:0:0:0:0:0:2), or on the local site
(ff05:0:0:0:0:0:0:2)
ff02::1:ff00:1234
Used prefix shows that this is a link-local multicast address. The suffix is generated from
the destination address. In this example, a packet should be sent to address “fe80::1234”,
but the network stack doesn't know the current layer 2 MAC address. It replaces the upper
104 bits with “ff02:0:0:0:0:1:ff00::/104” and leaves the lower 24 bits untouched. This
address is now used `on-link' to find the corresponding node which has to send a reply
containing its layer 2 MAC address.
Note: Anycast addresses cannot be used as source addresses, they are only used as
destination addresses.
A simple example for an anycast address is the subnet-router anycast address. Assuming
that a node has the following global assigned IPv6 address:
The subnet-router anycast address will be created blanking the suffix (least significant 64
bits) completely:
00:10:A4:E3:95:66
0210:a4ff:fee3:9566
With a given prefix, the result is the IPv6 address shown in example above:
2001:0db8:0100:f101:0210:a4ff:fee3:9566
Because the "automatically computed" host part is globally unique (except when a vendor
of a NIC uses the same MAC address on more than one NIC), client tracking is possible on
the host when not using a proxy of any kind.
This is a known problem, and a solution was defined: privacy extension, defined in RFC
3041 / Privacy Extensions for Stateless Address Autoconfiguration in IPv6 (there is also
already a newer draft available: draft-ietf-ipv6-privacy-addrs-v2-*). Using a random and a
static value a new suffix is generated from time to time. Note: this is only reasonable for
outgoing client connections and isn't really useful for well-known servers.
2001:0db8:100:f101::1
For manual suffixes like “::1” shown in the above example, it's required that the 7th most
significant bit is set to 0 (the universal/local bit of the automatically generated identifier).
Also some other (otherwise unchosen ) bit combinations are reserved for anycast
addresses, too.
Todays view is that routing will be mostly hierarchically designed for networks with only
one service provider. With more than one ISP connections, this is not possible, and
subject to an issue named multi-homing (infos on multi-homing: drafts-ietf-multi6-*,IPv6
Multihoming Solutions).
An example:
2001:0db8:100:1:2:3:4:5/48
Network:
2001:0db8:0100:0000:0000:0000:0000:0000
Netmask:
ffff:ffff:ffff:0000:0000:0000:0000:0000
For example if a routing table shows following entries (list is not complete):
2001:0db8:100::/48 :: U 1 0 0 sit1
2000::/3 ::192.88.99.1 UG 1 0 0 tun6to4
Shown destination addresses of IPv6 packets will be routed through shown device
Note: you shouldn't anymore use kernel series 2.2.x, because it's not IPv6-up-to-date
anymore. Also the IPv6 support in series 2.4.x is no longer improved according to
definitions in latest RFCs. It's recommend to use series 2.6.x now.
/proc/net/if_inet6
If this fails, it is quite likely, that the IPv6 module is not loaded.
# modprobe ipv6
If this is successful, this module should be listed, testable with following auto-magically
line:
Note: unloading the module is currently not supported and can result, under some
circumstances, in a kernel crash.
Its possible to automatically load the IPv6 module on demand. You only have to add
following line in the configuration file of the kernel module loader (normally
/etc/modules.conf or /etc/conf.modules):
It's also possible to disable automatically loading of the IPv6 module using following line
Additional note: in kernels series 2.6.x, the module loader mechanism was changed. The
new configuration file has to be named /etc/modprobe.conf instead of /etc/modules.conf.
Compile a new vanilla kernel (easy, if you know which options you needed)
Recompile kernel sources given by your Linux distribution (sometimes not so easy)
If you decide to compile a kernel, you should have previous experience in kernel
compiling and read the Linux Kernel HOWTO.
More detailed hints about compiling an IPv6-enabled kernel can be found e.g. on
IPv6-HOWTO-2#kernel.
Note: you should use whenever possible kernel series 2.6.x or above, because the IPv6
support in series 2.4.x only will no longer get backported features from 2.6.x and IPv6
support in series 2.2.x is hopeless outdated.
Same as for vanilla kernel, only recommend for advanced users, which are already familiar
with IPv6 and kernel compilation. See also USAGI project / FAQ and Obtaining the best
IPv6 support with Linux (Article) (Mirror).
A major issue is that because of the network layer structure of kernel implementation an
IPv6 packet isn't really recognized by it's IP header number (6 instead of 4). It's recognized
by the protocol number of the Layer 2 transport protocol. Therefore any transport
protocol which doesn't use such protocol number cannot dispatch IPv6 packets. Note: the
packet is still transported over the link, but on receivers side, the dispatching won't work
(you can see this e.g. using tcpdump).
Serial Line IP (SLIP, RFC 1055 / SLIP), should be better called now to SLIPv4, device
named: slX
ISDN with encapsulation syncppp, device names: ipppX (design issue of the ipppd,
will be merged into more general PPP layer in kernel series 2.5.x)
Auto-magically check:
# /sbin/route -? 2>& 1|grep -qw 'inet6' && echo "utility 'route' is IPv6-ready"
# /sbin/ip 2>&1 |grep -qw 'inet6' && echo "utility 'ip' is IPv6-ready"
If the program /sbin/ip isn't found, then I strongly recommend you install the iproute
package.
You can download the tar-ball and recompile it: Original FTP source and mirror
(missing)
Usage
# ping6 <hostwithipv6address>
# ping6 <ipv6address>
# ping6 [-I <device>] <link-local-ipv6address>
Example
# ping6 -c 1 ::1
PING ::1(::1) from ::1 : 56 data bytes
64 bytes from ::1: icmp_seq=0 hops=64 time=292 usec
Hint: ping6 needs raw access to socket and therefore root permissions. So if non-root
users cannot use ping6 then there are two possible problems:
1. ping6 is not in users path (probably, because ping6 is generally stored in /usr/sbin
-> add path (not really recommended)
2. ping6 doesn't execute properly, generally because of missing root permissions ->
chmod u+s /usr/sbin/ping6
Using link-local addresses for an IPv6 ping, the kernel does not know through which
(physically or virtual) device it must send the packet - each device has a link-local
address. A try will result in following error message:
# ping6 fe80::212:34ff:fe12:3456
connect: Invalid argument
In this case you have to specify the interface additionally like shown here:
Unlike in IPv4, where replies to a ping on the broadcast address can be disabled, in IPv6
currently this behavior cannot be disable except by local IPv6 firewalling.
# traceroute6 www.6bone.net
traceroute to 6bone.net (3ffe:b00:c18:1::10) from 2001:0db8:0000:f101::2, 30
¬ hops max, 16 byte packets
1 localipv6gateway (2001:0db8:0000:f101::1) 1.354 ms 1.566 ms 0.407 ms
2 swi6T1-T0.ipv6.switch.ch (3ffe:2000:0:400::1) 90.431 ms 91.956 ms 92.377 ms
3 3ffe:2000:0:1::132 (3ffe:2000:0:1::132) 118.945 ms 107.982 ms 114.557 ms
4 3ffe:c00:8023:2b::2 (3ffe:c00:8023:2b::2) 968.468 ms 993.392 ms 973.441 ms
5 3ffe:2e00:e:c::3 (3ffe:2e00:e:c::3) 507.784 ms 505.549 ms 508.928 ms
6 www.6bone.net (3ffe:b00:c18:1::10) 1265.85 ms * 1304.74 ms
Note: unlike some modern versions of IPv4 traceroute, which can use ICMPv4
echo-request packets as well as UDP packets (default), current IPv6-traceroute is only able
to send UDP packets. As you perhaps already know, ICMP echo-request packets are more
accepted by firewalls or ACLs on routers inbetween than UDP packets.
# tracepath6 www.6bone.net
1?: [LOCALHOST] pmtu 1480
1: 3ffe:401::2c0:33ff:fe02:14 150.705ms
2: 3ffe:b00:c18::5 267.864ms
3: 3ffe:b00:c18::5 asymm 2 266.145ms pmtu 1280
3: 3ffe:3900:5::2 asymm 4 346.632ms
4: 3ffe:28ff:ffff:4::3 asymm 5 365.965ms
5: 3ffe:1cff:0:ee::2 asymm 4 534.704ms
not port ssh: to suppress displaying SSH packets for running tcpdump in a remote
SSH session
Also some command line options are very useful to catch and print more information in a
packet, mostly interesting for digging into ICMPv6 packets:
“-s 512”: increase the snap length during capturing of a packet to 512 bytes
“-n”: don't resolve addresses to names, useful if reverse DNS resolving isn't working
proper
1.2.3.4 and 5.6.7.8 are tunnel endpoints (all addresses are examples)
$ telnet 3ffe:400:100::1 80
Trying 3ffe:400:100::1...
Connected to 3ffe:400:100::1.
Escape character is '^]'.
HEAD / HTTP/1.0
HTTP/1.1 200 OK
Date: Sun, 16 Dec 2001 16:07:21
GMT Server: Apache/2.0.28 (Unix)
Last-Modified: Wed, 01 Aug 2001 21:34:42 GMT
ETag: "3f02-a4d-b1b3e080"
Accept-Ranges: bytes
Content-Length: 2637
Connection: close
Content-Type: text/html; charset=ISO-8859-1
If the telnet client don't understand the IPv6 address and says something like “cannot
resolve hostname”, then it's not IPv6-enabled.
--without-ipv4-default: the client tries an IPv6 connect first automatically and fall
back to IPv4 if not working
$ ssh -6 ::1
user@::1's password: ******
[user@ipv6host user]$
If your ssh client doesn't understand the option “-6” then it's not IPv6-enabled, like most
ssh version 1 packages.
4.5.3.2. ssh.com
SSH.com's SSH client and server is also IPv6 aware now and is free for all Linux and
FreeBSD machine regardless if used for personal or commercial use.
1. If using an IPv4 only proxy in the settings, IPv6 requests will be sent to the proxy,
but the proxy will fail to understand the request and the request fails. Solution:
update proxy software (see later).
Also older versions don't understand an URL with IPv6 encoded addresses like
http://[3ffe:400:100::1]/ (this given URL only works with an IPv6-enabled browser!).
A short test is to try shown URL with a given browser and using no proxy.
A good starting point for browsing using IPv6 is http://www.kame.net/. If the turtle on this
page is animated, the connection is via IPv6, otherwise the turtle is static.
Kernel doesn't know, which physical or virtual link you want to use to send such ICMPv6
packets. Therefore it displays this error message.
Solution: Specify interface like: “ping6 -I eth0 fe80::2e0:18ff:fe90:9205”, see also program
ping6 usage.
These utilities create special ICMPv6 packets and send them out. This is done by using
raw sockets in the kernel. But raw sockets can only be used by the “root” user. Therefore
normal users get such error message.
Solution: If it's really needed that all users should be able to use these utilities, you can
add the “suid” bit using ”chmod u+s /path/to/program”, see also program ping6 usage. If
not all users should be able to, you can change the group of the program to e.g. “wheel”,
add these power users to this group and remove the execution bit for other users using
“chmod o-rwx /path/to/program”. Or configure “sudo” to enable your security policy.
These interfaces are normally named sitx. The name sit is a shortcut for Simple Internet
Transition. This device has the capability to encapsulate IPv6 packets into IPv4 ones and
tunnel them to a foreign endpoint.
sit0 has a special meaning and cannot be used for dedicated tunnels.
PPP interfaces get their IPv6 capability from an IPv6 enabled PPP daemon.
IPv6 capability for HDLC with encapsulation ip is already built-in in the kernel
ISDN PPP interfaces (ippp) aren't IPv6 enabled by kernel. Also there are also no plans to
do that because in kernel 2.5.+ they will be replaced by a more generic ppp interface layer.
Like mentioned earlier, this interfaces don't support IPv6 transport (sending is OK, but
dispatching on receiving don't work).
Ether-tap devices are IPv6-enabled and also stateless configured. For use, the module
“ethertap” has to be loaded before.
5.1.2.8. ATM
5.1.2.9. Others
Example:
# /sbin/ifconfig <interface> up
# /sbin/ifconfig <interface> down
Example:
# /sbin/ifconfig eth0 up
# /sbin/ifconfig eth0 down
Here you see some auto-magically configured IPv6 addresses and their lifetime.
# /sbin/ifconfig <interface>
Example (output filtered with grep to display only IPv6 addresses). Here you see different
IPv6 addresses with different scopes.
Example:
Example:
Example:
Example:
Example:
# /sbin/route -A inet6
Example (output is filtered for interface eth0). Here you see different IPv6 routes for
different addresses on a single interface.
Example:
A device can be needed, too, if the IPv6 address of the gateway is a link local one.
Following shown example adds a route for all currently global addresses (2000::/3)
through gateway 2001:0db8:0:f101::1
gateway
Not so often needed manually, mostly done by network configure scripts on shutdown
(full or per interface)
Example:
Example:
Metric “1” is used here to be compatible with the metric used by route, because the
default metric on using “ip” is “1024”.
Example:
Example:
Example:
Client can setup a default route like prefix “::/0”, they also learn such route on
autoconfiguration e.g. using radvd on the link like following example shows:
Older Linux kernel (at least <= 2.4.17) don't support default routes. You can set them up,
but the route lookup fails when a packet should be forwarded (normal intention of a
router). If you're still using such older kernel, “default routing” can be setup using the
currently used global address prefix “2000::/3”.
Note: take care about default routing without address filtering on edge routers. Otherwise
unwanted multicast or site-local traffic can leave the edge.
# ip -6 neigh show
fe80::201:23ff:fe45:6789 dev eth0 lladdr 00:01:23:45:67:89 router nud reachable
Example:
Example:
# ip -6 neigh help
Usage: ip neigh { add | del | change | replace } { ADDR [ lladdr LLADDR ]
[ nud { permanent | noarp | stale | reachable } ]
| proxy ADDR } [ dev DEV ]
ip neigh {show|flush} [ to PREFIX ] [ dev DEV ] [ nud STATE ]
Looks like some options are only for IPv4...if you can contribute information about flags
and advanced usage, pls. send.
There are some kind of tunnel mechanism and also some possibilities to setup tunnels.
IPv4 address of your local tunnel endpoint must be static, global unique and
reachable from the foreign tunnel endpoint
A foreign tunnel endpoint which is capable to route your IPv6 prefix to your local
tunnel endpoint (mostly remote manual configuration required)
9.1.3. 6to4-Tunneling
6to4 tunneling (RFC 3056 / Connection of IPv6 Domains via IPv4 Clouds) uses a simple
mechanism to create automatic tunnels. Each node with a global unique IPv4 address is
able to be a 6to4 tunnel endpoint (if no IPv4 firewall prohibits traffic). 6to4 tunneling is
mostly not a one-to-one tunnel. This case of tunneling can be divided into upstream and
downstream tunneling. Also, a special IPv6 address indicates that this node will use 6to4
tunneling for connecting the world-wide IPv6 network
The 6to4 address is defined like following (schema is taken from RFC 3056 / Connection
of IPv6 Domains via IPv4 Clouds):
| 3+13 | 32 | 16 | 64 bits |
+---+------+-----------+--------+--------------------------------+
| FP+TLA | V4ADDR | SLA ID | Interface ID |
| 0x2002 | | | |
+---+------+-----------+--------+--------------------------------+
FP and TLA together (16 bits) have the value 0x2002. V4ADDR is the node's global unique
IPv4 address (in hexadecimal notation). SLA is the subnet identifier (65536 local subnets
possible) and are usable to represent your local network structure.
For gateways, such prefix is generated by normally using SLA “0000” and suffix “::1” (not
a must, can be an arbitrary one with local-scope) and assigned to the 6to4 tunnel
interface. Note that Microsoft Windows uses V4ADDR also for suffix.
The node has to know to which foreign tunnel endpoint its in IPv4 packed IPv6 packets
should be send to. In “early” days of 6to4 tunneling, dedicated upstream accepting
routers were defined. See NSayer's 6to4 information for a list of routers.
Nowadays, 6to4 upstream routers can be found auto-magically using the anycast address
192.88.99.1. In the background routing protocols handle this, see RFC 3068 / An Anycast
Prefix for 6to4 Relay Routers for details.
The downstream (6bone -> your 6to4 enabled node) is not really fix and can vary from
foreign host which originated packets were send to. There exist two possibilities:
Foreign host uses 6to4 and sends packet direct back to your node (see below)
Foreign host sends packets back to the world-wide IPv6 network and depending on
the dynamic routing a relay router create a automatic tunnel back to your node.
from 6to4 to 6to4: is normally directly tunneled between the both 6to4 enabled hosts
Example:
# /sbin/route -A inet6
Example (output is filtered to display only tunnels through virtual interface sit0):
A good additional information about tunnel setup using “ip” is Configuring tunnels with
iproute2 (article) (Mirror).
Usage for creating a tunnel device (but it's not up afterward, also a TTL must be specified
because the default value is 0).
This not very recommended way to add a tunnel because it's a little bit strange. No
problem if adding only one, but if you setup more than one, you cannot easy shutdown
the first ones and leave the others running.
# /sbin/ifconfig sit0 up
Important: DON'T USE THIS, because this setup implicit enable "automatic tunneling"
from anywhere in the Internet, this is a risk, and it should not be advocated.
It's also possible to setup tunnels in Non Broadcast Multiple Access (NBMA) style, it's a
easy way to add many tunnels at once. But none of the tunnel can be numbered (which is
a not required feature).
# /sbin/ifconfig sit0 up
Important: DON'T USE THIS, because this setup implicit enable "automatic tunneling"
from anywhere -A
# /sbin/route in the Internet,
inet6 this is a risk, and
add <prefixtoroute1> gwit should not be advocated.
¬ ::<ipv4addressofforeigntunnel1> dev sit0
# /sbin/route -A inet6 add <prefixtoroute2> gw
¬ ::<ipv4addressofforeigntunnel2> dev sit0
9.3.2. Removing point-to-point tunnels
#
¬
/sbin/route -A inet6 add <prefixtoroute3> gw
::<ipv4addressofforeigntunnel3> dev sit0
Manually not so often needed, but used by scripts for clean shutdown or restart of IPv6
configuration.
9.3.2.2. Using "ifconfig" and "route" (deprecated because not very funny)
Not only the creation is strange, the shutdown also...you have to remove the tunnels in
backorder, means the latest created must be removed first.
1.2.3.4
2002:0102:0304::
Local 6to4 gateways should (but it's not a must, you can choose an arbitrary suffix with
local-scope, if you feel better) always assigned the suffix “::1”, therefore your local 6to4
address will be
2002:0102:0304::1
This is now the recommended way (a TTL must be specified because the default value is
0).
# /sbin/ip tunnel add tun6to4 mode sit ttl <ttldefault> remote any local <localipv4address>
Bring interface up
Add (default) route to the global IPv6 network using the all-6to4-routers IPv4 anycast
address
It was reported that some versions of “ip” (e.g. SuSE Linux 9.0) don't support
IPv4-compatible IPv6 addresses for gateways, in this case the related IPv6 address has to
be used:
9.4.1.2. Using "ifconfig" and "route" and generic tunnel device “sit0”
(deprecated)
This is now deprecated because using the generic tunnel device sit0 doesn't let specify
filtering per device.
# /sbin/ifconfig sit0 up
Add (default) route to the global IPv6 network using the all-6to4-relays IPv4 anycast
address
9.4.2.2. Using “ifconfig” and “route” and generic tunnel device “sit0”
(deprecated)
Shut down generic tunnel device (take care about this, perhaps it's still in use...)
More information in the meantime: RFC 2473 / Generic Packet Tunneling in IPv6
Specification
CONFIG_PROC_FS=y
You need read and sometimes also write access (normally root only) to the /proc-
filesystem
Normally, only entries in /proc/sys/* are writable, the others are readonly and for
information retrieving only.
# cat /proc/sys/net/ipv6/conf/all/forwarding
0
The program “sysctl” is included in package “procps” (on Red Hat Linux systems).
CONFIG_SYSCTL=y
# sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 0
# sysctl -w net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.forwarding = 1
Note: Don't use spaces around the “=” on setting values. Also on multiple values per line,
quote them like e.g.
11.1.2.3. Additionals
Note: There are sysctl versions in the wild which displaying “/” instead of the “.”
Hint: for digging fast into the settings, use the option “-a” (display all entries) in
conjunction with “grep”.
more sophisticated lines with several values: sometimes a header line is displayed
also, if not, have a look into the kernel source to retrieve information about the
meaning of each value...
11.2.2. conf/all/*
Change all the interface-specific settings.
11.2.2.1. conf/all/forwarding
Type: BOOLEAN
In IPv6 you can't control forwarding per device, forwarding control has to be done using
IPv6-netfilter (controlled with ip6tables) rulesets and specify input and output devices
(see Firewalling/Netfilter6 for more). This is different to IPv4, where you are able to control
forwarding per device (decision is made on interface where packet came in).
This also sets all interfaces' Host/Router setting 'forwarding' to the specified value. See
below for details. This referred to as global forwarding.
If this value is 0, no IPv6 forwarding is enabled, packets never leave another interface,
neither physical nor logical like e.g. tunnels.
11.2.3. conf/interface/*
Change special settings per interface.
The functional behaviour for certain settings is different depending on whether local
11.2.3.1. accept_ra
Type: BOOLEAN
Accept Router Advertisements, and autoconfigure this interface with received data.
11.2.3.2. accept_redirects
Type: BOOLEAN
11.2.3.3. autoconf
Type: BOOLEAN
11.2.3.4. dad_transmits
Type: INTEGER
Default: 1
11.2.3.5. forwarding
Type: BOOLEAN
Note: It is recommended to have the same setting on all interfaces; mixed router/host
scenarios are rather uncommon.
11.2.3.6. hop_limit
Type: INTEGER
Default: 64
11.2.3.7. mtu
Type: INTEGER
11.2.3.8. router_solicitation_delay
Type: INTEGER
Default: 1
11.2.3.9. router_solicitation_interval
Type: INTEGER
Default: 4
11.2.3.10. router_solicitations
Type: INTEGER
Default: 3
11.2.4. neigh/default/*
Change default settings for neighbor detection and some special global interval and
threshold values:
11.2.4.1. gc_thresh1
Type: INTEGER
Default: 128
More to be filled.
11.2.4.2. gc_thresh2
Type: INTEGER
Default: 512
More to be filled.
11.2.4.3. gc_thresh3
Type: INTEGER
Default: 1024
Increase this value if you have a lot of interfaces and problem with routes start to act
mysteriously and fail. Or if a running Zebra (routing daemon) reports:
11.2.4.4. gc_interval
Type: INTEGER
Default: 30
More to be filled.
11.2.5. neigh/interface/*
Change special settings per interface for neighbor detection.
11.2.5.1. anycast_delay
Type: INTEGER
Default: 100
More to be filled.
11.2.5.2. gc_stale_time
Type: INTEGER
Default: 60
More to be filled.
11.2.5.3. proxy_qlen
Type: INTEGER
Default: 64
More to be filled.
11.2.5.4. unres_qlen
Type: INTEGER
Default: 3
More to be filled.
11.2.5.5. app_solicit
Type: INTEGER
Default: 0
More to be filled.
11.2.5.6. locktime
Type: INTEGER
Default: 0
More to be filled.
11.2.5.7. retrans_time
Type: INTEGER
Default: 100
More to be filled.
11.2.5.8. base_reachable_time
Type: INTEGER
Default: 30
More to be filled.
11.2.5.9. mcast_solicit
Type: INTEGER
Default: 3
More to be filled.
11.2.5.10. ucast_solicit
Type: INTEGER
Default: 3
More to be filled
11.2.5.11. delay_first_probe_time
Type: INTEGER
Default: 5
More to be filled.
11.2.5.12. proxy_delay
Type: INTEGER
Default: 80
More to be filled.
11.2.6. route/*
Change global settings for routing.
11.2.6.1. flush
11.2.6.2. gc_interval
Type: INTEGER
Default: 30
More to be filled.
11.2.6.3. gc_thresh
Type: INTEGER
Default: 1024
More to be filled.
11.2.6.4. mtu_expires
Type: INTEGER
Default: 600
More to be filled.
11.2.6.5. gc_elasticity
Type: INTEGER
Default: 0
More to be filled.
11.2.6.6. gc_min_interval
Type: INTEGER
Default: 5
More to be filled.
11.2.6.7. gc_timeout
Type: INTEGER
Default: 60
More to be filled.
11.2.6.8. min_adv_mss
Type: INTEGER
Default: 12
More to be filled.
11.2.6.9. max_size
Type: INTEGER
Default: 4096
More to be filled.
11.3.1. ip_*
11.3.1.1. ip_local_port_range
11.3.2. tcp_*
11.3.3. icmp_*
This control settings are not used by IPv6. To enable ICMPv6 rate limiting (which is very
recommended because of the capability of ICMPv6 storms) netfilter-v6 rules must be used.
11.3.4. others
Unknown, but probably not used by IPv6.
11.4.1. if_inet6
Type: One line per addresss containing multiple values
Here all configured IPv6 addresses are shown in a special format. The example displays
for loopback interface only. The meaning is shown below (see “net/ipv6/addrconf.c” for
more).
# cat /proc/net/if_inet6
00000000000000000000000000000001 01 80 10 80 lo
+------------------------------+ ++ ++ ++ ++ ++
| | | | | |
1 2 3 4 5 6
2. Netlink device number (interface index) in hexadecimal (see “ip addr” , too)
6. Device name
11.4.2. ipv6_route
Here all configured IPv6 routes are shown in a special format. The example displays for
loopback interface only. The meaning is shown below (see “net/ipv6/route.c” for more).
# cat /proc/net/ipv6_route
00000000000000000000000000000000 00 00000000000000000000000000000000 00
+------------------------------+ ++ +------------------------------+ ++
| | | |
1 2 3 4
6. Metric in hexadecimal
7. Reference counter
8. Use counter
9. Flags
11.4.3. sockstat6
Type: One line per protocol with description and value
# cat /proc/net/sockstat6
TCP6: inuse 7
UDP6: inuse 2
RAW6: inuse 1
FRAG6: inuse 0 memory 0
11.4.4. tcp6
To be filled.
11.4.5. udp6
To be filled.
11.4.6. igmp6
To be filled.
11.4.7. raw6
To be filled.
11.4.8. ip6_flowlabel
To be filled.
11.4.9. rt6_stats
To be filled.
11.4.10. snmp6
Type: One line per SNMP description and value
SNMP statistics, can be retrieved via SNMP server and related MIB table by network
management software.
11.4.11. ip6_tables_names
Available netfilter6 tables
Example:
# netstat -nlptu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
¬ PID/Program name
tcp 0 0 0.0.0.0:32768 0.0.0.0:* LISTEN
¬ 1258/rpc.statd
tcp 0 0 0.0.0.0:32769 0.0.0.0:* LISTEN
¬ 1502/rpc.mountd
tcp 0 0 0.0.0.0:515 0.0.0.0:* LISTEN
¬ 22433/lpd Waiting
tcp 0 0 1.2.3.1:139 0.0.0.0:* LISTEN
¬ 1746/smbd
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN
¬ 1230/portmap
tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN
¬ 3551/X
tcp 0 0 1.2.3.1:8081 0.0.0.0:* LISTEN
¬ 18735/junkbuster
tcp 0 0 1.2.3.1:3128 0.0.0.0:* LISTEN
¬ 18822/(squid)
tcp 0 0 127.0.0.1:953 0.0.0.0:* LISTEN
¬ 30734/named
tcp 0 0 ::ffff:1.2.3.1:993 :::* LISTEN
¬ 6742/xinetd-ipv6
tcp 0 0 :::13 :::* LISTEN
¬ 6742/xinetd-ipv6
tcp 0 0 ::ffff:1.2.3.1:143 :::* LISTEN
¬ 6742/xinetd-ipv6
tcp 0 0 :::53 :::* LISTEN
¬ 30734/named
tcp 0 0 :::22 :::* LISTEN
¬ 1410/sshd
tcp 0 0 :::6010 :::* LISTEN
¬ 13237/sshd
udp 0 0 0.0.0.0:32768 0.0.0.0:*
¬ 1258/rpc.statd
udp 0 0 0.0.0.0:2049 0.0.0.0:*
¬ -
udp 0 0 0.0.0.0:32770 0.0.0.0:*
¬ 1502/rpc.mountd
udp 0 0 0.0.0.0:32771 0.0.0.0:*
¬ -
udp 0 0 1.2.3.1:137 0.0.0.0:*
¬ 1751/nmbd
udp 0 0 0.0.0.0:137 0.0.0.0:*
¬ 1751/nmbd
udp 0 0 1.2.3.1:138 0.0.0.0:*
¬ 1751/nmbd
udp 0 0 0.0.0.0:138 0.0.0.0:*
¬ 1751/nmbd
udp 0 0 0.0.0.0:33044 0.0.0.0:*
¬ 30734/named
udp 0 0 1.2.3.1:53 0.0.0.0:*
¬ 30734/named
udp 0 0 127.0.0.1:53 0.0.0.0:*
¬ 30734/named
udp 0 0 0.0.0.0:67 0.0.0.0:*
¬ 1530/dhcpd
udp 0 0 0.0.0.0:67 0.0.0.0:*
¬ 1530/dhcpd
udp 0 0 0.0.0.0:32858 0.0.0.0:*
¬ 18822/(squid)
udp 0 0 0.0.0.0:4827 0.0.0.0:*
¬ 18822/(squid)
udp 0 0 0.0.0.0:111 0.0.0.0:*
¬ 1230/portmap
udp 0 0 :::53 :::*
¬ 30734/named
Following packets are sent by a node with layer 2 MAC address “0:12:34:12:34:56” during
autoconfiguration to check whether a potential address is already used by another node
on the link sending this to the solicited-node link-local multicast address.
Node wants to send packages to “2001:0db8:0:1::10” but has no layer 2 MAC address
to send packet, so send solicitation now
Fortunately, in Red Hat Linux since 7.1 a snapshot of my IPv6 scripts is included, this was
and is still further on assisted by Pekka Savola.
Mandrake since version 8.0 also includes an IPv6-enabled initscript package, but a minor
bug still prevents usage (“ifconfig” misses “inet6” before “add”).
/etc/sysconfig/network-scripts/network-functions-ipv6
Auto-magically test:
The version of the library is important if you miss some features. You can get it executing
following (or easier look at the top of the file):
In shown example, the used version is 20011124. Check this against latest information on
initscripts-ipv6 homepage (Mirror) to see what has been changed. You will find there also
a change-log.
14.1.2. Short hint for enabling IPv6 on current RHL 7.1, 7.2,
7.3, ...
NETWORKING_IPV6=yes
Because of the really different configuration and script file structure it is hard (or
impossible) to use the set for Red Hat Linux and clones with this distribution. In versions
8.x they completly change their configuration setup.
IP6ADDR="<ipv6-address>/<prefix>"
IPADDR="<ipv6-address>/<prefix>"
1. Be sure that IPv6 is loaded, either because it is compiled into the kernel or because
the module is loaded. For the latest, three solutions, adding it to /etc/modules, using
the pre-up trick shown later or using kmod (not detailed here).
Jean-Marc V. Liotier's HOWTO for Freenet6 & Debian Users (announced 24.12.2002
on mailinglist [email protected] )
Example:
Support for IPv6 mobility can be enabled in Linux by installing the MIPL2 implementation
found at: http://www.mobile-ipv6.org/
This implementation is compliant with RFC 3775. It is composed of a kernel patch and a
mobility daemon called mip6d. Version 2.0.1 applies on Linux kernel 2.6.15.
Installation and setup are described in the Linux Mobile IPv6 HOWTO: http://gnist.org
/~lars/doc/Mobile-IPv6-HOWTO/Mobile-IPv6-HOWTO.html (temporary link)
16.1.3. Links
Mobile IPv6 for Linux (MIPL) project: http://www.mobile-ipv6.org/
RFC 3776 / Using IPsec to Protect Mobile IPv6 Signaling Between Mobile Nodes and
Home Agents
Attention: no warranty that described rules or examples can really protect your system!
Audit your ruleset after installation, see Section 18.3 for more.
Since kernel version 2.6.20 IPv6 connection tracking is fully working (and does not break
IPv4 NAT anymore like versions before)
17.2. Preparation
This step is only needed if distributed kernel and netfilter doesn't fit your requirements
and new features are available but still not built-in.
# cd /path/to/src
# cd iptables-version
Apply additional IPv6 related patches (still not in the vanilla kernel included)
ah-esp.patch
ipv6-agr.patch.ipv6
ipv6-ports.patch.ipv6
LOG.patch.ipv6
REJECT.patch.ipv6
# make print-extensions
Extensions found: IPv6:owner IPv6:limit IPv6:mac IPv6:multiport
# cd /path/to/src/linux-version-iptables-version/
Edit Makefile
- EXTRAVERSION =
+ EXTRAVERSION = -iptables-version+IPv6-try
Compilation and installing: see the kernel section here and other HOWTOs
# mv /usr/src/linux /usr/src/linux.old
# ln -s /path/to/src/linux-version-iptables-version /usr/src/linux
Rebuild SRPMS
Perhaps it's necessary to create a softlink for iptables libraries where iptables looks for
them
# ln -s /lib/iptables/ /usr/lib/iptables
17.3. Usage
17.3.1. Check for support
Load module, if so compiled
# modprobe ip6_tables
Short
# ip6tables -L
Extended
# ip6tables -n -v --line-numbers -L
Since kernel version 2.6.20 IPv6 connection tracking is well supported and should be
used instead of using stateless filter rules.
Using older kernels (unpatched kernel 2.4.5 and iptables-1.2.2) no type can be specified
17.3.2.8. Rate-limiting
Because it can happen (author already saw it to times) that an ICMPv6 storm will raise up,
you should use available rate limiting for at least ICMPv6 ruleset. In addition logging rules
should also get rate limiting to prevent DoS attacks against syslog and storage of log file
partition. An example for a rate limited ICMPv6 looks like:
Here an example is shown for a ruleset which allows incoming SSH connection from a
specified IPv6 address
To accept tunneled IPv6-in-IPv4 packets, you have to insert rules in your IPv4 firewall
setup relating to such packets, for example
If you have only a static tunnel, you can specify the IPv4 addresses, too, like
VERY RECOMMENDED! For security issues you should really insert a rule which blocks
incoming TCP connection requests. Adapt "-i" option, if other interface names are in use!
Perhaps the rules have to be placed below others, but that is work you have to think
about it. Best way is to create a script and execute rules in a specified way.
17.3.3. Examples
17.3.3.1. Simple example for Fedora Core
Following lines show a simple firewall configuration for Fedora Core 6 (since kernel
version 2.6.20). It was modfied from the default one (generated by system-config-firewall)
for supporting connection tracking and return the proper ICMPv6 code for rejects.
Incoming SSH (port 22) connections are allowed.
File: /etc/sysconfig/ip6tables
File: /etc/sysconfig/iptables
Usage:
# chkconfig iptables on
# chkconfig ip6tables on
Following lines show a more sophisticated but still stateless filter setup as an example.
Happy netfilter6 ruleset creation....
# ip6tables -n -v -L
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 extIN all sit+ * ::/0 ::/0
4 384 intIN all eth0 * ::/0 ::/0
0 0 ACCEPT all * * ::1/128 ::1/128
0 0 ACCEPT all lo * ::/0 ::/0
0 0 LOG all * * ::/0 ::/0
¬ LOG flags 0 level 7 prefix `INPUT-default:'
0 0 DROP all * * ::/0 ::/0
More to be filled...
More to be filled...
Note: strobe isn't really developed further on, the shown version number isn't the right
one.
Info: More detailed information concerning IPv6 Security can be found here:
Using AES-128 for encryption and SHA1 for authentication, this mode decreases the MTU
by 42 octets.
modes. Here, the complete IP packet is being encrypted and gets a new IP header
prepended, all together constituing a new IP packet (this mechanism is also known as
"encapsulation")
This mode usually decreases the MTU by 40 octets from the MTU of transport mode. I.e.
using AES-128 for encryption and SHA1 for authentication 82 octets less than the normal
MTU.
Currently, two different IKE daemons are available for Linux, which totally differ in
configuration and usage.
I prefer “pluto” from the *S/WAN implementation because of the easier and
one-config-only setup.
19.3.1.1. Manipulation of the IPsec SA/SP database with the tool “setkey”
“setkey” is important to define the security policy (SP) for the kernel.
File: /etc/racoon/setkey.sh
#!/sbin/setkey -f
flush;
spdflush;
spdadd 2001:db8:1:1::1 2001:db8:2:2::2 any -P out ipsec esp/transport//require;
spdadd 2001:db8:2:2::2 2001:db8:1:1::1 any -P in ipsec esp/transport//require;
#!/sbin/setkey -f
flush;
spdflush;
spdadd 2001:db8:1:1::1 2001:db8:2:2::2 any -P out ipsec
¬ esp/tunnel/2001:db8:1:1::1-2001:db8:2:2::2/require;
spdadd 2001:db8:2:2::2 2001:db8:1:1::1 any -P in ipsec
¬ esp/tunnel/2001:db8:2:2::2-2001:db8:1:1::1/require;
For the other peer, you have to replace “in” with “out”.
“racoon” requires a configuration file for proper execution. It includes the related settings
to the security policy, which should be set up previously using “setkey”.
File: /etc/racoon/racoon.conf
listen
{
isakmp 2001:db8:1:1::1;
}
remote 2001:db8:2:2::2
{
exchange_mode main;
lifetime time 24 hour;
proposal
{
encryption_algorithm 3des;
hash_algorithm md5;
authentication_method pre_shared_key;
dh_group 2;
}
}
# gateway-to-gateway
File: /etc/racoon/psk.txt
2001:db8:2:2::2 verysecret
At least the daemon needs to be started. For the first time, use debug and foreground
mode. The following example shows a successful IKE phase 1 (ISAKMP-SA) and 2
(IPsec-SA) negotiation:
# racoon -F -v -f /etc/racoon/racoon.conf
Foreground mode.
2005-01-01 20:30:15: INFO: @(#)ipsec-tools 0.3.3 (http://ipsec-tools.sourceforge.net)
2005-01-01 20:30:15: INFO: @(#)This product linked
¬ OpenSSL 0.9.7a Feb 19 2003 (http://www.openssl.org/)
2005-01-01 20:30:15: INFO: 2001:db8:1:1::1[500] used as isakmp port (fd=7)
2005-01-01 20:31:06: INFO: IPsec-SA request for 2001:db8:2:2::2
¬ queued due to no phase1 found.
2005-01-01 20:31:06: INFO: initiate new phase 1 negotiation:
¬ 2001:db8:1:1::1[500]<=>2001:db8:2:2::2[500]
2005-01-01 20:31:06: INFO: begin Identity Protection mode.
2005-01-01 20:31:09: INFO: ISAKMP-SA established
¬ 2001:db8:1:1::1[500]-2001:db8:2:2::2[500] spi:da3d3693289c9698:ac039a402b2db401
2005-01-01 20:31:09: INFO: initiate new phase 2 negotiation:
¬ 2001:6f8:900:94::2[0]<=>2001:db8:2:2::2[0]
2005-01-01 20:31:10: INFO: IPsec-SA established:
¬ ESP/Tunnel 2001:db8:2:2::2->2001:db8:1:1::1 spi=253935531(0xf22bfab)
2005-01-01 20:31:10: INFO: IPsec-SA established:
¬ ESP/Tunnel 2001:db8:1:1::1->2001:db8:2:2::2 spi=175002564(0xa6e53c4)
Each direction got its own IPsec-SA (like defined in the IPsec standard). With “tcpdump”
on the related interface, you will see as result of an IPv6 ping:
# setkey -D
2001:db8:1:1::1 2001:db8:2:2::2
esp mode=tunnel spi=175002564(0x0a6e53c4) reqid=0(0x00000000)
E: 3des-cbc bd26bc45 aea0d249 ef9c6b89 7056080f 5d9fa49c 924e2edd
A: hmac-md5 60c2c505 517dd8b7 c9609128 a5efc2db
seq=0x00000000 replay=4 flags=0x00000000 state=mature
created: Jan 1 20:31:10 2005 current: Jan 1 20:40:47 2005
diff: 577(s) hard: 3600(s) soft: 2880(s)
last: Jan 1 20:35:05 2005 hard: 0(s) soft: 0(s)
current: 540(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 3 hard: 0 soft: 0
sadb_seq=1 pid=22358 refcnt=0
2001:db8:2:2::2 2001:db8:1:1::1
esp mode=tunnel spi=253935531(0x0f22bfab) reqid=0(0x00000000)
E: 3des-cbc c1ddba65 83debd62 3f6683c1 20e747ac 933d203f 4777a7ce
A: hmac-md5 3f957db9 9adddc8c 44e5739d 3f53ca0e
seq=0x00000000 replay=4 flags=0x00000000 state=mature
created: Jan 1 20:31:10 2005 current: Jan 1 20:40:47 2005
diff: 577(s) hard: 3600(s) soft: 2880(s)
last: Jan 1 20:35:05 2005 hard: 0(s) soft: 0(s)
current: 312(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 3 hard: 0 soft: 0
sadb_seq=0 pid=22358 refcnt=0
A major difference to “racoon”, only one configuration file is required. Also, an initscript
exists for automatic setup after booting.
The configuration is very similar to the IPv4 one, only one important option is necessary.
File: /etc/ipsec.conf
# basic configuration
config setup
# Debug-logging controls: "none" for (almost) none, "all" for lots.
# klipsdebug=none
# plutodebug="control parsing"
include /etc/ipsec.d/examples/no_oe.conf
conn ipv6-p1-p2
connaddrfamily=ipv6 # Important for IPv6!
left=2001:db8:1:1::1
right=2001:db8:2:2::2
authby=secret
esp=aes128-sha1
ike=aes128-sha-modp1024
type=transport
#type=tunnel
compress=no
#compress=yes
auto=add
#auto=start
File: /etc/ipsec.secrets
If installation of Openswan was successfully, an initscript should exist for starting IPsec,
simply run (on each peer):
# /etc/rc.d/init.d/ipsec start
Afterwards, start this connection on one peer. If you saw the line “IPsec SA established”,
all worked fine.
Because *S/WAN and setkey/racoon do use the same IPsec implementation in Linux 2.6.x
kernel, “setkey” can be used here too to show current active parameters:
# setkey -D
2001:db8:1:1::1 2001:db8:2:2::2
esp mode=transport spi=2844489488(0xa98b7710) reqid=16385(0x00004001)
E: aes-cbc 082ee274 2744bae5 7451da37 1162b483
A: hmac-sha1 b7803753 757417da 477b1c1a 64070455 ab79082c
seq=0x00000000 replay=64 flags=0x00000000 state=mature
created: Jan 1 21:16:32 2005 current: Jan 1 21:22:20 2005
diff: 348(s) hard: 0(s) soft: 0(s)
last: hard: 0(s) soft: 0(s)
current: 0(bytes) hard: 0(bytes) soft: 0(bytes)
allocated: 0 hard: 0 soft: 0
# ip xfrm policy
...
# ip xfrm state
...
Additional infos:
more to be filled...
Note: unlike in IPv4 current versions doesn't allow to bind a server socket to dedicated
IPv6 addresses, so only any or none are valid. Because this can be a security issue, check
the Access Control List (ACL) section below, too!
options {
# sure other options here, too
listen-on-v6 { any; };
};
options {
# sure other options here, too
listen-on-v6 { none; };
};
acl internal-net {
127.0.0.1;
1.2.3.0/24;
2001:0db8:100::/56;
::1/128;
::ffff:1.2.3.4/128;
};
acl ns-internal-net {
1.2.3.4;
1.2.3.5;
2001:0db8:100::4/128;
2001:0db8:100::5/128;
};
This ACLs can be used e.g. for queries of clients and transfer zones to secondary
name-servers. This prevents also your caching name-server to be used from outside using
IPv6.
options {
# sure other options here, too
listen-on-v6 { none; };
allow-query { internal-net; };
allow-transfer { ns-internal-net; };
};
It's also possible to set the allow-query and allow-transfer option for most of single zone
definitions, too.
AAAA and reverse IP6.INT: specified in RFC 1886 / DNS Extensions to support IP
version 6, usable since BIND version 4.9.6
A6, DNAME (DEPRECATED NOW!) and reverse IP6.ARPA: specified in RFC 2874 /
DNS Extensions to Support IPv6 Address Aggregation and Renumbering, usable
since BIND 9, but see also an information about the current state at Domain Name
System Extension (dnsext)
Perhaps filled later more content, for the meantime take a look at given RFCs and
A6, DNAME (DEPRECATED NOW!) and reverse IP6.ARPA: take a look into chapter 4
and 6 of the BIND 9 Administrator Reference Manual (ARM) distributed with the
bind-package or get this here: BIND manual version 9.3
Because IP6.INT is deprecated (but still in use), a DNS server which will support IPv6
information has to serve both reverse zones.
Because there are some troubles around using the new formats, current best practice is:
AAAA
Specifying a dedicated server for the query, an IPv6 connect can be forced:
If you see such entries in the log, check whether requests from this client should be
allowed and perhaps review your ACL configuration.
Some Linux distribution contain an extra package for the IPv6 enabled xinetd, some
others start the IPv6-enabled xinetd if following variable is set: NETWORKING_IPV6="yes",
mostly done by /etc/sysconfig/network (only valid for Red Hat like distributions). In newer
releases, one binary supports IPv4 and IPv6.
If you enable a built-in service like e.g. daytime by modifying the configuration file in
/etc/xinetd.d/daytime like
After restarting the xinetd you should get a positive result like:
Shown example also displays an IMAP and IMAP-SSL IPv4-only listening xinetd.
Note: earlier versions had a problem that an IPv4-only xinetd won't start on an
IPv6-enabled node and also the IPv6-enabled xinetd won't start on an IPv4-only node.
This is known to be fixed in later versions, at least version 2.3.11.
Listen [2001:0db8:100::1]:80
<VirtualHost [2001:0db8:100::1]:80>
ServerName ipv6only.yourdomain.yourtopleveldomain
# ...sure more config lines
</VirtualHost>
Listen [2001:0db8:100::2]:80
Listen 1.2.3.4:80
<VirtualHost [2001:0db8:100::2]:80 1.2.3.4:80>
ServerName ipv6andipv4.yourdomain.yourtopleveldomain
# ...sure more config lines
</VirtualHost>
Apache2 supports a method called “sendfile” to speedup serving data. Some NIC
drivers also support offline checksumming. In some cases, this can lead to
connection problems and invalid TCP checksums. In this cases, disable “sendfile”
either by recompiling using configure option “--without-sendfile” or by using the
"EnableSendfile off" directive in configuration file.
You can specify some information and flags which should be contained in the
advertisement. Common used are
Prefix (needed)
Radvd's config file is normally /etc/radvd.conf. An simple example looks like following:
interface eth0 {
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
prefix 2001:0db8:0100:f101::/64 {
AdvOnLink on;
AdvAutonomous on;
AdvRouterAddr on;
};
};
Version since 0.6.2pl3 support the automatic (re)-generation of the prefix depending on an
IPv4 address of a specified interface. This can be used to distribute advertisements in a
LAN after the 6to4 tunneling has changed. Mostly used behind a dynamic dial-on-demand
Linux router. Because of the sure shorter lifetime of such prefix (after each dial-up,
another prefix is valid), the lifetime configured to minimal values:
interface eth0 {
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 10;
prefix 0:0:0:f101::/64 {
AdvOnLink off;
AdvAutonomous on;
AdvRouterAddr on;
Base6to4Interface ppp0;
AdvPreferredLifetime 20;
AdvValidLifetime 30;
};
};
This results on client side in (assuming, ppp0 has currently 1.2.3.4 as local IPv4 address):
Because a small lifetime was defined, such prefix will be thrown away quickly, if no
Additional note: if you do not used special 6to4 support in initscripts, you have to setup a
special route on the internal interface on the router, otherwise you will get some
backrouting problems. for the example showh here:
This route needs to be replaced every time the prefix changes, which is the case after a
new IPv4 address was assigned to the dial-up interface.
21.4.2. Debugging
A program called “radvdump” can help you looking into sent or received advertisements.
Simple to use:
# radvdump
Router advertisement from fe80::280:c8ff:feb9:cef9 (hoplimit 255)
AdvCurHopLimit: 64
AdvManagedFlag: off
AdvOtherConfigFlag: off
AdvHomeAgentFlag: off
AdvReachableTime: 0
AdvRetransTimer: 0
Prefix 2002:0102:0304:f101::/64
AdvValidLifetime: 30
AdvPreferredLifetime: 20
AdvOnLink: off
AdvAutonomous: on
AdvRouterAddr: on
Prefix 2001:0db8:100:f101::/64
AdvValidLifetime: 2592000
AdvPreferredLifetime: 604800
AdvOnLink: on
AdvAutonomous: on
AdvRouterAddr: on
AdvSourceLLAddress: 00 80 12 34 56 78
Output shows you each advertisement package in readable format. You should see your
configured values here again, if not, perhaps it's not your radvd which sends the
advertisement...look for another router on the link (and take the LLAddress, which is the
MAC address for tracing).
You can specify more information than by using radvd. The are most similar to IPv4 DHCP
server.
After a proper configuration, the daemon reacts on received ICMPv6 multicast packets
sent by a client to address ff02::16
dhcp6s's config file is normally /etc/dhcp6s.conf. An simple example looks like following:
interface eth0 {
server-preference 255;
renew-time 60;
rebind-time 90;
prefer-life-time 130;
valid-life-time 200;
allow rapid-commit;
option dns_servers 2001:db8:0:f101::1 sub.domain.example;
link AAA {
range 2001:db8:0:f101::1000 to 2001:db8:0:f101::ffff/64;
prefix 2001:db8:0:f101::/64;
};
};
dhcp6c's config file is normally /etc/dhcp6c.conf. An simple example looks like following:
interface eth0 {
send rapid-commit;
request domain-name-servers;
};
21.5.3. Usage
21.5.3.1. dhcpv6_server
21.5.3.2. dhcpv6_client
# # dhcp6c -f eth0
21.5.4. Debugging
21.5.4.1. dhcpv6_server
The server has one foreground and two debug toggles (both should be used for
debugging), here is an example:
# dhcp6s -d -D -f eth0
21.5.4.2. dhcpv6_client
The client has one foreground and two debug toggles, here is an example:
# dhcp6c -d -f eth0
Oct/03/2005 17:18:16 dhcpv6 doesn't support hardware type 776
Oct/03/2005 17:18:16 doesn't support sit0 address family 0
Oct/03/2005 17:18:16 netlink_recv_rtgenmsg error
Oct/03/2005 17:18:16 netlink_recv_rtgenmsg error
Oct/03/2005 17:18:17 status code for this address is: success
Oct/03/2005 17:18:17 status code: success
Oct/03/2005 17:18:17 netlink_recv_rtgenmsg error
Oct/03/2005 17:18:17 netlink_recv_rtgenmsg error
Oct/03/2005 17:18:17 assigned address 2001:db8:0:f101::1002 prefix len is not in any RAs pref
Oct/03/2005 17:18:17 renew time 60, rebind time 9
21.6. tcp_wrapper
tcp_wrapper is a library which can help you to protect service against misuse.
Each service which is called by xinetd (if xinetd is compiled using tcp_wrapper
library)
21.6.3. Usage
tcp_wrapper is controlled by two files name /etc/hosts.allow and /etc/hosts.deny. For
more information see
$ man hosts.allow
In this file, each service which should be positive filtered (means connects are accepted)
need a line.
Note: there are broken implementations around, which uses following broken IPv6
network description: [2001:0db8:100:200::/64]. Hopefully, such versions will be fixed soon.
This file contains all negative filter entries and should normally deny the rest using
ALL: ALL
If this node is a more sensible one you can replace the standard line above with this one,
but this can cause a DoS attack (load of mailer and spool directory), if too many connects
were made in short time. Perhaps a logwatch is better for such issues.
21.6.4. Logging
Depending on the entry in the syslog daemon configuration file /etc/syslog.conf the
tcp_wrapper logs normally into /var/log/secure.
A refused connection via IPv4 to an xinetd covered daytime service produces a line like
following example
¬ from=::ffff:1.2.3.4
Jan 2 20:32:06 gate xinetd-ipv6[12346]: FAIL: daytime-stream libwrap
from=2001:0db8:100:200::212:34ff:fe12:3456
A refused connection via IPv4 to an dual-listen sshd produces a line like following
example
A permitted connection via IPv4 to an xinetd covered daytime service produces a line like
following example
A permitted connection via IPv4 to an dual-listen sshd produces a line like following
example
Jan 2 20:43:10 gate sshd[21975]: Accepted password for user from ::ffff:1.2.3.4
¬ port 33381 ssh2
Jan 2 20:42:19 gate sshd[12345]: Accepted password for user
from 2001:0db8:100:200::212:34ff:fe12:3456 port 33380 ssh2
21.7. vsftpd
21.7.1. Listening on IPv6 addresses
Edit the configuration file, ususally /etc/vsftpd/vsftpd.conf, and adjust the listen option
like
listen_ipv6=yes
That's all.
21.8. proftpd
<VirtualHost 192.0.2.1>
...
Bind 2001:0DB8::1
...
</VirtualHost>
That's all.
RFC 3542 / Advanced Sockets Application Program Interface (API) for IPv6
Following contents of this section is contributed by John Wenker, Sr. Software Engineer
Performance Technologies San Diego, CA USA http://www.pt.com/.
This section describes how to write IPv6 client-server applications under the Linux
operating system. First thing's first, and credit must be given where it is due. The
information contained in this section is derived from Chapters 2 through 4 of IPv6
Network Programming by Jun-ichiro itojun Hagino (ISBN 1-55558-318-0). The reader is
encouraged to consult that book for more detailed information. It describes how to
convert IPv4 applications to be IPv6 compatible in a protocol-independent way, and
describes some of the common problems encountered during the conversion along with
suggested solutions. At the time of this writing, this is the only book of which the author
is aware that specifically addresses how to program IPv6 applications [since writing this
section, the author has also become aware of the Porting applications to IPv6 HowTo by
Eva M. Castro at Since writing this HowTo, the author has also become aware of the
Porting applications to IPv6 HowTo by Eva M. Castro at http://jungla.dit.upm.es/~ecastro
/IPv6-web/ipv6.html]. Unfortunately, of the almost 360 pages in the book, maybe 60 are
actually useful (the chapters mentioned). Nevertheless, without the guidance of that book,
the author would have been unable to perform his job duties or compose this HowTo.
While most (but certainly not all) of the information in the Hagino book is available via the
Linux 'man' pages, application programmers will save a significant amount of time and
frustration by reading the indicated chapters of the book rather than searching through
the 'man' pages and online documentation.
Other than the Hagino book, any other information presented in this HowTo was obtained
through trial and error. Some items or explanations may not be entirely “correct” in the
grand IPv6 scheme, but seem to work in practical application.
The discussion that follows assumes the reader is already experienced with the traditional
TCP/IP socket API. For more information on traditional socket programming, the
Internetworking with TCP/IP series of textbooks by Comer & Stevens is hard to beat,
specifically Volume III: Client-Server Programming and Applications, Linux/POSIX Sockets
Version (ISBN 0-13-032071-4). This HowTo also assumes that the reader has had at least a
bare basic introduction to IPv6 and in particular the addressing scheme for network
addresses (see Section 2.3).
In IPv4, network addresses are 32 bits long and define a network node. Addresses are
written in dotted decimal notation, such as 192.0.2.1, where each number represents eight
bits of the address. Such an IPv4 address is represented by the struct sockaddr_in data
type, which is defined in <netinet/in.h>.
struct sockaddr_in
{
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
/* Plus some padding for alignment */
};
The sin_family component indicates the address family. For IPv4 addresses, this is always
set to AF_INET. The sin_addr field contains the 32-bit network address (in network byte
order). Finally, the sin_port component represents the transport layer port number (in
network byte order). Readers should already be familiar with this structure, as this is the
standard IPv4 address structure.
The biggest feature of IPv6 is its increased address space. Instead of 32-bit network
addresses, IPv6 allots 128 bits to an address. Addresses are written in colon-hex notation
of the form fe80::2c0:8cff:fe01:2345, where each hex number separated by colons
represents 16 bits of the address. Two consecutive colons indicate a string of consecutive
zeros for brevity, and at most only one double-colon may appear in the address. IPv6
addresses are represented by the struct sockaddr_in6 data type, also defined in
<netinet/in.h>.
struct sockaddr_in6
{
sa_family_t sin6_family;
in_port_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
uint32_t sin6_scope_id;
};
The sin6_family, sin6_port, and sin6_addr components of the structure have the same
meaning as the corresponding fields in the sockaddr_in structure. However, the
sin6_family member is set to AF_INET6 for IPv6 addresses, and the sin6_addr field holds a
128-bit address instead of only 32 bits.
The sin6_flowinfo field is used for flow control, but is not yet standardized and can be
ignored.
The sin6_scope_id field has an odd use, and it seems (at least to this naïve author) that
the IPv6 designers took a huge step backwards when devising this. Apparently, 128-bit
IPv6 network addresses are not unique. For example, it is possible to have two hosts, on
separate networks, with the same link-local address (see Figure 1). In order to pass
information to a specific host, more than just the network address is required; the scope
identifier must also be specified. In Linux, the network interface name is used for the
scope identifier (e.g. “eth0”) [be warned that the scope identifier is implementation
dependent!]. Use the ifconfig(1M) command to display a list of active network interfaces.
A colon-hex network address can be augmented with the scope identifier to produce a
"scoped address”. The percent sign ('%') is used to delimit the network address from the
scope identifier. For example, fe80::1%eth0 is a scoped IPv6 address where fe80::1
represents the 128-bit network address and eth0 is the network interface (i.e. the scope
identifier). Thus, if a host resides on two networks, such as Host B in example below, the
user now has to know which path to take in order to get to a particular host. In Figure 1,
Host B addresses Host A using the scoped address fe80::1%eth0, while Host C is
addressed with fe80::1%eth1.
Host A (fe80::1) ---- eth0 ---- Host B ---- eth1 ---- Host C (fe80::1)
Getting back to the sockaddr_in6 structure, its sin6_scope_id field contains the index of
the network interface on which a host may be found. Server applications will have this
field set automatically by the socket API when they accept a connection or receive a
datagram. For client applications, if a scoped address is passed as the node parameter to
getaddrinfo(3) (described later in this HowTo), then the sin6_scope_id field will be filled in
correctly by the system upon return from the function; if a scoped address is not
supplied, then the sin6_scope_id field must be explicitly set by the client software prior to
attempting to communicate with the remote server. The if_nametoindex(3) function is
used to translate a network interface name into its corresponding index. It is declared in
<net/if.h>.
As any programmer familiar with the traditional TCP/IP socket API knows, several socket
functions deal with "generic" pointers. For example, a pointer to a generic struct sockaddr
data type is passed as a parameter to some socket functions (such as connect(2) or
bind(2)) rather than a pointer to a specific address type. Be careful... the sockaddr_in6
structure is larger than the generic sockaddr structure! Thus, if your program receives a
generic address whose actual type is unknown (e.g. it could be an IPv4 address structure
or an IPv6 address structure), you must supply sufficient storage to hold the entire
address. The struct sockaddr_storage data type is defined in <bits/socket.h> for this
purpose [do not #include this file directly within an application; use <sys/socket.h> as
usual, and <bits/socket.h> will be implicitly included].
For example, consider the recvfrom(2) system call, which is used to receive a message
from a remote peer. Its function prototype is:
The from parameter points to a generic sockaddr structure. If data can be received from an
IPv6 peer on the socket referenced by s, then from should point to a data type of struct
sockaddr_storage, as in the following dummy example:
/*
** Read a message from a remote peer, and return a buffer pointer to
** the caller.
**
** 's' is the file descriptor for the socket.
*/
char *rcvMsg( int s )
{
static char bfr[ 1025 ]; /* Where the msg is stored. */
ssize_t count;
struct sockaddr_storage ss; /* Where the peer adr goes. */
socklen_t sslen;
sslen = sizeof( ss );
count = recvfrom( s,
bfr,
sizeof( bfr ) - 1,
0,
(struct sockaddr*) &ss,
&sslen );
bfr[ count ] = '\0'; /* Null-terminates the message. */
return bfr;
} /* End rcvMsg() */
The primary lookup function in the new socket API is getaddrinfo(3). Its prototype is as
follows.
The node parameter is a pointer to the hostname or IP address being translated. The
referenced string can be a hostname, IPv4 dotted decimal address, or IPv6 colon-hex
address (possibly scoped). The service parameter is a pointer to the transport layer's
service name or port number. It can be specified as a name found in /etc/services or a
decimal number. getaddrinfo(3) resolves the host/service combination and returns a list of
address records; a pointer to the list is placed in the location pointed at by res. For
example, suppose a host can be identified by both an IPv4 and IPv6 address, and that the
indicated service has both a TCP entry and UDP entry in /etc/services. In such a scenario,
it is not inconceivable that four address records are returned; one for TCP/IPv6, one for
UDP/IPv6, one for TCP/IPv4, and one for UDP/IPv4.
The definition for struct addrinfo is found in <netdb.h> (as is the declaration for
getaddrinfo(3) and the other functions described in this section). The structure has the
following format:
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
Consult the 'man' page for getaddrinfo(3) for detailed information about the various fields;
this HowTo only describes a subset of them, and only to the extent necessary for normal
IPv6 programming.
The ai_family, ai_socktype, and ai_protocol fields have the exact same meaning as the
parameters to the socket(2) system call. The ai_family field indicates the protocol family
(not the address family) associated with the record, and will be PF_INET6 for IPv6 or
PF_INET for IPv4. The ai_socktype parameter indicates the type of socket to which the
record corresponds; SOCK_STREAM for a reliable connection-oriented byte-stream or
SOCK_DGRAM for connectionless communication. The ai_protocol field specifies the
underlying transport protocol for the record.
The ai_addr field points to a generic struct sockaddr object. Depending on the value in
the ai_family field, it will point to either a struct sockaddr_in (PF_INET) or a struct
sockaddr_in6 (PF_INET6). The ai_addrlen field contains the size of the object pointed at
by the ai_addr field.
As mentioned, getaddrinfo(3) returns a list of address records. The ai_next field points to
the next record in the list.
The hints parameter to getaddrinfo(3) is also of type struct addrinfo and acts as a filter for
the address records returned in res. If hints is NULL, all matching records are returned;
but if hints is non-NULL, the referenced structure gives "hints" to getaddrinfo(3) about
which records to return. Only the ai_flags, ai_family, ai_socktype, and ai_protocol fields
are significant in the hints structure, and all other fields should be set to zero.
Programs can use hints->ai_family to specify the protocol family. For example, if it is set
to PF_INET6, then only IPv6 address records are returned. Likewise, setting
hints->ai_family to PF_INET results in only IPv4 address records being returned. If an
application wants both IPv4 and IPv6 records, the field should be set to PF_UNSPEC.
The hints->socktype field can be set to SOCK_STREAM to return only records that
correspond to connection-oriented byte streams, SOCK_DGRAM to return only records
corresponding to connectionless communication, or 0 to return both.
For the Internet protocols, there is only one protocol associated with connection-oriented
sockets (TCP) and one protocol associated with connectionless sockets (UDP), so setting
hints->ai_socktype to SOCK_STREAM or SOCK_DGRAM is the same as saying, "Give me
only TCP records," or "Give me only UDP records," respectively. With that in mind, the
hints->ai_protocol field isn't really that important with the Internet protocols, and pretty
much mirrors the hints->ai_socktype field. Nevertheless, hints->ai_protocol can be set to
IPPROTO_TCP to return only TCP records, IPPROTO_UDP to return only UDP records, or 0
for both.
The node or service parameter to gethostbyname(3) can be NULL, but not both. If node is
NULL, then the ai_flags field of the hints parameter specifies how the network address in
a returned record is set (i.e. the sin_addr or sin6_addr field of the object pointed at by the
ai_addr component in a returned record). If the AI_PASSIVE flag is set in hints, then the
returned network addresses are left unresolved (all zeros). This is how server applications
would use getaddrinfo(3). If the flag is not set, then the address is set to the local
loopback address (::1 for IPv6 or 127.0.0.1 for IPv4). This is one way a client application
can specify that the target server is running on the same machine as the client. If the
service parameter is NULL, the port number in the returned address records remains
unresolved.
The getaddrinfo(3) function returns zero on success, or an error code. In the case of an
error, the gai_strerror(3) function is used to obtain a character pointer to an error message
corresponding to the error code, just like strerror(3) does in the standard 'C' library.
Once the address list is no longer needed, it must be freed by the application. This is
done with the freeaddrinfo(3) function.
The last function that will be mentioned in this section is getnameinfo(3). This function is
the inverse of getaddrinfo(3); it is used to create a string representation of the hostname
and service from a generic struct sockaddr data object. It has the following prototype.
The sa parameter points to the address structure in question, and salen contains its size.
The host parameter points to a buffer where the null-terminated hostname string is
placed, and the hostlen parameter is the size of that buffer. If there is no hostname that
corresponds to the address, then the network address (dotted decimal or colon-hex) is
placed in host. Likewise, the serv parameter points to a buffer where the null-terminated
service name string (or port number) is placed, and the servlen parameter is the size of
that buffer. The flags parameter modifies the function's behavior; in particular, the
NI_NUMERICHOST flag indicates that the converted hostname should always be formatted
in numeric form (i.e. dotted decimal or colon-hex), and the NI_NUMERICSERV flag
indicates that the converted service should always be in numeric form (i.e. the port
number).
The symbols NI_MAXHOST and NI_MAXSERV are available to applications and represent
the maximum size of any converted hostname or service name, respectively. Use these
when declaring output buffers for getnameinfo(3).
For security reasons that this author won't pretend to understand, "IPv4 mapped
addresses" should not be allowed in IPv6-capable server applications. To put it in terms
that everyone can understand, this simply means that a server should not accept IPv4
traffic on an IPv6 socket (an otherwise legal operation). An IPv4 mapped address is a
mixed-format address of the form:
::ffff:192.0.2.1
where the first portion is in IPv6 colon-hex format and the last portion is in IPv4 dotted
decimal notation. The dotted decimal IPv4 address is the actual network address, but it is
being mapped into an IPv6 compatible format.
To prevent IPv4 mapped addresses from being accepted on an IPv6 socket, server
applications must explicitly set the IPV6_V6ONLY socket option on all IPv6 sockets
created [the Hagino book implies that this is only a concern with server applications.
However, it has been observed during testing that if a client application uses an IPv4
mapped address to specify the target server, and the target server has IPv4 mapped
addresses disabled, the connection still completes regardless. On the server side, the
connection endpoint is an IPv4 socket as desired; but on the client side, the connection
endpoint is an IPv6 socket. Setting the IPV6_V6ONLY socket option on the client side as
well as the server side prevents any connection from being established at all.]. There's
only one problem. Apparently, IPV6_V6ONLY isn't defined on all systems [or at least it
wasn't in 2005 when the Hagino book was written]. The server example at the end of this
chapter provides a method for handling this problem.
If IPv4 traffic cannot be handled on IPv6 sockets, then that implies that server applications
must open both an IPv4 and IPv6 socket for a particular network service if it wants to
handle requests from either protocol. This goes back to the flexibility issue mentioned
earlier. If getaddrinfo(3) returns multiple address records, then server applications should
traverse the list and open a passive socket for each address provided.
::1 localhost
127.0.0.1 localhost
fe80::2c0:8cff:fe01:2345 pt141
192.0.2.1 pt141
The "localhost" and "pt141" hostnames can be translated to either an IPv4 or IPv6 network
address. So, for example, if "pt141" is passed as the node parameter to getaddrinfo(3), the
function returns both an IPv4 and IPv6 address record for the host (assuming the
behavior hasn't been modified by the hints parameter). Unfortunately, a scoped address
cannot be used in /etc/hosts. Doing so results in getaddrinfo(3) returning only the IPv4
record.
Suppose a machine has the IPv4 address 192.0.2.1. A client application running on that
machine can connect to a server application on the same machine by using either the
local loopback address (127.0.0.1) or the network address (192.0.2.1) as the target server.
Much to this author's surprise (and dismay), it turns out that an IPv6 client application
cannot connect to a server application on the same machine if it uses the network address
of that machine as the target; it must use the local loopback address (::1).
Although the sample source code is believed to be free of errors, the author
makes no guarantees as to its reliability, especially considering that some error
paths were intentionally omitted for brevity. Use it at your own risk!
When you get right down to it, there really aren't that many differences between IPv4 and
IPv6 applications. The trick is to code IPv6 applications in a protocol-independent
manner, such that they can handle both IPv4 and IPv6 simultaneously and transparently.
This sample application does just that. The only protocol-dependent code in the example
occurs when printing network addresses in verbose mode; but only after the ai_family
field in the addrinfo structure has been checked, so the programs know exactly what type
of address they're handling at the time.
The server code is found in file tod6d.c (time-of-day IPv6 daemon). Once built, the server
may be started using the following command syntax (assuming tod6d is the executable
file):
ARGUMENTS:
service
OPTIONS:
-v
The server handles both TCP and UDP requests on the network. The server source code
contained in tod6d.c follows:
/******************************************************************************
* File: tod6d.c
fprintf( stderr, \
"%s (line %d): System call ERROR - %s.\n", \
pgmName, \
__LINE__, \
strerror( errno ) ); \
exit( 1 ); \
} /* End IF system call failed. */ \
} while ( false )
/******************************************************************************
* Function: main
*
* Description:
* Set up a time-of-day server and handle network requests. This server
* handles both TCP and UDP requests.
*
* Parameters:
* The usual argc and argv parameters to a main() function.
*
* Return Value:
* This is a daemon program and never returns. However, in the degenerate
* case where no sockets are created, the function returns zero.
******************************************************************************/
int main( int argc,
char *argv[ ] )
{
int opt;
const char *service = DFLT_SERVICE;
int tSckt[ MAXTCPSCKTS ]; /* Array of TCP socket descriptors. */
size_t tScktSize = MAXTCPSCKTS; /* Size of uSckt (# of elements). */
int uSckt[ MAXUDPSCKTS ]; /* Array of UDP socket descriptors. */
size_t uScktSize = MAXUDPSCKTS; /* Size of uSckt (# of elements). */
/*
** Set the program name (w/o directory prefix).
*/
pgmName = strrchr( argv[ 0 ], '/' );
pgmName = pgmName == NULL ? argv[ 0 ] : pgmName + 1;
/*
** Process command options.
*/
opterr = 0; /* Turns off "invalid option" error messages. */
while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) >= 0 )
{
switch ( opt )
{
case 'v': /* Verbose mode. */
{
verbose = true;
break;
}
default:
{
USAGE;
}
} /* End SWITCH on command option. */
} /* End WHILE processing options. */
/*
** Process command line arguments.
*/
switch ( argc - optind )
{
case 0: break;
case 1: service = argv[ optind ]; break;
default: USAGE;
} /* End SWITCH on number of command line arguments. */
/*
** Open both a TCP and UDP socket, for both IPv4 & IPv6, on which to receive
** service requests.
*/
if ( ( openSckt( service, "tcp", tSckt, &tScktSize ) < 0 ) ||
( openSckt( service, "udp", uSckt, &uScktSize ) < 0 ) )
{
exit( 1 );
}
/*
** Run the time-of-day server.
*/
if ( ( tScktSize > 0 ) || ( uScktSize > 0 ) )
{
tod( tSckt, /* tod() never returns. */
tScktSize,
uSckt,
uScktSize );
}
/*
** Since tod() never returns, execution only gets here if no sockets were
** created.
*/
if ( verbose )
{
fprintf( stderr,
"%s: No sockets opened... terminating.\n",
pgmName );
}
return 0;
} /* End main() */
/******************************************************************************
* Function: openSckt
*
* Description:
* Open passive (server) sockets for the indicated inet service & protocol.
* Notice in the last sentence that "sockets" is plural. During the interim
* transition period while everyone is switching over to IPv6, the server
* application has to open two sockets on which to listen for connections...
* one for IPv4 traffic and one for IPv6 traffic.
*
* Parameters:
* service - Pointer to a character string representing the well-known port
* on which to listen (can be a service name or a decimal number).
* protocol - Pointer to a character string representing the transport layer
* protocol (only "tcp" or "udp" are valid).
* desc - Pointer to an array into which the socket descriptors are
* placed when opened.
* descSize - This is a value-result parameter. On input, it contains the
* max number of descriptors that can be put into 'desc' (i.e. the
* number of elements in the array). Upon return, it will contain
* the number of descriptors actually opened. Any unused slots in
* 'desc' are set to INVALID_DESC.
*
* Return Value:
* 0 on success, -1 on error.
******************************************************************************/
static int openSckt( const char *service,
const char *protocol,
int desc[ ],
size_t *descSize )
{
struct addrinfo *ai;
int aiErr;
struct addrinfo *aiHead;
struct addrinfo hints = { .ai_flags = AI_PASSIVE, /* Server mode. */
.ai_family = PF_UNSPEC }; /* IPv4 or IPv6. */
size_t maxDescs = *descSize;
/*
** Initialize output parameters. When the loop completes, *descSize is 0.
*/
while ( *descSize > 0 )
{
desc[ --( *descSize ) ] = INVALID_DESC;
}
/*
** Check which protocol is selected (only TCP and UDP are valid).
*/
if ( strcmp( protocol, "tcp" ) == 0 ) /* TCP protocol. */
{
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
}
else if ( strcmp( protocol, "udp" ) == 0 ) /* UDP protocol. */
{
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
}
else /* Invalid protocol. */
{
fprintf( stderr,
"%s (line %d): ERROR - Unknown transport "
"layer protocol \"%s\".\n",
pgmName,
__LINE__,
protocol );
return -1;
}
/*
** Look up the service's well-known port number. Notice that NULL is being
** passed for the 'node' parameter, and that the AI_PASSIVE flag is set in
** 'hints'. Thus, the program is requesting passive address information.
** The network address is initialized to :: (all zeros) for IPv6 records, or
** 0.0.0.0 for IPv4 records.
*/
if ( ( aiErr = getaddrinfo( NULL,
service,
&hints,
&aiHead ) ) != 0 )
{
fprintf( stderr,
"%s (line %d): ERROR - %s.\n",
pgmName,
__LINE__,
gai_strerror( aiErr ) );
return -1;
}
/*
** For each of the address records returned, attempt to set up a passive
** socket.
*/
for ( ai = aiHead;
( ai != NULL ) && ( *descSize < maxDescs );
ai = ai->ai_next )
{
if ( verbose )
{
/*
** Display the current address info. Start with the protocol-
** independent fields first.
*/
fprintf( stderr,
"Setting up a passive socket based on the "
"following address info:\n"
" ai_flags = 0x%02X\n"
" ai_family = %d (PF_INET = %d, PF_INET6 = %d)\n"
" ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d)\n"
" ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d)\n"
" ai_addrlen = %d (sockaddr_in = %d, "
"sockaddr_in6 = %d)\n",
ai->ai_flags,
ai->ai_family,
PF_INET,
PF_INET6,
ai->ai_socktype,
SOCK_STREAM,
SOCK_DGRAM,
ai->ai_protocol,
IPPROTO_TCP,
IPPROTO_UDP,
ai->ai_addrlen,
sizeof( struct sockaddr_in ),
sizeof( struct sockaddr_in6 ) );
/*
** Now display the protocol-specific formatted socket address. Note
** that the program is requesting that getnameinfo(3) convert the
** host & service into numeric strings.
*/
getnameinfo( ai->ai_addr,
ai->ai_addrlen,
hostBfr,
sizeof( hostBfr ),
servBfr,
sizeof( servBfr ),
NI_NUMERICHOST | NI_NUMERICSERV );
switch ( ai->ai_family )
{
case PF_INET: /* IPv4 address record. */
{
struct sockaddr_in *p = (struct sockaddr_in*) ai->ai_addr;
fprintf( stderr,
" ai_addr = sin_family: %d (AF_INET = %d, "
"AF_INET6 = %d)\n"
" sin_addr: %s\n"
" sin_port: %s\n",
p->sin_family,
AF_INET,
AF_INET6,
hostBfr,
servBfr );
break;
} /* End CASE of IPv4. */
case PF_INET6: /* IPv6 address record. */
{
struct sockaddr_in6 *p = (struct sockaddr_in6*) ai->ai_addr;
fprintf( stderr,
" ai_addr = sin6_family: %d (AF_INET = %d, "
"AF_INET6 = %d)\n"
" sin6_addr: %s\n"
" sin6_port: %s\n"
" sin6_flowinfo: %d\n"
" sin6_scope_id: %d\n",
p->sin6_family,
AF_INET,
AF_INET6,
hostBfr,
servBfr,
p->sin6_flowinfo,
p->sin6_scope_id );
break;
} /* End CASE of IPv6. */
default: /* Can never get here, but just for completeness. */
{
fprintf( stderr,
"%s (line %d): ERROR - Unknown protocol family (%d).\n",
pgmName,
__LINE__,
ai->ai_family );
freeaddrinfo( aiHead );
return -1;
} /* End DEFAULT case (unknown protocol family). */
} /* End SWITCH on protocol family. */
} /* End IF verbose mode. */
/*
** Create a socket using the info in the addrinfo structure.
*/
{
fprintf( stderr,
"%s (line %d): WARNING - Some address records were "
"not processed due to insufficient array space.\n",
pgmName,
__LINE__ );
} /* End IF verbose and some address records remain unprocessed. */
/*
** Clean up.
*/
freeaddrinfo( aiHead );
return 0;
} /* End openSckt() */
/******************************************************************************
* Function: tod
*
* Description:
* Listen on a set of sockets and send the current time-of-day to any
* clients. This function never returns.
*
* Parameters:
* tSckt - Array of TCP socket descriptors on which to listen.
* tScktSize - Size of the tSckt array (nbr of elements).
* uSckt - Array of UDP socket descriptors on which to listen.
* uScktSize - Size of the uSckt array (nbr of elements).
*
* Return Value: None.
******************************************************************************/
static void tod( int tSckt[ ],
size_t tScktSize,
int uSckt[ ],
size_t uScktSize )
{
char bfr[ 256 ];
ssize_t count;
struct pollfd *desc;
size_t descSize = tScktSize + uScktSize;
int idx;
int newSckt;
struct sockaddr *sadr;
socklen_t sadrLen;
struct sockaddr_storage sockStor;
int status;
size_t timeLen;
char *timeStr;
time_t timeVal;
ssize_t wBytes;
/*
** Allocate memory for the poll(2) array.
*/
desc = malloc( descSize * sizeof( struct pollfd ) );
if ( desc == NULL )
{
fprintf( stderr,
"%s (line %d): ERROR - %s.\n",
pgmName,
__LINE__,
strerror( ENOMEM ) );
exit( 1 );
}
/*
** Initialize the poll(2) array.
*/
for ( idx = 0; idx < descSize; idx++ )
{
desc[ idx ].fd = idx < tScktSize ? tSckt[ idx ]
: uSckt[ idx - tScktSize ];
desc[ idx ].events = POLLIN;
desc[ idx ].revents = 0;
}
/*
** Main time-of-day server loop. Handles both TCP & UDP requests. This is
** an interative server, and all requests are handled directly within the
** main loop.
*/
while ( true ) /* Do forever. */
{
/*
** Wait for activity on one of the sockets. The DO..WHILE construct is
** used to restart the system call in the event the process is
** interrupted by a signal.
*/
do
{
status = poll( desc,
descSize,
-1 /* Wait indefinitely for input. */ );
} while ( ( status < 0 ) && ( errno == EINTR ) );
CHK( status ); /* Check for a bona fide system call error. */
/*
** Get the current time.
*/
timeVal = time( NULL );
timeStr = ctime( &timeVal );
timeLen = strlen( timeStr );
/*
** Indicate that there is new network activity.
*/
if ( verbose )
{
char *s = malloc( timeLen+1 );
strcpy( s, timeStr );
s[ timeLen-1 ] = '\0'; /* Overwrite '\n' in date string. */
fprintf( stderr,
"%s: New network activity on %s.\n",
pgmName,
s );
free( s );
} /* End IF verbose. */
/*
** Process sockets with input available.
*/
for ( idx = 0; idx < descSize; idx++ )
{
switch ( desc[ idx ].revents )
{
case 0: /* No activity on this socket; try the next. */
continue;
case POLLIN: /* Network activity. Go process it. */
break;
default: /* Invalid poll events. */
{
fprintf( stderr,
"%s (line %d): ERROR - Invalid poll event (0x%02X).\n",
pgmName,
__LINE__,
desc[ idx ].revents );
exit( 1 );
}
} /* End SWITCH on returned poll events. */
/*
** Determine if this is a TCP request or UDP request.
*/
if ( idx < tScktSize )
{
/*
** TCP connection requested. Accept it. Notice the use of
** the sockaddr_storage data type.
*/
sadrLen = sizeof( sockStor );
wBytes,
0,
sadr, /* Address & address length */
sadrLen ); /* received in recvfrom(). */
} while ( ( count < 0 ) && ( errno == EINTR ) );
CHK( count ); /* Check for a bona fide error. */
wBytes -= count;
} /* End WHILE there is data to send. */
} /* End ELSE a UDP datagram is available. */
desc[ idx ].revents = 0; /* Clear the returned poll events. */
} /* End FOR each socket descriptor. */
} /* End WHILE forever. */
} /* End tod() */
The TCP client code is found in file tod6tc.c (time-of-day IPv6 TCP client). Once built, the
TCP client may be started using the following command syntax (assuming tod6tc is the
executable file):
ARGUMENTS:
host
service
The TCP service (or well-known port number) to which a connection attempt is
made. Default is "daytime".
OPTIONS:
-s
This option is only meaningful for IPv6 addresses, and is used to set the scope
identifier (i.e. the network interface on which to establish the connection). Default is
"eth0". If host is a scoped address, this option is ignored.
-v
/******************************************************************************
* File: tod6tc.c
* Description: Contains source code for an IPv6-capable 'daytime' TCP client.
* Author: John Wenker, Sr. Software Engineer
* Performance Technologies, San Diego, USA
******************************************************************************/
/*
** System header files.
*/
#include <errno.h> /* errno declaration and error codes. */
#include <net/if.h> /* if_nametoindex(3). */
#include <netdb.h> /* getaddrinfo(3) and associated definitions. */
#include <netinet/in.h> /* sockaddr_in and sockaddr_in6 definitions. */
#include <stdio.h> /* printf(3) et al. */
#include <stdlib.h> /* exit(2). */
#include <string.h> /* String manipulation and memory functions. */
#include <sys/socket.h> /* Socket functions (socket(2), connect(2), etc). */
#include <unistd.h> /* getopt(3), read(2), etc. */
/*
** Constants & macros.
*/
#define DFLT_HOST "localhost" /* Default server name. */
#define DFLT_SCOPE_ID "eth0" /* Default scope identifier. */
#define DFLT_SERVICE "daytime" /* Default service name. */
#define INVALID_DESC -1 /* Invalid file (socket) descriptor. */
#define MAXBFRSIZE 256 /* Max bfr sz to read remote TOD. */
#define VALIDOPTS "s:v" /* Valid command options. */
/*
** Type definitions (for convenience).
*/
typedef enum { false = 0, true } boolean;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr_in6 sockaddr_in6_t;
/*
** Prototypes for internal helper functions.
*/
static int openSckt( const char *host,
const char *service,
unsigned int scopeId );
static void tod( int sckt );
/*
** Global (within this file only) data objects.
*/
static const char *pgmName; /* Program name (w/o directory). */
static boolean verbose = false; /* Verbose mode. */
/*
** Usage macro.
*/
#define USAGE \
{ \
fprintf( stderr, \
"Usage: %s [-v] [-s scope_id] [host [service]]\n", \
pgmName ); \
exit( 127 ); \
} /* End USAGE macro. */
/*
** This "macro" (even though it's really a function) is loosely based on the
** CHK() macro by Dr. V. Vinge (see server code). The status parameter is
** a boolean expression indicating the return code from one of the usual system
** calls that returns -1 on error. If a system call error occurred, an alert
** is written to stderr. It returns a boolean value indicating success/failure
** of the system call.
**
** Example: if ( !SYSCALL( "write",
** count = write( fd, bfr, size ) ) )
** {
** // Error processing... but SYSCALL() will have already taken
** // care of dumping an error alert to stderr.
** }
*/
static __inline boolean SYSCALL( const char *syscallName,
int lineNbr,
int status )
{
if ( ( status == -1 ) && verbose )
{
fprintf( stderr,
"%s (line %d): System call failed ('%s') - %s.\n",
pgmName,
lineNbr,
syscallName,
strerror( errno ) );
}
return status != -1; /* True if the system call was successful. */
} /* End SYSCALL() */
/******************************************************************************
* Function: main
*
* Description:
* Connect to a remote time-of-day service and write the remote host's TOD to
* stdout.
*
* Parameters:
* The usual argc & argv parameters to a main() program.
*
* Return Value:
* This function always returns zero.
******************************************************************************/
int main( int argc,
char *argv[ ] )
{
const char *host = DFLT_HOST;
int opt;
int sckt;
unsigned int scopeId = if_nametoindex( DFLT_SCOPE_ID );
const char *service = DFLT_SERVICE;
/*
** Determine the program name (w/o directory prefix).
*/
pgmName = (const char*) strrchr( argv[ 0 ], '/' );
pgmName = pgmName == NULL ? argv[ 0 ] : pgmName+1;
/*
** Process command line options.
*/
opterr = 0; /* Turns off "invalid option" error messages. */
while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) != -1 )
{
switch ( opt )
{
case 's': /* Scope identifier (IPv6 kluge). */
{
scopeId = if_nametoindex( optarg );
if ( scopeId == 0 )
{
fprintf( stderr,
"%s: Unknown network interface (%s).\n",
pgmName,
optarg );
USAGE;
}
break;
}
case 'v': /* Verbose mode. */
{
verbose = true;
break;
}
default:
{
USAGE;
}
} /* End SWITCH on command option. */
} /* End WHILE processing command options. */
/*
** Process command arguments. At the end of the above loop, optind is the
** index of the first NON-option argv element.
*/
switch ( argc - optind )
{
case 2: /* Both host & service are specified on the command line. */
{
service = argv[ optind + 1 ];
/***** Fall through *****/
}
case 1: /* Host is specified on the command line. */
{
host = argv[ optind ];
/***** Fall through *****/
}
case 0: /* Use default host & service. */
{
break;
}
default:
{
USAGE;
}
} /* End SWITCH on number of command arguments. */
/*
** Open a connection to the indicated host/service.
**
** Note that if all three of the following conditions are met, then the
** scope identifier remains unresolved at this point.
** 1) The default network interface is unknown for some reason.
** 2) The -s option was not used on the command line.
** 3) An IPv6 "scoped address" was not specified for the hostname on the
** command line.
** If the above three conditions are met, then only an IPv4 socket can be
** opened (connect(2) fails without the scope ID properly set for IPv6
** sockets).
*/
if ( ( sckt = openSckt( host,
service,
scopeId ) ) == INVALID_DESC )
{
fprintf( stderr,
"%s: Sorry... a connection could not be established.\n",
pgmName );
exit( 1 );
}
/*
** Get the remote time-of-day.
*/
tod( sckt );
/*
** Close the connection and terminate.
*/
(void) SYSCALL( "close",
__LINE__,
close( sckt ) );
return 0;
} /* End main() */
/******************************************************************************
* Function: openSckt
*
* Description:
* Sets up a TCP connection to a remote server. Getaddrinfo(3) is used to
* perform lookup functions and can return multiple address records (i.e. a
* list of 'struct addrinfo' records). This function traverses the list and
* tries to establish a connection to the remote server. The function ends
* when either a connection has been established or all records in the list
* have been processed.
*
* Parameters:
* host - A pointer to a character string representing the hostname or IP
* address (IPv4 or IPv6) of the remote server.
* service - A pointer to a character string representing the service name or
* well-known port number.
* scopeId - For IPv6 sockets only. This is the index corresponding to the
* network interface on which to set up the connection. This
* parameter is ignored for IPv4 sockets or when an IPv6 "scoped
* address" is specified in 'host' (i.e. where the colon-hex
* network address is augmented with the scope ID).
*
* Return Value:
* Returns the socket descriptor for the connection, or INVALID_DESC if all
* address records have been processed and a connection could not be
* established.
******************************************************************************/
static int openSckt( const char *host,
const char *service,
unsigned int scopeId )
{
struct addrinfo *ai;
int aiErr;
struct addrinfo *aiHead;
struct addrinfo hints;
sockaddr_in6_t *pSadrIn6;
int sckt;
/*
** Initialize the 'hints' structure for getaddrinfo(3).
**
** Notice that the 'ai_family' field is set to PF_UNSPEC, indicating to
** return both IPv4 and IPv6 address records for the host/service. Most of
** the time, the user isn't going to care whether an IPv4 connection or an
** IPv6 connection is established; the user simply wants to exchange data
** with the remote host and doesn't care how it's done. Sometimes, however,
** the user might want to explicitly specify the type of underlying socket.
** It is left as an exercise for the motivated reader to add a command line
** option allowing the user to specify the IP protocol, and then process the
** list of addresses accordingly (it's not that difficult).
*/
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 records (don't care). */
hints.ai_socktype = SOCK_STREAM; /* Connection-oriented byte stream. */
hints.ai_protocol = IPPROTO_TCP; /* TCP transport layer protocol only. */
/*
** Look up the host/service information.
*/
if ( ( aiErr = getaddrinfo( host,
service,
&hints,
&aiHead ) ) != 0 )
{
fprintf( stderr,
"%s (line %d): ERROR - %s.\n",
pgmName,
__LINE__,
gai_strerror( aiErr ) );
return INVALID_DESC;
}
/*
** Go through the list and try to open a connection. Continue until either
** a connection is established or the entire list is exhausted.
*/
for ( ai = aiHead, sckt = INVALID_DESC;
( ai != NULL ) && ( sckt == INVALID_DESC );
ai = ai->ai_next )
{
/*
** IPv6 kluge. Make sure the scope ID is set.
*/
if ( ai->ai_family == PF_INET6 )
{
pSadrIn6 = (sockaddr_in6_t*) ai->ai_addr;
if ( pSadrIn6->sin6_scope_id == 0 )
{
pSadrIn6->sin6_scope_id = scopeId;
int inBytes;
/*
** The client never sends anything, so shut down the write side of the
** connection.
*/
if ( !SYSCALL( "shutdown",
__LINE__,
shutdown( sckt, SHUT_WR ) ) )
{
return;
}
/*
** Read the time-of-day from the remote host.
*/
do
{
if ( !SYSCALL( "read",
__LINE__,
inBytes = read( sckt,
bfr,
MAXBFRSIZE ) ) )
{
return;
}
bfr[ inBytes ] = '\0'; /* Null-terminate the received string. */
fputs( bfr, stdout ); /* Null string if EOF (inBytes == 0). */
} while ( inBytes > 0 );
fflush( stdout );
} /* End tod() */
The UDP client code is found in file tod6uc.c (time-of-day IPv6 UDP client). It is almost an
exact duplicate of the TCP client (and in fact was derived from it), but is included in this
HowTo for completeness. Once built, the UDP client may be started using the following
command syntax (assuming tod6uc is the executable file):
ARGUMENTS:
host
service
The UDP service (or well-known port number) to which datagrams are sent. Default is
"daytime".
OPTIONS:
-s
This option is only meaningful for IPv6 addresses, and is used to set the scope
identifier (i.e. the network interface on which to exchange datagrams). Default is
"eth0". If host is a scoped address, this option is ignored.
-v
/******************************************************************************
* File: tod6uc.c
* Description: Contains source code for an IPv6-capable 'daytime' UDP client.
* Author: John Wenker, Sr. Software Engineer
* Performance Technologies, San Diego, USA
******************************************************************************/
/*
** System header files.
*/
#include <errno.h> /* errno declaration and error codes. */
#include <net/if.h> /* if_nametoindex(3). */
#include <netdb.h> /* getaddrinfo(3) and associated definitions. */
#include <netinet/in.h> /* sockaddr_in and sockaddr_in6 definitions. */
#include <stdio.h> /* printf(3) et al. */
#include <stdlib.h> /* exit(2). */
#include <string.h> /* String manipulation and memory functions. */
#include <sys/socket.h> /* Socket functions (socket(2), connect(2), etc). */
#include <unistd.h> /* getopt(3), recvfrom(2), sendto(2), etc. */
/*
** Constants & macros.
*/
#define DFLT_HOST "localhost" /* Default server name. */
#define DFLT_SCOPE_ID "eth0" /* Default scope identifier. */
#define DFLT_SERVICE "daytime" /* Default service name. */
#define INVALID_DESC -1 /* Invalid file (socket) descriptor. */
#define MAXBFRSIZE 256 /* Max bfr sz to read remote TOD. */
#define VALIDOPTS "s:v" /* Valid command options. */
/*
** Type definitions (for convenience).
*/
typedef enum { false = 0, true } boolean;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr_in6 sockaddr_in6_t;
/*
** Prototypes for internal helper functions.
*/
static int openSckt( const char *host,
const char *service,
unsigned int scopeId );
static void tod( int sckt );
/*
** Global (within this file only) data objects.
*/
static const char *pgmName; /* Program name (w/o directory). */
static boolean verbose = false; /* Verbose mode. */
/*
** Usage macro.
*/
#define USAGE \
{ \
fprintf( stderr, \
"Usage: %s [-v] [-s scope_id] [host [service]]\n", \
pgmName ); \
exit( 127 ); \
} /* End USAGE macro. */
/*
** This "macro" (even though it's really a function) is loosely based on the
** CHK() macro by Dr. V. Vinge (see server code). The status parameter is
** a boolean expression indicating the return code from one of the usual system
** calls that returns -1 on error. If a system call error occurred, an alert
** is written to stderr. It returns a boolean value indicating success/failure
** of the system call.
**
** Example: if ( !SYSCALL( "write",
** count = write( fd, bfr, size ) ) )
** {
** // Error processing... but SYSCALL() will have already taken
** // care of dumping an error alert to stderr.
** }
*/
static __inline boolean SYSCALL( const char *syscallName,
int lineNbr,
int status )
{
if ( ( status == -1 ) && verbose )
{
fprintf( stderr,
"%s (line %d): System call failed ('%s') - %s.\n",
pgmName,
lineNbr,
syscallName,
strerror( errno ) );
}
return status != -1; /* True if the system call was successful. */
} /* End SYSCALL() */
/******************************************************************************
* Function: main
*
* Description:
* Connect to a remote time-of-day service and write the remote host's TOD to
* stdout.
*
* Parameters:
* The usual argc & argv parameters to a main() program.
*
* Return Value:
* This function always returns zero.
******************************************************************************/
int main( int argc,
char *argv[ ] )
{
const char *host = DFLT_HOST;
int opt;
int sckt;
unsigned int scopeId = if_nametoindex( DFLT_SCOPE_ID );
const char *service = DFLT_SERVICE;
/*
** Determine the program name (w/o directory prefix).
*/
pgmName = (const char*) strrchr( argv[ 0 ], '/' );
pgmName = pgmName == NULL ? argv[ 0 ] : pgmName+1;
/*
** Process command line options.
*/
opterr = 0; /* Turns off "invalid option" error messages. */
while ( ( opt = getopt( argc, argv, VALIDOPTS ) ) != -1 )
{
switch ( opt )
{
case 's': /* Scope identifier (IPv6 kluge). */
{
scopeId = if_nametoindex( optarg );
if ( scopeId == 0 )
{
fprintf( stderr,
"%s: Unknown network interface (%s).\n",
pgmName,
optarg );
USAGE;
}
break;
}
} /* End main() */
/******************************************************************************
* Function: openSckt
*
* Description:
* Sets up a UDP socket to a remote server. Getaddrinfo(3) is used to
* perform lookup functions and can return multiple address records (i.e. a
* list of 'struct addrinfo' records). This function traverses the list and
* tries to establish a connection to the remote server. The function ends
* when either a connection has been established or all records in the list
* have been processed.
*
* Parameters:
* host - A pointer to a character string representing the hostname or IP
* address (IPv4 or IPv6) of the remote server.
* service - A pointer to a character string representing the service name or
* well-known port number.
* scopeId - For IPv6 sockets only. This is the index corresponding to the
* network interface on which to exchange datagrams. This
* parameter is ignored for IPv4 sockets or when an IPv6 "scoped
* address" is specified in 'host' (i.e. where the colon-hex
* network address is augmented with the scope ID).
*
* Return Value:
* Returns the socket descriptor for the connection, or INVALID_DESC if all
* address records have been processed and a socket could not be initialized.
******************************************************************************/
static int openSckt( const char *host,
const char *service,
unsigned int scopeId )
{
struct addrinfo *ai;
int aiErr;
struct addrinfo *aiHead;
struct addrinfo hints;
sockaddr_in6_t *pSadrIn6;
int sckt;
/*
** Initialize the 'hints' structure for getaddrinfo(3).
**
** Notice that the 'ai_family' field is set to PF_UNSPEC, indicating to
** return both IPv4 and IPv6 address records for the host/service. Most of
** the time, the user isn't going to care whether an IPv4 connection or an
** IPv6 connection is established; the user simply wants to exchange data
** with the remote host and doesn't care how it's done. Sometimes, however,
** the user might want to explicitly specify the type of underlying socket.
** It is left as an exercise for the motivated reader to add a command line
** option allowing the user to specify the IP protocol, and then process the
** list of addresses accordingly (it's not that difficult).
*/
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = PF_UNSPEC; /* IPv4 or IPv6 records (don't care). */
hints.ai_socktype = SOCK_DGRAM; /* Connectionless communication. */
hints.ai_protocol = IPPROTO_UDP; /* UDP transport layer protocol only. */
/*
** Look up the host/service information.
*/
if ( ( aiErr = getaddrinfo( host,
service,
&hints,
&aiHead ) ) != 0 )
{
fprintf( stderr,
"%s (line %d): ERROR - %s.\n",
pgmName,
__LINE__,
gai_strerror( aiErr ) );
return INVALID_DESC;
}
/*
** Go through the list and try to open a connection. Continue until either
** a connection is established or the entire list is exhausted.
*/
for ( ai = aiHead, sckt = INVALID_DESC;
( ai != NULL ) && ( sckt == INVALID_DESC );
ai = ai->ai_next )
{
/*
** IPv6 kluge. Make sure the scope ID is set.
*/
if ( ai->ai_family == PF_INET6 )
{
pSadrIn6 = (sockaddr_in6_t*) ai->ai_addr;
if ( pSadrIn6->sin6_scope_id == 0 )
{
pSadrIn6->sin6_scope_id = scopeId;
} /* End IF the scope ID wasn't set. */
} /* End IPv6 kluge. */
/*
** Display the address info for the remote host.
*/
if ( verbose )
{
/*
** Temporary character string buffers for host & service.
*/
char hostBfr[ NI_MAXHOST ];
char servBfr[ NI_MAXSERV ];
/*
** Display the address information just fetched. Start with the
** common (protocol-independent) stuff first.
*/
fprintf( stderr,
"Address info:\n"
" ai_flags = 0x%02X\n"
" ai_family = %d (PF_INET = %d, PF_INET6 = %d)\n"
" ai_socktype = %d (SOCK_STREAM = %d, SOCK_DGRAM = %d)\n"
" ai_protocol = %d (IPPROTO_TCP = %d, IPPROTO_UDP = %d)\n"
" ai_addrlen = %d (sockaddr_in = %d, "
"sockaddr_in6 = %d)\n",
ai->ai_flags,
ai->ai_family,
PF_INET,
PF_INET6,
ai->ai_socktype,
SOCK_STREAM,
SOCK_DGRAM,
ai->ai_protocol,
IPPROTO_TCP,
IPPROTO_UDP,
ai->ai_addrlen,
sizeof( struct sockaddr_in ),
sizeof( struct sockaddr_in6 ) );
/*
** Display the protocol-specific formatted address.
*/
getnameinfo( ai->ai_addr,
ai->ai_addrlen,
hostBfr,
sizeof( hostBfr ),
servBfr,
sizeof( servBfr ),
NI_NUMERICHOST | NI_NUMERICSERV );
switch ( ai->ai_family )
{
case PF_INET: /* IPv4 address record. */
{
sockaddr_in_t *pSadrIn = (sockaddr_in_t*) ai->ai_addr;
fprintf( stderr,
" ai_addr = sin_family: %d (AF_INET = %d, "
"AF_INET6 = %d)\n"
" sin_addr: %s\n"
" sin_port: %s\n",
pSadrIn->sin_family,
AF_INET,
AF_INET6,
hostBfr,
servBfr );
break;
} /* End CASE of IPv4 record. */
case PF_INET6: /* IPv6 address record. */
{
pSadrIn6 = (sockaddr_in6_t*) ai->ai_addr;
fprintf( stderr,
" ai_addr = sin6_family: %d (AF_INET = %d, "
"AF_INET6 = %d)\n"
" sin6_addr: %s\n"
" sin6_port: %s\n"
" sin6_flowinfo: %d\n"
" sin6_scope_id: %d\n",
pSadrIn6->sin6_family,
AF_INET,
AF_INET6,
hostBfr,
servBfr,
pSadrIn6->sin6_flowinfo,
pSadrIn6->sin6_scope_id );
break;
} /* End CASE of IPv6 record. */
default: /* Can never get here, but just for completeness. */
{
fprintf( stderr,
"%s (line %d): ERROR - Unknown protocol family (%d).\n",
pgmName,
__LINE__,
ai->ai_family );
break;
} /* End DEFAULT case (unknown protocol family). */
} /* End SWITCH on protocol family. */
} /* End IF verbose mode. */
/*
** Create a socket.
*/
if ( !SYSCALL( "socket",
__LINE__,
sckt = socket( ai->ai_family,
ai->ai_socktype,
ai->ai_protocol ) ) )
{
sckt = INVALID_DESC;
continue; /* Try the next address record in the list. */
}
/*
** Set the target destination for the remote host on this socket. That
** is, this socket only communicates with the specified host.
*/
if ( !SYSCALL( "connect",
__LINE__,
connect( sckt,
ai->ai_addr,
ai->ai_addrlen ) ) )
{
(void) close( sckt ); /* Could use SYSCALL() again here, but why? */
sckt = INVALID_DESC;
continue; /* Try the next address record in the list. */
}
} /* End FOR each address record returned by getaddrinfo(3). */
/*
** Clean up & return.
*/
freeaddrinfo( aiHead );
return sckt;
} /* End openSckt() */
/******************************************************************************
* Function: tod
*
* Description:
* Receive the time-of-day from the remote server and write it to stdout.
*
* Parameters:
* sckt - The socket descriptor for the connection.
*
* Return Value: None.
******************************************************************************/
static void tod( int sckt )
{
char bfr[ MAXBFRSIZE+1 ];
int inBytes;
/*
** Send a datagram to the server to wake it up. The content isn't
** important, but something must be sent to let it know we want the TOD.
*/
if ( !SYSCALL( "write",
__LINE__,
write( sckt, "Are you there?", 14 ) ) )
{
return;
}
/*
** Read the time-of-day from the remote host.
*/
if ( !SYSCALL( "read",
__LINE__,
inBytes = read( sckt,
bfr,
MAXBFRSIZE ) ) )
{
return;
}
bfr[ inBytes ] = '\0'; /* Null-terminate the received string. */
fputs( bfr, stdout ); /* Null string if EOF (inBytes == 0). */
fflush( stdout );
} /* End tod() */
22.2.2. Perl
As of May 2007 it's not known that the Perl core itself already supports IPv6. It can be
added by using following modules:
Socket6
Anyway, some other modules exist for/with IPv6 support (e.g. Net::IP), search for “IPv6”
on http://search.cpan.org/.
Configuring IPv6 with Cisco IOS by Sam Brown, Sam Browne, Neal Chen, Robbie
Harrell, Edgar, Jr. Parenti (Editor), Eric Knipp (Editor), Paul Fong (Editor)362 pages;
Syngress Media Inc; ISBN 1928994849; (July 12, 2002).
24.1.1.2. General
IPv6 in Practice: A Unixer's Guide to the Next Generation Internet von Benedikt
Stockebrand, November 2006; ISBN 3-540-24524-3
IPv6 Essentials by Silvia Hagen, 2nd Edition, May 2006; ISBN 0-5961-0058-2 ToC,
Index, Sample Chapter etc.; O'Reilly Pressrelease
IPv6 Networks by Niles, Kitty; (ISBN 0070248079); 550 pages; Date Published
05/01/1998.
Big Book of Ipv6 Addressing Rfcs by Peter H. Salus (Compiler), Morgan Kaufmann
Publishers, April 2000, 450 pages ISBN 0126167702.
Migrating to IPv6 - IPv6 in Practice by Marc Blanchet Publisher: John Wiley & Sons;
ISBN 0471498920; 1st edition (November 2002); 368 pages.
O'reilly Network search for keyword IPv6 results in 29 hits (28. January 2002)
Transient Addressing for Related Processes: Improved Firewalling by Using IPv6 and
Multiple Addresses per Host; written by Peter M. Gleiz, Steven M. Bellovin (PC-PDF-
Version; Palm-PDF-Version; PDB-Version)
Internetworking IPv6 with Cisco Routers by Silvano Gai, McGrawHill Italia, 1997. The
13 chapters and appendix A-D are downloadable as PDF-documents.
Aufbruch in die neue Welt - IPv6 in IPv4 Netzen by Dipl.Ing. Ralf Döring, TU Illmenau,
1999
http://www.ipv6.ac.uk/
24.1.4. Others
See following URL for more: SWITCH IPv6 Pilot / References
24.2.2. 2003
Suggestions are welcome!
24.2.3. 2004
1st Global IPv6 Summit in Sao Paul, Brazil
EMEA: Ripe NCC, Ripe NCC / registration page, Ripe NCC / IPv6 registration
Latin America and Caribbea: LACNIC, IPv6 Registration Services, IPv6 Allocation
Policy
Africa: AfriNIC
Also a list of major (prefix length 32) allocations per local registry is available here: Ripe
NCC / IPv6 allocations.
Note: A list of available Tunnel broker can be found in the section Tunnel broker below.
Former IPng. Tunnelbroker and IPv6 resources, now migrated to the SixXs System.
tunnelc - a perl based tunnel client script: freshmeat.net: Project details for tunnel
client SourceForge: Project Info - tunnelc (also here)
Linux Advanced Routing & Traffic Control HOWTO, Chapter 6: IPv6 tunneling with
Cisco and/or 6bone.
24.3.1.4. 6to4
24.3.1.5. ISATAP
go6 - The IPv6 Portal: an IPv6 online portal with a wiki-based IPv6 knowledge center,
an IPv6 discussion forum, an up-to-date collection of IPv6 Events and News, free
IPv6 access and services, IPv6 software applications, and much more
Publishing the list of IPv6-related RFCs is beyond the scope of this document, but given
URLs will lead you to such lists:
IP Version 6 (ipv6)
Mobile IP (mobileip)
Get any information about IPv6, from overviews, through RFCs & drafts, to
implementations (including availability of stacks on various platforms & source code
for IPv6 stacks)
24.3.3.3. Others
SWITCH IPv6 Pilot / References, big list of IPv6 references maintained by Simon
Leinen
IPv6-HowTo for Linux by Peter Bieringer - Germany, and his Bieringer / IPv6 -
software archive
DeepSpace6 / IPv6 Status Page - Italy (Mirror) (will superseed upper one)
PLD
Red Hat
Fedora Core
Debian
Novell/SuSE
Novell/SuSE Linux
Mandriva
Mandriva
24.3.4.3. General
IPv6.org
6bone
Playground.sun.com / IPv6 Info Page - maintained by Robert Hinden, Nokia. Get any
information about IPv6, from overviews, through RFCs & drafts, to implementations
(including availability of stacks on various platforms & source code for IPv6 stacks).
6INIT - IPv6 Internet Initiative - an EU Fifth Framework Project under the IST
Programme.
internet || site and internet2 Working Group - Presentation (HTML + PPT) from IPv6
Workshops: (Stateless Autoconfiguration, IPv6 Addressing, USAGI, Provider
Independent IPv6 Addressing and other topics).
NetworkWorldFusion: Search / Doc Finder: searched for IPv6 (102 documents found
22.12.2002)
Klingon IPv6 tools, Klingon IPv6 tools (native IPv6 only access): IPv6 firewall
examples, bandwith testing and portscanner
The World Atlas of the Internet: Americas; IDATE - 2/1/2002 - 242 PAges - ID:
IDT803907. Countries covered: Central America, North America, South America; List:
Price: $ 3,500.00; excerpt: Panorama of Internet access markets across the globe.
Market assessment and forecasts up to 2006 for 34 countries: market structure: main
ISPs and market shares; number of subscribers, of ISPs.
Early Interest Rising for IPv6 by IDC (Author); List Price: $1,500.00; Edition: e-book
(Acrobat Reader); Publisher: IDC; ISBN B000065T8E; (March 1, 2002)
24.3.4.5. Patents
Canadian Patent Database: Home, Search (Basic Search, just enter IPv6 in the search
field ;-); 84 documents found 22.12.2002)
Delphion Research: Patent Search Page. Basic (free) registration needed. Examples
found 21.12.2002 searching for IPv6: Communicating method between IPv4 terminal
and IPv6 terminal and IPv4-IPv6 converting apparatus Translator for IP networks,
network system using the translator, and IP network coupling method therefor
24.3.5. By countries
24.3.5.1. Europe
24.3.5.2. Austria
24.3.5.3. Australia
24.3.5.4. Belgium
24.3.5.5. Brazil
IPv6 do Brasil
24.3.5.6. China
24.3.5.7. Czech
24.3.5.8. Germany
OpenBC / IPv6
24.3.5.9. France
24.3.5.10. Italy
24.3.5.11. Japan
24.3.5.12. Korea
24.3.5.13. Mexico
IPv6 Mexico (spain & english version): IPv6 Project Hompeage of The National
Autonomous University of Mexico (UNAM)
24.3.5.14. Netherland
24.3.5.15. Portugal
24.3.5.16. Russia
24.3.5.17. Switzerland
British Telecom IPv6 Home: BT's ISP IPv6 Trial, UK's first IPv6 Internet Exchange etc.
IPv6 for Cisco IOS Software, File 2 of 3: Aug 2002 -- Table of Contents: IPv6 for Cisco
IOS Software; Configuring Documentation Specifics; Enabling IPv6 Routing and
Configuring; IPv6 Addressing; Enabling IPv6 Processing Globally.
24.3.6.3. Compaq
24.3.6.4. HPUX
comp.sys.hp.hpux FAQ
24.3.6.5. IBM
Now that IBM's announced the availability of z/OS V1.4, what's new in this release?
This question was posed on 15 August 2002
24.3.6.6. Microsoft
Getting Started with the Microsoft IPv6 Technology Preview for Windows 2000
Internet Connection Firewall Does Not Block Internet Protocol Version 6 Traffic
(6.11.2001)
HOW TO: Install and Configure IP Version 6 in Windows .NET Enterprise Server
(26.10.2002)
Windows .NET Server 6to4 Router Service Quits When You Advertise a 2002 Address
on the Public Interface (28.10.2002)
24.3.6.7. Solaris
24.3.6.8. Sumitoma
24.3.6.9. ZebOS
Information Security
Wireshark (former known as Ethereal) is a free network protocol analyzer for Unix and
Windows
Fefe's patches for IPv6 with djbdnsAug 2002 -- What is djbdns and why does it need
IPv6? djbdns is a full blown DNS server which outperforms BIND in nearly all
respects.
CommView 5.0
Posadis 0.50.6
24.3.8.3. SNMP
Another list of IPv6 Internet Exchanges can be found here: IPv6 status of IXPs in Europe
24.4.2.1. Estonia
24.4.2.2. Europe
24.4.2.3. France
French National Internet Exchange IPv6 (since 1.11.2002 active). FNIX6 provides a
free and reliable high speed FastEthernet interconnection between ISP located in
TeleCity Paris.
24.4.2.4. Germany
24.4.2.5. Japan
JPIX, Tokyo
24.4.2.6. Korea
6NGIX
24.4.2.7. Netherlands
24.4.2.8. UK
UK6X: London
XchangePoint: London
24.4.2.9. USA
24.4.3.1. Belgium
24.4.3.2. Canada
Freenet6 - /48 Delegation, Canada Getting IPv6 Using Freenet6 on Debian Freenet6
creater
24.4.3.3. China
24.4.3.4. Estonia
Estpak
24.4.3.5. Germany
24.4.3.6. Italy
Comv6
24.4.3.7. Japan
Internet Initiative Japan (Japanese language) - with IPv6 native line service and IPv6
tunneling Service
24.4.3.8. Malaysia
24.4.3.9. Netherlands
IPng Netherland - Intouch, SurfNet, AMS-IX, UUNet, Cistron, RIPE NCC and AT&T are
connected at the AMS-IX. It is possible (there are requirements...) to get an static
tunnel.
SURFnet Customers
24.4.3.10. Norway
UNINETT - Pilot IPv6 Service (for Customers): tunnelbroker & address allocation
Uninett-Autoupdate-HOWTO
24.4.3.11. Spain
Consulintel
24.4.3.12. Switzerland
24.4.3.13. UK
NTT, United Kingdom - IPv6 Trial. IPv4 Tunnel and native IPv6 leased Line
connections. POPs are located in London, UK Dusseldorf, Germany New Jersey, USA
(East Coast) Cupertino, USA (West Coast) Tokyo, Japan
IPNG-UK
24.4.3.14. USA
ESnet, USA - Energy Sciences Network: Tunnel Registry & Address Delegation for
directly connected ESnet sites and ESnet collaborators.
24.4.3.15. Singapore
24.4.4.5. Webserver
24.5. Maillists
Lists of maillists are available at:
Mobile Web-based, see mipl mipl (at) mobile- English Info, Archive
IP(v6) for URL ipv6.org
Linux
Linux IPv6 usagi-users-ctl usagi-users (at) English Info / Search,
users using (at) linux-ipv6.org linux-ipv6.org Archive
USAGI
extension
IPv6 on debian-ipv6 (at) English Info/Subscription
Debian lists.debian.org /Archive
Linux
6bone majordomo (at) 6bone 6bone (at) isi.edu English Info, Archive
isi.edu
IPv6 users majordomo (at) users users (at) ipv6.org English Info, Archive
in general ipv6.org
Bugtracking bugtraq-subscribe bugtraq (at) English Info, Archive
of Internet (at) securityfocus.com
applications securityfocus.com (2)
(1)
student-ipv6 (India) Description: This is the group for the Student Awareness group
of IPv6 in India
IPv6-BITS Description: This List will co-ordinate the working of Project Vertebrae.
ping, traceroute, tracepath, 6bone registry, DNS: JOIN / Testtools (German language
only, but should be no problem for non German speakers)
Versions x.y.z are work-in-progress and published as LyX and SGML file on CVS. Because
Deep Space 6 mirrors these SGML files and generate independend from TLDP public
versions, this versions will show up there and also on its mirrors.
0.60.2
0.60.1
0.60
0.52
0.51
2006-11-08/PB: remove broken URLs, add a new book (credits to Bryan Vukich)
0.50.2
0.50.1
0.50
2006-08-24/PB: check RFC URLs, fix URL to Chinese translation, finalize for
publishing
0.49.5
0.49.4
2006-08-21/PB: some review, update and enhancement of the content, replace old
6bone example addresses with the current defined ones.
0.49.3
0.49.2
0.49.1
0.49
2005-10-03/PB: add configuration hints for DHCPv6, major broken URL cleanup
(credits to Necdet Yucel)
0.48.1
0.48
0.47.1
2005-01-01/PB: add information and examples about IPv6 IPsec, add some URLs
0.47
2004-08-30/PB: add some notes about proftpd, vsftpd and other daemons, add some
URLs, minor fixes, update status of Spanish translation
0.46.4
0.46.3
2004-06-23/PB: add note about started Greek translation, replace Taiwanese with
Chinese for related translation
0.46.2
0.46.1
0.46
0.45.1
0.45
0.44.2
0.44.1
0.44
2003-08-15/PB: fix URLs, add hint on tcp_wrappers (about broken notation in some
versions) and Apache2
0.43.4
2003-07-26/PB: fix URL, add archive URL for maillist users at ipv6.org, add some ds6
URLs
0.43.3
0.43.2
0.43.1
2003-06-07/PB: fix some URLs, fix credits, add some notes at IPsec
0.43
2003-06-05/PB: add some notes about configuration in SuSE Linux, add URL of
French translation
0.42
0.41.4
0.41.3
2003-04-23/PB: Minor fixes, remove a broken URL, fix URL to Taiwanese translation
0.41.2
2003-04-13/PB: Fix some typos, add a note about a French translation is in progress
0.41.1
0.41
0.40.2
0.40.1
0.40
0.39.2
0.39.1
0.39
2003-01-13/PB: fix a bug (forgotten 'link” on “ip link set” (credits to Yaniv Kaul)
0.38.1
0.38
0.37.1
0.37
0.36.1
0.36
2002-12-16/PB: Check of and fix broken links (credits to Georg Käfer), some spelling
fixes
0.35
0.34.1
0.34
0.33
2002-11-18/PB: Fix broken RFC-URLs, add parameter ttl on 6to4 tunnel setup example
0.32
0.31.1
0.31
0.30
0.29
0.28.1
2002-09-16/PB: Add note about ping6 to multicast addresses, add some labels
0.28
2002-08-17/PB: Fix broken LDP/CVS links, add info about Polish translation, add URL
of the IPv6 Address Oracle
0.27
0.26.2
0.26.1
0.26
0.25.2
0.25.1
0.25
2002-05-16/PB: Cosmetic fix for 2^128, thanks to José Abílio Oliveira Matos for help
with LyX
0.24
0.23
2002-03-27/PB: Add entries in URL list and at maillists, add a label and minor
information about IPv6 on RHL
0.22
2002-03-04/PB: Add info about 6to4 support in kernel series 2.2.x and add an entry in
URL list and at maillists
0.21
0.20.4
2002-02-21/PB: Migrate more grammar checks submitted by John Ronan, add some
additional hints at DNS section
0.20.3
0.20.2
0.20.1
0.20
2002-01-30/PB: Add a hint about default route problem, some minor updates
0.19.2
0.19.1
0.19
2002-01-25/PB: Add two German books, fix quote entinities in exported SGML code
0.18.2
0.18.1
0.18
0.17.2
2002-01-22/PB: Cosmetic fix double existing text in history (at 0.16), move all credits
to the end of the document
0.17.1
0.17
2002-01-19/PB: Add some forgotten information and URLs about global IPv6
addresses
0.16
2002-01-19/PB: Minor fixes, remove “bold” and “emphasize” formats on code lines,
fix “too long unwrapped code lines” using selfmade utility, extend list of URLs.
0.15
0.14
0.13
0.12
0.11
0.10
25.2. Credits
The quickest way to be added to this nice list is to send bug fixes, corrections, and/or
updates to me ;-).
If you want to do a major review, you can use the native LyX file (see original source) and
send diffs against it, because diffs against SGML don't help too much.
Pekka Savola <pekkas at netcore dot fi>: For major reviews, input and suggestions.
Martin F. Krafft <madduck at madduck dot net>: For grammar checks and general
reviewing of the document.
John Ronan <j0n at tssg dot wit dot ie>: For grammar checks.
Georg Käfer <gkaefer at gmx dot at>: For detection of no proper PDF creation (fixed
now by LDP maintainer Greg Ferguson), input for German books, big list of URLs,
checking all URLs, many more suggestions, corrections and contributions, and the
German translation
Michel Boucey <mboucey at free dot fr>: Finding typos and some broken URLs,
contribute some suggestions and URLs, and the French translation
Michele Ferritto <m dot ferritto at virgilio dot it>: Finding bugs and the Italian
translation
Benjamin Thery <benjamin dot thery at bull dot net>: For contribution of updated
mobility section
John Wenker <jjw at pt dot com>: major contribution to Programming using C-API
Writing a LDP HOWTO as a newbie (in LyX and exporting this to DocBook to conform to
SGML) isn't as easy as some people say. There are some strange pitfalls... Nevertheless,
thanks to:
Credits for fixes and hints are listed here, will grow sure in the future
S .P. Meenakshi <meena at cs dot iitm dot ernet dot in>: For a hint using a “send
mail” shell program on tcp_wrapper/hosts.deny
Frank Dinies <FrankDinies at web dot de>: For a bugfix on IPv6 address explanation
John Freed <jfreed at linux-mag dot com>: For finding a bug in IPv6 multicast
address explanation
Craig Rodrigues <crodrigu at bbn dot com>: For suggestion about RHL IPv6 setup
Fyodor <fyodor at insecure dot org>: Note me about outdated nmap information
Tom Goodale <goodale at aei-potsdam dot mpg dot de>: For some suggestions
Arnout Engelen <arnouten at bzzt dot net>: For sending note about a draft was
adopted to RFC now
lithis von saturnsys <lithis at saturnsys dot com>: Reporting a misaddressed URL
Guy Hulbert <gwhulbert at rogers dot com>: Send a note that RFC1924 is probably
an April fool's joke
Walter Jontofsohn <wjontof at gmx dot de>: Hints for SuSE Linux 8.0/8.1
J.P. Larocque <piranha at ely dot ath dot cx>: Reporting archive URL for maillist
users at ipv6 dot org
Colm MacCarthaigh <colm dot maccarthaigh at heanet dot ie>: Hint for sendfile issue
on Apache2
Tiago Camilo <tandre at ipg dot pt>: Contribute some URLs about Mobile IPv6
Harald Geiger: Reporting a bug in how described the bit counting of the
universal/global bit
Bjoern Jacke <bjoern at j3e dot de>: Triggered me to fix some outdated information
on xinetd
Christoph Egger <cegger at chrrr dot com>: Sending note about “ip” has problems
with IPv4-compatible addresses on SuSE Linux 9.0 and trigger to add a hint on
6to4-radvd example
David Lee Haw Ling <hawling at singnet dot com dot sg>: Sending information
about a tunnel broker
Michael H. Warfield <mhw at iss dot net>: Sending note about suffix for 6to4 routers
Tomasz Mrugalski <thomson at klub dot com dot pl>: Sending updates for DHCPv6
section
Kalin KOZHUHAROV <kalin at tar dot bz>: Fixing a not so well explanation
Roel van Dijk <rdvdijk at planet dot nl>: Reporting broken URLs
Catalin Muresan <catalin dot muresan at astral dot ro>: Reporting minor bugs
Dennis van Dok <dvandok at quicknet dot nl>: Reporting minor bugs
Necdet Yucel <nyucel at comu dot edu dot tr>: Reporting broken URLs
If you have any questions, subscribe to proper maillist and describe your problem
providing as much as information as possible.