 So hello, everybody. Thank you for coming. This is going to be a session about IPv6. And I should hope that I wouldn't have to do this session. I should hope that by 2016 we would have solved this problem. I was hoping that we would have already switched or been on the very long way to the switch having been done. Apparently, that is not the case. So I wanted to talk to you about what some of the changes are. So first of all, thank you for coming. Thank you so much for attending this session. I'm going to be doing a brief introduction on what IPv6 is, what does it look like, a little bit of the differences compared to IPv4. I don't know how many of you have used it before, have deployed it, have played with it, or seen it. So I'm going to do a brief introduction. And then I'm going to talk about some of the important things for you to know that you can do and also show a bit of API. So if you're developing a low level application, that's how you mostly would be using the API. So let me quickly introduce myself. That is actually me, not in 1999. That was actually me in 1982 playing with high technology of the time. What actually was interesting for me is that I began my open source career by doing IPv6. So I was a student at the time, and I got the question when I applied to a company to do some open source work. I wanted to start thinking of an internship. And they said, well, what do you want to work on? So I just started thinking, well, I could do this, could do that. I had already submitted a patch. My first patch to open source was actually a patch to the Linux kernel back in 1999. And it was actually about fixing something really stupid. I don't remember the details about IPv6. So I decided, well, let me try to do IPv6. And my first contribution was actually to make an IPv6-capable browser in the year 2000. Mozilla already had IPv6 support. So I decided to work on Conqueror, the new KDE browser for KDE 2. That was in the year 2000. And I started working on KDE during the year 2001 to 2003. Ended up going to work for Troll Tech in 2006. And then that led me to my open source career today. And today I work for the Open Source Technology Center at Intel doing, among other things, IoT. And that brings me back to IPv6. So the timeline that you see here, I'm also showing that IPNG was formed in 1993. So 23 years ago, somebody realized, you know, we need to start thinking about the future. The first RFC for IPv6, that one is actually obsolete, was published in 1995. So I'm going to ask you that date of the IPv4 exhaustion. I'm going to ask for guesses. Does anybody want to venture a guess of what that date is? Somebody said last year, does anybody want to say before or after that? Sorry? 2014? The correct date is actually 2011. So IPv6 has been exhausted in the main pool by the Internet Assigned Numbers Authority, IANA, since 2011, January. Later in the same year, Asia, so the Asian Regional Address Authority, also ran out of its blocks. So Asia has been out of IPv4 blocks except for returned and bartering schemes since 2011. Europe followed soon after in 2013. And North America was in 2015. The only one remaining is actually Africa. So the African Regional Authority still has, according to current estimates, enough until 2019. So you see the situation we're in. We've been predicting that this was going to happen for 23 years. Now, we're still alive. The world hasn't melted down. That means we actually found workarounds. But they're all that, they're workarounds. So like I said, I'm going to talk a bit about what it is. Show the IPv6 API for programming, low level. And then some of the interesting things you can do with it. Before that, what happened to IPv5? So IPv5, they just used the version number in the IP block for something different. It was an RFC that they published for exploring ideas and reserved that number. It never went anywhere. So the next one available was V6. That is not Babylon 5. That is Babylon 4. And the reason why it's there is because it disappeared. We can chat later about what happened in Babylon 5. So here's some comparisons. The biggest difference between IPv4 and IPv6 is the addressing size. So it is the fact that before I have today in IPv4, I have only 32 bits of addressing possible. And IPv6 expands that to 128. And if all of them were assigned to the entire planet, we would have something around, and I'm probably remembering wrong, but something around 500 trillion addresses per square centimeter of the planet. So we're probably safe. They also created an architectural addressing scheme. So the entire world right now is restricted to about 2 and 1 half percent of the entire addressing. So we're going to use that. And if we find out that we actually need to change the way we do things, we have plenty of room left. Multicasting is actually very corner part of the protocol itself. I'm going to get back to multicasting because it's one of the most interesting features of IPv6. Because now you can do things that in IPv4 were only thought of later. They're bolted on IPv4. They're not exactly built in from the get go supporting many of the things that you might want to do. The maximum transmit unit, that's what MTU stands for, the requirement from the protocol is that at least 1,280 octets be supported on the wire level. So if you have a transmission interface, for example, that is smaller than that, it would require the fragmentation to be done on the lower level. So an example for that could be Bluetooth. So Bluetooth has a frame size of 256 bytes. There's no way you can transmit a packet that contains 1,280 in that. So what it does is that the Bluetooth protocol will fragment it and send it multiple packets, multiple frames, I'm sorry, and then reconstruct them before the layer above receives it. So why is that an advantage? Well, the advantage on that is that the IP layer can actually be much simpler. Fragmentation, like I wrote in there, is always done at origin. So the packet is always received at the end exactly the same way that it was sent. In IPv4, a router in between could decide, I'm going to break this and send the smaller chunks completely out of order. So the receiver needs to put them back together. And that's all putting back together before giving it to the TCP layer that also needs to do putting back together. IPv6 has privacy extensions. And the interesting things that some of them have come into IPv4 because they were invented for v6. But they're built in to the protocol. And even the link layer address resolution is built in the protocol itself. So like I said, some of the things that were invented for v6 actually made it to v4. If you've been connected to, for example, a wireless network and it had no internet connectivity or your DHCP server was down, you might have seen an address like this one that you're seeing here, 169254. That's what we call a link local address in v4. It's an address that is automatically assigned by your own computer because it could not find any other. You usually think of this when, if you've noticed it, you think, oh, I don't have internet. This is useless. I'll just reconnect or find another network. Have you ever been through this, seen this address and thought that? Well, in IPv6, when you do see a link local, it's actually very different because it actually means that I might actually have other people to talk to, other devices on my same network to talk to because it's more designed for that. Now, it doesn't mean I have to access the internet. That's a second story. Any casting is another one I'll be back to. But suffice to say that this particular IP address that is here is not one server. It's actually multiple. I'm not talking about load balancing with multiple mirrors behind the scenes and doing proxy. No, it's actually one. At the IP level, it might reach multiple different servers. I have a drawing for it later. And another example is IPsec. It was created as a privacy extension for IPv6 as an authentication address encryption. And it was just so interesting that they decided, let's do it on IPv4 as well. And it led to VPNs being done on top of IPv6. So let's look at what an address looks like. Like I said, it goes from 32 to 128 bits. It gets to be this big address that I showed here. There's two smaller forms. The one I showed in blue is the normal one that you're usually going to see. It just compresses sequences of zeros to shorter segments. There is a compact form by that RFC there. My opinion, not very useful. It's not very useful to remember. Yeah, that was actually an April Fool's RFC. Some addresses that we all know are actually made simpler. The local host address is just one bit set, so column, column 1. So every time that you need to type it, it's actually much simpler. But the idea is, of course, that you're not going to type them because they're very, very long. I mentioned that the devices can configure themselves. So here's how it works. It enables one of the technologies that is more the cornerstone of IPv6 that you're going to see it in practice is called the stateless address auto configuration. It enables devices that as soon as they connect to a network to communicate with each other without having a DHCP server. And by that, I even mean via the internet. The way it works is like this. My device connects to a network. It will send a packet asking, is there any router around here? The routers receive it and say, yes, I'm a router. And in that reply packet, it includes a bit of information saying, here are the addresses valid in my network. So with that bit of information, the device can add a node ID of itself and form a full address with two packets and completely stateless. Any device connecting to a network automatically is talking to everybody else. The router can include a little bit of more information saying, hey, by the way, there's a DHCP server you might want to check for more information, like DNS servers, NTP servers, Wins servers, printer servers, domain searches, or any other information that DHCP has. But it's not necessary. If I have a constrained node, a device that doesn't care about name resolution and only needs to talk to other devices on the same network, it doesn't have NTP client. It can skip that and say, well, I don't care. I'll just stick to the information I had. And that's enough for me to talk to every other node in my network, in my organization, and even to the internet if I wanted to. I didn't explain here, but the point is that the address, the interface ID that it creates is actually tied to your own device. So the question some people ask is, what about my privacy? So what happens if I connect to another network? Will it be able to tell that it's the same person? So the typical case is you go to Wi-Fi hotspots. So you go into this cafe, and next you're in this other store. That bit of information might be interesting to some people, to especially advertiser, saying, well, this person likes coffee and jeans. I might be able to sell him something. So IPv6 has created temporary and random generated addresses. The way it works for the one on the left column is they're completely random. You've got 63 bits of randomness in your address. It means that every time, every 12 hours more or less, rotated after a time, your address changes. And every time you connect to a different network, it changes. For somebody tracking you from the outside of that network, it's completely impossible for them to know that it's you. Because every time or after a time, your address has changed, they don't know it's you. Now, of course, this doesn't include tracking by other means like cookies. This is the low level, the solution from the IP level. And of course, your browser needs to have that kind of functionality to avoid tracking and other application layers as well. Whenever I talk to people about this, they go, well, what if I want to reach my server? What if I, for example, acquire resources on my network? Example, I have a port forwarding into my machine. I'm sorry. If I have a firewall rule that allows my host to be reached from the outside if I want to remotely administer it. Well, one solution, of course, is always to use manual addressing. Another one is this new one. It's not yet common on Linux. It's called stable but opaque addresses. So it is the result of a pseudo-random function. They just bunch a bit of information together. That depends on some secret known to you, the SSID of the network you're connecting to, and some other information. You can read the spec to see what. And what happens is that every time you connect to that network, you've got the same address. But you connect to a different network. It's a different address. So again, it prevents tracking when you connect to different networks. They won't know that it's you. Interestingly, you can actually use both at the same time. So that means your machine will configure locally an address to be reached. But when it sends out a packet, it uses the random one. So don't forget your firewall rules. I just mentioned this. If you're a server administrator or a network administrator, don't forget that now you have addresses that might be nodes that are addressable from the outside world. That doesn't mean that you have to make them reachable from the outside world. So this is one of the most important differences on IPv4 and IPv6 networks. Because on IPv4, what we're used to whenever I connect to my home network or my office network or this network here, I'm always getting a private address. We're getting here 172.26 something. Well, that means somebody on the internet cannot address us. Because that specific address is actually all over the world. Different networks are using it. Well, on IPv6, I might actually get a global address. So I am addressable from the entire world. But that doesn't mean that I need to be reachable. So a firewall might still block incoming traffic and say, well, let's protect the user. But it does have its advantages, right? I'm going to talk a little bit more about it. But the fact is, since it's unique address, I don't need to do address translation. My routers now have less requirement for resources. So I just mentioned something that let's just pay attention to what I said. Well, in my network at home, every device I have has an addressable IPv6 address. So how does the world know what it is? It works like this. Of course, you can always assign addresses manually. And you probably can tell which company is using that address on top. It's a real one. This other technology is called prefix delegation. So this is an example of a network here of a site with three networks. The way it works is that the main router asks their provider of internet services for a prefix. And in this case, it got a slash 62 network, which means that it has 66 bits of address space for the entire network, which is about this. It's four times the square of the entire internet today. But if you're looking at IPv6, usually that means I've got four networks. Usually an IPv6 network is going to use a prefix of 64. And I just realized that the fonts cut off. So this is a 64 here. So I'll pay attention when generating the PDF and fix it for you. The presentation will be online later. So the router asked for four networks. And then it assigned one to net one. For net two, it assigned via prefix delegation to the other router. So in my network at home, I only have one. I don't need more. My router, which is a standard open WRT router, asks my ISP in the US I'm using Comcast, asks it for a prefix for a single network, it gets it, and then it runs what I said before. It runs a DHCP server and announces the prefix to all devices. So my laptop and my phone, whenever they connect to my network at home, they're just like this net one here. They get the prefix announcement. And automatically, they're on IPv6. I mentioned the casting. So let's just look at what they are. Unicast is the normal one that we usually think, which is reaching one. Unicast, it's a one-to-one communication. My sender, he used the blue one. I'm trying to reach the green one. Unicast is I'm just going to get to that particular one. There's nobody else with the same address. Multicast is one too many. It's sending to all of the addresses in a group. The address is likely different. I'm not going to get into the architecture. You can look up later. But it means I'm reaching everybody that has joined that group. The most common use for it is MDNS, or multicast DNS, that the most common use you've seen, which is what allows you to discover devices on your network at home, usually, especially if you have Apple devices. The Unicast is an interesting one that was invented specifically for IPv6, which is to reach, it's a one-to-any, in the sense of I want to reach any of those that belong in a group. Doesn't matter which one, as long as I reach one. The example for this, the typical example you're going to see is routers. So if I have multiple routers in my network and all of them reach the internet, any of them work. I don't need to reach that specific one if that one is freer. So the addresses don't look different. It's a matter of routing that they themselves, these devices that join that Unicast, decide that, well, if I receive it, I'm fine. If I don't, somebody else, it doesn't matter. Are there any questions here just on the overview of IPv6? Do you mind coming to the microphone? Is there any FCS, like in layer 2 of IPv6, or no? There is FCS thing, because you said that there is no, the originated bit size will be sent and received, and there is no fragmentation by it. Is there any FCS? So you're asking about the efficiency of the packets transmission. I'm not sure I understood the question. Yeah, it's the part that Frecon did check how frame and packet are sent and receiving. So I'm going to try and answer. The packets are not bigger than what they are today. So if you're connecting to a wired or wireless network, usually the packets are up to 1,500 bytes in size. That's the size of a frame on ethernet. The size is chosen in such a manner that I might maximize what I'm transmitting. I'm maximizing my throughput per packet, but minimizing the chance of collision. I want to use as little as possible so that if there is a collision, if I lose this packet, I didn't lose too much. The next one might arrive. The number 1280 was chosen so that I can reasonably send 1k of data payload, of my payload, to the destination. Because to that, you have to add the overhead of IP itself, TCP, or UDP, and there might be some extra headers. So that's what they think. The 1280 should be enough. On networks like I mentioned before, like Bluetooth or 6LowPan 15.4, the frames are smaller. So the lower layer needs to fragment them. And they do it. The frames are smaller exactly so that they actually avoid the collision so that the frames, if there is a collision, there's little loss of data. And they can be re-transmitted by fragment as well. Did this more or less answer the question? Yeah. Yeah. OK, thanks. In terms of API, what I want you to remember is two things. First, always use the IPv6 API. I'm going to show you why. If you have a higher level API than the Socket API that you get from Linux or your OS, use it. Use it and make sure that it does support IPv6. If it doesn't, in 2016, stop using it, throw it away. I'm serious. Any API that doesn't support IPv6 today doesn't deserve to be used. But if you have to use the Socket level API, always use the IPv6 API. And I'm showing you why here. It's actually simpler to use than the IPv4 that you might have learned in the old days. It supports both. So you don't have to care about which one it is. And you don't have to assume anything about the address. The other thing I want you to know is actually don't assume anything about the address. So let me give you a challenge. A URL is like this. Scheme, host, port, path, query, and fragment. I want to construct this URL for these pieces of data here. Note the part about having columns inside the host name and a column separating the host from the port. Who's seeing a problem? Yeah? So what happens is that it actually adds these extra brackets in the address. So my example is don't assume that you just can construct URLs by concatenating things. Don't do that. Use a proper API for it. If you have an API for URLs, use it. Don't try to construct by hand. So you don't forget the brackets. So let's get to the lowest level. The lowest level is a socket address. A socket address, I'm sorry if you can't read everything from the bottom, from the back. I actually tried to make it big. It's the same thing as it used to be for IPv4. You've got a socket address, iNet, Internet, or Internet 6. It has the family, which is v4 or v6. A port number, an address. And IPv6 has two extra bits of information I'm not going to get into. But one of them, to be honest, in 20 years of using IPv6, I've never used the flow info. The scope ID is interesting, but I'm not going to get into. There's this other API that was created at the same time called socket storage. The idea is that you put it into a union with everything that you have. It will be big enough to contain everything you need, including, as an example, Unix socket paths. So how does it work? I'm actually not going to ask you to look into this. So to resolve an address, you use this function that was created specifically for IPv6. But it's what you should be using today. Never use get host by name anymore. You're going to use get address info, get adder info. All you need to do is decide what you want to get. The example I have here is I don't care which one. Just ask for everybody everything. If my machine has IPv6, yes, return it. If it doesn't have IPv6, then don't bother returning IPv6 addresses. And I'm using for TCP, so I'm asking for string sockets. If you're doing a server, if you're receiving connections, there's the comment there saying use the passive flag. You're going to call it. And this example program here simply prints it. It doesn't use them. So actually it does use them. So there's this generic function here called use. I'm not saying what it just uses right now. It's as simple as that, a resolver. It resolves host names. Do you see here the HTTP? It resolves service names as well. So I don't have to remember which port HTTP is. It will resolve it for me. I could type there SMTP, SMTPS, IMAPS, or something other. It will resolve by itself. It serves for both receiving sockets and outgoing sockets. So bind and connect. So how do we do the opposite? So how do I reverse it to a host name? There is another function called get name info. So this is an example of using. So this one simply prints what it had resolved. And I ran it as an example, trying to get the IPV address for cane or a free node while I was connected to the Wi-Fi network here in the hotel. It printed those first two. So look how it always printed IPV4 first. Wouldn't you say, well, why? So what I did as an example, just a test, I actually connected to the VPN to my home and ran it again. And look how the order changed. So get address info is actually intelligent enough to know that you do have or you don't have an IPV6 address in your network, that you don't have connectivity. So it will sort things in the order that is most likely to reach the server. In the case of these addresses here as well, it can actually even sort the IPV6 addresses depending on which region of the world you are in. So if you're in Europe, it will sort the European addresses first. Well, let me make a connection. So I'm going to connect to the host. If you've written low-level programming, you know socket and connect. Look at that. Everything I need for that connection is already in the resolution. I don't have to remember that it is a family afinet. What is the socket type? Again, it's sock stream. Yes. And what's the last parameter? I never remember. Just put 0 there. No. There you go. It's all done. Connect the same thing. And this is a simple HTTP client that tries to get something. So if I actually run this example on k.net, I get something as a result. And I can use the same thing on the other direction. So if I had used that passive flag to say I want to listen to receive a connection, look at how it again shows, oops. Look at, go back. No, went too much now. I don't have the highlight. So look again how it's again the same thing for the bind. So I don't have to worry about what to do there. I mentioned that always use IPv6 API, because it subsumes the IPv4 one. So this socket that I created here will receive IPv4 connections. They will look slightly different. It will look like this FFFF specific address there, right? Receiving IPv4 is actually the default on Linux, but somebody couldn't turn it off. So I actually recommend that you always turn it back on, even if it was already on. Or if you want to do the dual sockets, you can turn it off by yourself as well. So my recommendation is to always do this V6 only turning on and off. So let me just make a note here on this particular address. If your application has some kind of access control lists that you use to match IP to IP or networks, you need to take care to be sure that you're matching the V4 to that specific IPv6 address. So it is an IPv6 address. It won't be binary equal to your V4. So you want to convert to make sure that you're looking to one another correctly. I'm just going to go briefly over some of the interesting things I mentioned so that you can do. Like I said before, you can use IPv6 for your entire network with globally addressable, but not reachable, addresses. So all your routing elements, so if you're a big sysadmin for a network, let's say like the company I work for, I work for Intel, they can actually use IPv6 for all of them, all the routers. I've seen many, even ISPs, when you do a trace route, you do notice some of the whole routers in between have private addresses. I don't know if you've seen this, it's not very common, but it happens that some of them have private addresses because they didn't have enough IP addresses in their blocks to waste on routers. So with IPv6, you can do it for all of them, so including your routing elements. If you have cloud containers, if you have containers VMs or everything else, so one of the keynotes this morning was showing how when you launch VMs on Amazon, they actually get private addresses by default. On IPv6, no, they would all get public, where they might be firewalled, remember, remember your firewall rules, but they might also all already be routable. So if you're all in the same network element, the same routing, the same firewall zone, they might reach each other the moment that they're provisioned. This is going to be very important for us on this IoT world that is coming, internet of things, because you're going to have 50 billion devices connected. All your devices at home will have a proper address. Another interesting thing was the replacing broadcast with multicast. IPv4, you see often, and by the way, I turn on my machine here, look at your syslog. Mine keeps telling me that there's a bunch of, that's a lot of broadcasts arriving. Many of them are misconfigured clients sending things that you don't want to, but my point is that I keep receiving this information a lot and a lot of data that my machine is receiving on before, even if I don't care about it. So multicast allows me to select what I want to receive. I'm participating in MDNS. I'm only getting MDNS. I'm not getting Windows shares announcements. So one to everyone or one to the entire group, like I mentioned before. But since it's built in to the protocol, it allows us to more closely control which groups and always everything is using groups and ever just sending it to everybody whether interested or not. As part of the address, you also have the scope limitation. So I can always say, everybody that is on the same network as I am, so I'm the same routing network, or the same organization, or things like that. The most common ones are two and three. The most commonly used ones are link, local, and realm, local. And finally, I didn't get into this API, but there is a more advanced socket API. The one I showed was the basic socket API. This one is the advanced one. It allows us to get more information from the packet. So as an example, there are the two that I have here. So if I receive a UDP datagram, I can query it and say, hey, was this addressed to me or was this multicast? Why would you want to do that? Well, there are certain protocols that would say, if you received a multicast and you don't have that information, don't reply with an error. There's no point in replying with errors if you don't have that information. But if it was a unicast asking specifically you about it, well, yeah, no, you reply, no, I don't have this. It can also allow us to decide, I'm going to send this packet. I want to send on this particular interface, not on that one. On IPv4, that's very actually very difficult. It would only do it from the routing table, which means that only the scissor men can configure it and configure exactly one outgoing device. Now, this was, again, all created for IPv6. There are equivalents for v4 on Linux. So IP packet info. But it doesn't exist in other systems. This API is standard. This one exists in all the operating systems. It exists on VSDs. It exists on macOS. It exists on Windows. The v4 doesn't. I had one more, which is a six-low pan was created specifically for using IPv6 on low-power networks. So the example, the question I had about efficiency, what they did is actually they compressed the header because there's a lot of redundant information. By compressing the header, we actually get IPv6 on these networks. More than that, we removed the entire link layer addressing. It's only IP. As you can see, two groups adopted it, both the Thread Group and the Bluetooth, the Special Interest Group. They adopted it for their next versions. That's what I had. Any more questions? Would you mind coming to the microphone? We're being filmed. OK, it's actually a bit of a philosophical question, perhaps, but actually, two of them. No one, philosophical one. It's actually a difference. So the philosophical one, how long do you think people, a lot of people even in with some connection to the IT industry will keep thinking that they are actually safer by using IPv4 behind a nut than just using IPv6 to the state for firewall? Because I've heard that from a lot of people that, oh, I've got a private IPv4 address. I'm safer. OK, so that's an interesting philosophical question. I won't spend an hour on it. I would say that it's a misguided assumption. You're not safer. If somebody broke into your network, then you would not be safer in any way. The biggest difference is the addressability. So it's what I mentioned more than once. If you have the biggest problem you're going to have with IPv6 is if you have a misconfigured router that did not firewall properly, then you might actually get somebody going to your devices internally. That would increase your surface attack area. And if any of those devices that was reachable has a vulnerability, it would allow you to break into your entire network. So that is definitely an issue. Now, a proper season in that is worth their salary will not allow the misconfigured firewall that way. So that's what I'm saying that it's an incorrect assumption to say I'm safer. You have to use security in depth. There's no way to say, well, just because my addresses are public or private, I'm not going to get attacked. You might be by the same vectors. If it's not the firewall, the firewall is the minimum thing that you're going to have configured. You still have other attack vectors. You might have devices that open a connection, a persistent connection to do something. And through that, it might be attacked. Somebody might attack you via USB drive. So you might have heard the details of what happened to, I was the uranium power plant, the Stuxnet virus. It was muggled in via USB, right? So you still have to do security in depth. There's no way around it. It's not the address that is going to make you safer or less safe. The question you asked, how long they're going to think that? I don't know. I was hoping that we would have switched to IPv6 by now, whereas I'm here talking to you about it. And the technical question for change. So you mentioned enabling or re-enabling dual stack support for IPv6 sockets. I know that, at least, I think it was like four years ago or so. There are some of the security researchers said that you should definitely, by all means, switch that thing off and make sure that you can actually keep IPv6 and IPv4 sockets separately, because there were, at least at that time, some security issues with this IPv4 traffic coming over IPv6 sockets in Linux not being filtered properly. So do you know what that has been solved? And is it safe to use now? So I remember something about it. You were right. There was a discussion about it. And I remember reading about it and saying, well, it's not an intrinsic failure. It's not because you turned it on that you're going to be more vulnerable. The issue is what the pointed out is the ACL. That was exactly the problem, because you might have a rule that allows something, and specifically was blocking IPv4 for, I don't know. It was a hacking attempt. So you added the ACL saying, well, this guy here just dropped all the packets. Because it now is coming through the IPv6 layer, if you're not careful, you're not going to match the ACL. The most common scenario is the other way around. You want to grant privileges, and it doesn't match. So you're doing the whitelist functionality instead of blacklisting. But in essence, it's the same thing. You just have to be careful when you're using a dual stack socket that whenever you get a packet that's actually coming from v4, you treat it as v4. You just have to do it correctly. Now, if you do have in your application the ability to open two sockets independently and deal with them in your code is proper fine, by all means do it. So it might actually be easier in your application on some cases. For other applications, it might be easier to use a dual stack. I showed the simpler one here. Other other questions? OK, so thank you so much. I'm around until next Friday, because I'm coming to the other conference as well. If for those of you, if you want to talk to me more, I'm usually by the Intel booth. I'm very interested in making sure that IPv6 does get deployed. I'm happy to help you answer questions. If you have a problem like, let's talk about what happened in that security announcement, I'll be happy to chat with you. Or if you want to talk about other networking aspects, IoT, I'm there. So thank you so much for coming. And happy conference. Have a continuation. I hope to see you tonight.