Linux IPv6 FAQ

This Document has been replaced by the IPv6-HOWTO


Version: Created 1996-Sep-13, last changed 1996-Sep-18.


This is a second draft. There will be quite a few more drafts. Expect lots of mistakes and email me about every one of them :) I have not worked with the project at all (as a matter of fact I just opened the sources last night :) ); update: I reviewed the API and some RFCs and made comments about differences and asked questions; but want to help everybody focus by making this FAQ available. The main URL is http://U.Q.Net/~ulmo/linux/ipv6/; I have been having difficulty with Apache lately, so try Panix & Armory.

This may turn into a HOWTO someday.

Right now (UT 1996 Sep 16 22:06), I'm too tired to finish this round of drafts. Please don't hesitate to send me corrections, updates, writing in some sections, suggestions, etc.


The main author for Linux's IPv6 is Pedro Roque Marques <>. Naturally as with any author of such key software, while he's happy to be accessible and receive all sorts of communications, at least try to read this FAQ first and then the archives of the netdev list (see below) so that his (and everyone's, including yours) time is best used. Ideally you'll work on it on your own until you have something to contribute, at which point you can post your contribution to the list, and people will help you even more.

The initial author of the FAQ is Bradley Ward Allen <>, who knows so little that he is a good person to make a FAQ (since all of his questions will go here!)

Reference Documentation:

This is the best WWW I've found yet: IP Next Generation (IPng). Definately look at it.

RFCs are simple: get (also available from other RFC FTP sites around the world) and search for "Version 6", "IPv6", "v6", "Internet Protocol Version 6", "ipng", etc. You'll find among others: 1983, 1981, 1972, 1971, 1970, 1946, 1933, 1924, 1920, 1919, 1897, 1888, 1887, 1886, 1885, 1884, 1883, 1882, 1881, 1863, 1852, 1851, 1829, 1828, 1827, 1826, 1825, 1810, 1809, 1800, 1754, 1752, 1744, 1707, 1700, as well as a whole slew of drafts (not yet standards, but good background material in case you want to program something) in (as of the writing of this FAQ, at least 52 draft documents related to IPv6; note also the abstracts for further info).

Mailing List:

The mailing list is a communications fast-track for developers. It's not meant for questions with simple to derive answers, nor for general non-development related issues. Beyond this FAQ you are expected to have a bit of intelligence and time; if you can't help implement, or at the least debug (with patches in hand), the software, then please just be patient and use this FAQ & your installation as a measure of "how far they've gotten", unless you really have something useful to contribute.

It is expected that this harsh tone will be diminished when IPv6 finally gets integrated into the Linux 2.1 development tree, as more and more people will start tinkering with it. However, there will slowly be more appropriate places to discuss issues, meaning you have even less excuse to blather :) : & (according to the issues at hand). Correct me if I'm wrong!


Follow the FAQ sort of in order from this point on, and you'll naturally be led into installation.

Software mirror list:





Main site (use closest if possible):

Get all of the latest files of the various packages. In short, you should probably get the latest of:
    inet6, net-patch, net-tools, tcpdump
In addition, get a resolver that understands IPv6; while Bind 4.9.4-P1 introduced it, it is very buggy, so it's best to go directly to something more stable (this drivers certain developers mad since the nonrelease versions aren't supposed to be more stable) such as this. What I haven't seen programmed into BIND yet is the ability to use the IPv6 network facilities; it seems only capable of serving IPv6 DNS queries only (which is a big step forward though). Note that there are incompatabilities between /usr/include/netdb.h from Bind and from Linux -- try to fix them & send patches to the appropriate maintainers.

Include header files:

They're in inet6/netinet6, and must be found in /usr/include/netinet6. You can symlink or copy them into place.

rpcent undefined

You overwrote your old netdb.h & other resolver include files with the new one from bind. That's good. Only thing is, bind's header files and libc's don't agree. Ok, what to do? Well, libc people should get their act together and work out these issues with Paul Vixie <>, like I've been trying to do. Why don't you grab my include files for now and send me & everyone else patches so we can make it perfect?

Can't find -lresolv6

Replace "-lresolv6" with "-lresolv". If you built .so files for the latest resolver but not libresolv.a, then replace -lresolv with the .so file (/lib/ and it should work. I don't know if making a symlink from libresolv.a to libresolv6.a would also work (if those exist) or even a symlink from to libresolv6.a (horrors!), but they're worth a try too.

If libresolv.a exists and is up to date, and there's a .so file too, will -lresolv link statically or dynamically?

ping6: unknown protocol icmpv6

The IPv6-ICMP line in /etc/protocols should be something like this: icmpv6 58 IPv6-ICMP # ICMP for IPv6 [Deering] My /etc/protocols has a few rude comments but has this fixed.

can't resolve symbol 'ether_ntohost'

Q:~# tcpdump6 -f -i ppp0 
tcpdump6: can't resolve symbol 'ether_ntohost'
Answer: I don't know yet.

Application programming using IPv6:

Let's face it. The API has a long ways to go before you're ready to do package upgrades smoothly with it. Just testing & playing around you can get someplace. But when I did a hack to make sendmail work with IPv6 (it took me 12 hours), it was pointed out how horrible my code was and how much better it would have been (and simpler) if I had only used this new standard API that doesn't even exist anywhere yet. I'm sure it will ... you get the idea.

Reference docs from standards bodies

As of 1996-Sep-16 things are in a woeful state of flux, hopefully the standards bodies will be accessible and things will actually move forward. Regardless, we have to start doing things, so just start programming and keep a tab on when the standards come out & start informing people to switch to the standards (give them patches if possible) when they come out. Else, the venders will win an ugly race because we're all waiting for standards bodies to make dumb decisions.

Some standards bodies make their standards well known; others do not. One that does is IETF, with draft-ietf-ipngwg-bsd-api-05.txt. Rumor has it they ought to have released a more recent one; I'll try to summarize the changes right here that would have been in that more recent one.

Reference to the above draft document was made in IPng Specifications under Program Interfaces, so look there for anything more and be sure to tell me if you find anything so I can include it here.

Another API standards draft is POSIX 1003.1g. I cannot find any of POSIX's stuff on the Internet. They suck. Anyway lots of people are waiting for them to decide something. I'll never know when they decide anything since I have no way to see what they decide, except fourth-hand, which isn't very good. I suggest that if you have access to POSIX's stuff, to repost it on our mailing list so progress can be made in all directions quicker.

The third place is "under the table" as it was so put: make a nice, clean decision, put it someplace useful (glibc, libc, etc.) and use it (thus documenting its use in many available source codes).

Between these three sources, the API will eventually develop. Here's the current state of affairs and what you should use.

The API as we use/understand/see/have/developed it so far:

I can't stress this enough: whenever you see problems in the API, at this stage in time, please mail the mailing list so progress can be made in all directions quicker.

There's a few things in inet6-tst-08's inet6/test/.

Here's what Pedro Roque Marques <> had to say to fill in this section:

The socket API allows programers to access the new address family AF_INET6 as well. One important concept to bare in mind is that while a machine that implements the AF_INET6 address family runs two network protocols ipv6/ipv4 (both accessible via AF_INET6 sockets) it only runs one instance of TCP and UDP.

(Then Craig Metz <> said this:)

More correctly, (TCP/IPv4 and TCP/IPv6) and (UDP/IPv4 and UDP/IPv6) share a port space between them. For example, if you did TCP/X.25, it would have a separate port space from IPvn.

(back to Pedro:)

A new sockaddr, sockaddr_in6, struct was defined with members sin6_family, sin6_port and sin6_addr. sin6_addr is itself a struct in6_addr (these definitions are accessible via <inet/inet6/in6.h>)

The more significative change in programing is that programers are expected to use the Posix 1003.1g getaddrinfo/getnameinfo (instead of traditional resolver functions) which should allow for a more address format independent programing. We still don't use this interface since the code we plan to use (NRL support lib) has not been released officially yet. (Craig:)getaddrinfo() is a POSIX 1003.1g spec function; getnameinfo() is not. It is specified in the IPv6 BSD base API spec.

(Craig still) I'd strongly recommend the use of the nrl_getnameinfo() function, which is getnameinfo() with a flags field that allows you to efficiently implement the '-n' flag [the one that turns off reverse name resolution -ulmo] to many programs as well as do some other nice things.

[Where is NRL support library defined?? Who's making it? (National Research Laboratories, naturally? :) ) Aha it's Naval Research Laboratories. When will it be out? -Ulmo]

(Pedro ...) I've noted above that the AF_INET6 address family can access ipv4 sockets. The standard defines IPv4-mapped addresses (of the form ::ffff:d1.d2.d3.d4, where d1.d2.d3.d4 is an ipv4 address) for this purpose.

An example server application:

struct sockaddr_in6 sin6; char hostname[Y]; sk = socket(AF_INET6, SOCK_STREAM, 0); bind to IPV6_ADDR_ANY (0::0), port x accept(sk, (struct sockaddr *) &sin6, ...) getnameinfo(&(struct sockaddr *) &sin6, sizeof(sin6), hostname, ....); this server will accept ipv4 or ipv6 TCP connections on port x. The getnameinfo function will then return the hostname, either by an PTR lookup or by an PTR lookup if (the address is ::ffff:<ipv4>)

Then Craig Metz <> said this:

Try this block instead (which uses a few functions in the NRL support library for convenience):

{ int i, s; struct addrinfo *ai, *ai2, req; req.ai_socktype = SOCK_STREAM; req.ai_flags |= AI_PASSIVE; if (i = getaddrinfo(NULL, "a-service", &req, &ai)) { fprintf(stderr, "getaddrinfo: %s(%d)\n", nrl_gai_strerror(i), i); exit(1); } for (ai2 = ai; ai; ai = ai->ai_next) { if ((s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0) { fprintf(stderr, "socket: %s(%d)\n", strerror(errno), errno); continue; } if (bind(s, ai->ai_addr, ai->ai_addrlen) < 0) { fprintf(stderr, "bind: %s(%d)\n", strerror(errno), errno); close(s); continue; } if (listen(s, 5) < 0) { fprintf(stderr, "listen: %s(%d)\n", strerror(errno), errno); close(s); continue; } break; } /* maybe save parts of the addrinfo used */ freeaddrinfo(ai2); (Craig still:) The advantage to using getaddrinfo() for a server is, as you'll notice, there's no mention of anything specific to a protocol family. This is a HUGE win for making apps that can work with any protocol family without modification (IPv4, IPv6, ISO, etc).

(Pedro) client app:

an client application can request address resolution via getaddrinfo which returns a pointer to:

struct addrinfo { int ai_flags; /* input flags */ int ai_family; /* protocol family for socket */ int ai_socktype; /* socket type */ int ai_protocol; /* protocol for socket */ int ai_addrlen; /* length of socket-address */ struct sockaddr *ai_addr; /* socket-address for socket */ char *ai_canonname; /* canonical name for service location (iff req) */ struct addrinfo *ai_next; /* pointer to next in list */ }; If the ai_family retuned is AF_INET the application can access it either via an AF_INET socket or an AF_INET6 socket as ::ffff:<ipv4>. You can request explicitly that the library does this conversion for you.

Then Craig Metz <> said this:

inet6_isipv4addr() will tell you if an in6_addr is an IPv4-mapped address or not. The flaw here is that this works on IPv6 addresses and NOT sockaddrs.

IMO, a properly written client or server shouldn't need to care whether it's connected to a mapped address or not, especially because the address/name resolution libraries take care of making the right things happen (e.g., a [nrl_]getnameinfo() on a IPv4-mapped address generates an IN-ADDR.ARPA lookup correctly).

More API stuff:

A discussion ensues: I (Ulmo) mentioned something about hton and then Pedro said: Pedro> You are messing things a bit. hton{l,s} convers short/long Pedro> integers to network byte order and will remain usefull. But Pedro> yes, inet_pton (presentation to network) will transform a Pedro> string representing an IPv6 adddress (dealing with double Pedro> colums, zeros, etc) to an struct in6_addr (in network byte Pedro> order of course). Craig> 99.9% of the app authors should never use inet_ntop or Craig> inet_pton IMO; use getaddrinfo()/getnameinfo() instead. Because Craig> inet_ntop and inet_pton never deal with host names, they're a Craig> fairly big loss. With 128-bit addresses, the DNS is even more Craig> necessary than it was with IPv4. Alan> That requires you can force your getnameinfo()/getaddrinfo() to Alan> go to files only and not DNS. Too many applications have speed Alan> and security needs beyond DNS. Craig> It's not clear what you're saying. If you want Craig> getnameinfo() not to go to DNS, use nrl_getnameinfo() and give Craig> a the flag to tell it so. If you want getnameinfo() not to go Craig> to DNS, don't give it a DNS name. (The NRL versions always use Craig> the local host table first, btw) Alan> Yes but nrl_* routines aren't standardised. Obviously they Alan> should be. From several standpoints its important you can use Alan> names not have some box querying a spoofable DNS for stuff. On Alan> certain systems for example spoofing loghost as some other Alan> machine into the local DNS means they get no logs of an Alan> attack. Im glad the nrl_* code goes file first! Pedro> That is indeed the problem. Craig tried to call the IPng WG Pedro> attention on this but the answer as been almost non existent. Pedro> It may well be that the nrl version will be more used. Pedro> Pedro> Craig, why don't you draft inet_getnameinfo and submit it to Pedro> IPng WG ? Then let them handle the bureaucracy that comes from Pedro> having two standard bodies working at the same API. ;-) As you can see, there are many issues that need to be worked on with the API. Please, PROGRAM things and then complain about any API issues that seem fuzzy or don't work right and things will be worked on as appropriate. We need progress in this area now and this is kind of the biggest way to get action. Be prepared to feel like you're a dog or cat chasing your own tail (as well as others' tails who are also chasing their own tails).

yet more api stuff

(i'm getting tired already sigh -- expect me to just sorta dump more and more with less and less formatting and organization here) Craig> Pedro> ulmo> o Is it considered safer & more portable to Craig> Pedro> ulmo> do memset(&struct_sockaddr_in6_variable, 0, Craig> Pedro> ulmo> sizeof(struct sockaddr_in6)); or to just set Craig> Pedro> ulmo> all four variables explicitly Craig> Pedro> ulmo> (sin6_{family,port,flowinfo,addr})? Craig> Pedro> Craig> Pedro> You can initialize with memset. I see no problem with that. Craig> Craig> You should initialize with memset, just in case. Craig> [Me (Ulmo) asking whether flows are ok -- well I can say look at some flow discussion in mailing list archive of nanog or something like that -- or was it big-internet? info.big-internet on my] Craig> Pedro> When you find out what it is please tell me about it Craig> Pedro> ;-). It is an opaque string that nobody know exactly how Craig> Pedro> it will be used by that the WG felt a demanding need for Craig> Pedro> :-) RFC 1883 contains rules for generating a flow label. Craig> Craig> The flow info is probably going away. Craig>

Q: Can Linux configure some interfaces as forwarding and others as non-forwarding and thus be a dual-mode node (acting as both host and router depending on the interface)?

Excerpt from RFC1883 (within section 2, Terminology):
   Note: it is possible, though unusual, for a device with multiple
   interfaces to be configured to forward non-self-destined packets
   arriving from some set (fewer than all) of its interfaces, and to
   discard non-self-destined packets arriving from its other interfaces.
   Such a device must obey the protocol requirements for routers when
   receiving packets from, and interacting with neighbors over, the
   former (forwarding) interfaces.  It must obey the protocol
   requirements for hosts when receiving packets from, and interacting
   with neighbors over, the latter (non-forwarding) interfaces.
Note that one of Linux's strengths is often to be a router, so many users will be looking forward to these capabilities.

A: yes, but not exactly like that.

Q: How does one turn forwarding on or off? And, is this per node or interface, once again?

A: (Pedro says) /sys/net/ipv6/ipv6_forwarding. node configuration. (That is, the ipv6_forwarding command; I'm not sure if this is what inet6-tst-08's inet6/test/rt_ctl.c is all about??

more dump ... too tired to finish now

ulmo> Q: Can Linux configure some interfaces as ulmo> forwarding and others as non-forwarding and ulmo> thus be a dual-mode node (acting as both host ulmo> and router depending on the interface)? Pedro> No. I tought a bit about that and couldn't find a Pedro> cenario where it would be really usefull. So it took the Pedro> simpler way and decided that testing an ipv6_forward Pedro> variable costed less than having to check what Pedro> forwarding variable to check first. Pedro> Pedro> Note that in the case of a PPP server both interfaces Pedro> need to be forwarding interfaces. Craig> Note also that once we get firewall code for IPv6 you can do Craig> things that way, though the ND messages would still claim the Craig> Linux box is a router for all interfaces (presumably you Craig> wouldn't do router advertisements on interfaces where you're Craig> not planning to route). Alan> You can firewall filter your routing advertisements smartly Alan> too. Some 3com routers for example smart filter the RIP/SAP Alan> broadcasts for IPX so that each network receives a table Alan> representing the truth according to the firewall not the whole Alan> truth. btw Alan> is Alan Cox <> (for those who couldn't figure that out from all his postings on mailing lists)

Q: Will the radix tree implementation in ipv6_route.c allow Linux to handle a large number of routes, and therefore behave as a good router machine (such as in an ISP or backbone)?

A: (Pedro:) That is what all that hairy code is about. In theory a radix tree seams a good aproach to me. I looked around papers about routing tree algorithms and I saw nothing clearly better than these patricia type trees.

(This started a little discussion where we found out that Patricia trees are excellent, that Pedro seems like he's on the right track, that this can handle 1,000,000 routes nicely, but for 30,000 routes the hash in IPv4 (is it in 2.0? If not it will be in 2.1 ...) is faster than the BSD version but that the BSD version had a simple flaw that a single line of code did 100% speedup ... anyway, point is, this will most likely be a great point of IPv6 in Linux. You could stick your Linux box in a network hub, and perhaps with a bit of contact with the developers to fine-tune your particular configuration (and thus make Linux even more appropriate for this application and others do it without as much fuss too), let it fly.


IPv6 has much more autoconfiguration than IPv4. Furthermore, since autoconfiguration is a large goal of IPv6, it is surely to be better understood and therefore more developed and utilized than with IPv4.

I think autoconfiguration in Linux's IPv6 will improve with time, so anything you do to manually configure it should be construed as testing until this is fully developed.

The kernel should configure everything automatically as stipulated by the protocols, and will (via documentation and implementation) specify what user-land protocol dependencies exist, and those should be created and installed appropriately; configuring the interfaces manually should be minimized (non-existant?)

(To which Pedro says:) Yes. That is the idea.

(Pedro) In a working environment, the only configuration necessary for an host will be to ifconfig up (no address info) its interfaces [e.g., eth0, lo, sit0 -ulmo]. When you have a routing announcement deamon on your network (every router should have one), the information it announces will be sufficient to configure addresses, local (interface) routes and default routers.

Example of complete IPv6 host configuration by ulmo -- put this in a bootup script:

ifconfig lo up ifconfig sit0 up ifconfig eth0 up Pedro> ulmo> Here's how I'm "testing" so far in a RedHat-style Pedro> ulmo> configuration environment: Pedro> Pedro> ulmo> ========= /etc/sysconfig/network-scripts/ifcfg-eth0: Pedro> ulmo> ONBOOT=yes DEVICE=eth0 IPADDR= Pedro> ulmo> NETMASK= BROADCAST= GATEWAY="" Pedro> ulmo> IP6ADDR=5f07:f100:82fa:1100:1010:a0:2410:e666 Pedro> Pedro> This address, on an host, should be given by concatenation of Pedro> the announced prefix 5f07:f100:82fa:1100:1010/80 and your link Pedro> local token i assume, a0:2410:e666. [but it will be autoconfigured; he's talking about the special case of configuring manually; such as for a router?? I don't quite get it (i.e. is there such a thing as a router that *has* to be configured? -ulmo] Pedro> ulmo> IP6ADDR=fec0::1 IP6PREFIXLEN=12 Pedro> Pedro> fec0:: is site-local reseved addresses. Those should be Pedro> announced also and not configured manually.

Configuring the IPv6-over-IPv4 tunnel (sit0):

sit0 is the tunnel which automatically tunnels IPv6 packets addresses to destinations of the form ::w.x.y.z via IPv4 to the IPv6-over-IPv4 tunnel interface at the IPv4 address w.x.y.z. There, it gets put back into IPv6 on the other host. (Unlike the Linux tunl0 driver, you don't specify the other ends' IP# with the ifconfig pointopoint argument; rather you do it as in the example below for all the affected prefixes.)

Pedro> automatic tunneling:
Pedro> 	just ifconfig sit0 up and your set.
Pedro> configured tunneling:
Pedro> 	after iface is up do
Pedro> 	route add prefix ::
Pedro> [just don't forget than the other end has to have a tunnel to
Pedro> you also this is if you want to receive packets back]

Test tunnel sites and the "6bone":

6bone Home Page

The rest of this section should be removed. Perhaps this should be put into WWW below.

There are some sites listed in the page [GET IMPLEMENTATION PAGE URL IP Next Generation (IPng) FROM THAT SUN HTTP PAGE AND PUT IT HERE] Platform whatevers ... excerpts:

(Pedro:) There are also linux machines on the 6bone. Try (intel) or (sparc).

Speaking on the 6bone: I can peer with folks that are close to me in terms of network topology and give them 6bone access. I've barable connection to .pt, .es and and also to other eurpean coutries if there happens to be a path using dante (EuropaNet) between them an If your are interested mail me. I would prefer of course sites that have research interest in IPv6.

Someone said 6bone isn't appropriate in the FAQ. I need further explaination of this concept; we're still in development and we need testing sites; eventually when people are happy their tests work they can drop off the 6bone. But whenever anyone is testing their network code they need someone to test it with.

How does one route to the 6bone?

A: (quoting Pedro) Having a configured tunnel to another 6bone host (1996-Sep-21). Pointer: 6bone Home Page You will find there all the info you need about what the 6bone is, how to connect, maps and all. Need to organize this more: ulmo> Ok, so that explains IPv6-over-IPv4. But what about this ulmo> example: ulmo> * The address of the second machine is ulmo> :: Its test address on the 6bone is ulmo> 5f00:bd00:c009:500:0:800:2072:6fe5. ulmo> The big question for me is how & where to route packets ulmo> destined for 5f00:bd00:c009:500:0:800/80 via :: I ulmo> know how to get to :: (that's easy; "ifconfig sit0 ulmo> up"). But, what will make "ping ulmo> 5f00:bd00:c009:500:0:800:2072:6fe5" work? ulmo> "route -A inet6 ulmo> add 5f00:bd00:c009:500:0:800/80 ::" doesn't work. ^ | add "gw" here, i think. It would if Sun had a route back to the prefix you would be using (yes, you need to get a prefix too, which is easy, just read RFC 1897). That is what i ment with "[ ... the other end as to have a tunnel to you ...]". btw: and you generaly don't route /80's. IPv6 provider based allocation specifies /64 prefix, 16 bit for site subnet id, 48 for media (ie. ethernet) token. Test address allocation (RFC 1897) follows the same logic. [...] ./Pedro.

When/if gated will have IPv6 support?

I don't know. I asked the gated-people mailing list today. We'll see the response soon.

Note that RedHat is now part of the Gated Consortium, among other things means that they are allowed to distribute the source code, and they do so on ftp://FTP.REDHAT.COM/ along with some Linux patches in ftp://FTP.RedHat.Com/pub/gated/ to make it work with the latest version, R3_6Alpha_2.

Related WWW

stuff to organize when i'm not stressed:

None currently here, but I have a number of messages in ipv6/todo that I have to sort through. I'll get to that soon.