 Alright, let's get started. In this talk, we're going to be going over a new protocol I've been working on at Zapdom called HostSocketSharing, or HSS. This allows a USB host to share its internet connection with the connected device. Before jumping into that, I want to briefly introduce myself. My name is Daniel Berliner, and I am a Principal Product Engineer at Zapdom in Chicago. I mostly work on our firmware, Linux drivers, and other Linux needs. At Zapdom, we provide a highly scalable solution for IoT devices to connect to a secure IPv6 overlay network that is globally routable but publicly invisible. However, contrary to what the sales team told me, I'm here to present HSS from a much more generic standpoint rather than going too far into our use cases for it. In this talk, I'm going to introduce the idea of having a USB host share its internet connection with the device, discuss use cases where this approach is advantageous, go over the protocol we wrote for accomplishing this, and give an overview of the implementation we wrote for this as well. The other reason that I'm giving this talk is to engage the open source community to look for ideas either on implementation or on the concept of this to see if we can make it more useful for more people. During the talk, if you have a question, please do just send it. I like to address questions as soon as they come in. Alright, so the problem we're trying to solve here is to get a USB device to have an internet connection provided by the host it's plugged into. This seems simple enough. USB has Ethernet over USB protocols, and you can also do internet connection sharing over USB. Which is, yeah, one of the, yeah, so yeah, you could do some of the tethering over USB as Sophia has commented. However, there's a few drawbacks. Internet connection sharing over a USB link requires NAT or bridging, which requires you to either select an IP subnet to use or run DHCP. If you're going to be using any of the CDC classes, those present difficulty going from device to host. They were fundamentally designed from host to device. The most common use case being a network interface card either through an Ethernet port or through a Wi-Fi device. They're also specific to Ethernet. If you're forwarding Ethernet packets over the network, you do have to know quite a bit about the network. Neither of those are easy solutions for what we're trying to do. Primarily, because they're not plug and play, we need a solution that's idiot-proof and user-friendly. You need to be able to just plug it in and have the connection without requiring a lot of user configuration or custom user space software on the host to manage it. Claude asks, could we also use IPv6? Yes. The purpose of this is for either IPv4 or IPv6. All right, so what we got together to solve this was a protocol we call host socket sharing. This is a protocol that allows the connected device to open sockets on the host and virtually manage them. This has a number of key advantages. No special networking configuration is required. The device can use the host's internet connection as is, even if it's a complex setup that requires quite a bit of negotiating with the routers. Furthermore, any firewall rules are implicitly also applied to the device. This meets already it-proof requirements. You can just plug it in and have it work. You don't need to know anything about the network, and you most importantly don't need to change the network to send things over it. This is an inversion from a lot of protocols you may be familiar with because it starts at the device and goes to the host rather than the other way around. This operates by having a driver on the device that creates sockets on IP or IPv6 for TCP or UDP and operates them at the request of the device. USB is used to relay the data and commands over the wire from one to the other. What kind of devices would want this? Well, there's a number of use cases. If you have a USB printer, scanner, or other interaction device that wants to download firmware updates or communicate with the cloud, they could benefit from this so that they don't have to write custom specific drivers to the machine that they're running on. Many of these devices already use generic drivers for their purposes and could benefit from a standard model to handle network connections. And I certainly know I would not miss setting up Wi-Fi on a printer. I'm sure anyone who's done that would not miss it. IoT sensors connected to a gateway are another use case. They often know what they need. They know where they need it, but they may lack the ability to connect themselves either through not having hardware or their hardware not being sufficient for the environment. So a generic solution to communicate with their gateway would be helpful. Another use case we've thought of is a hardware VPN dongle. This is something that you'd send data into. It would encrypt, packetize, and send data back out through its own secure key storage, perhaps a TPM or its own crypto processors. Before we move on to discussing what this looks like, do we have any questions from a conceptual standpoint? Alright, well, from the device's perspective, its user space applications will send data to a new socket family called AFHSS. This outwardly behaves as if it were an iNet socket, but internally it bypasses the network stack and sends all its data through USB so it can be sent to the internet by the host. From the host's perspective, it has a USB driver that sits listening to the other side of the connection and forwarding these operations and data over the actual iNet and iNet 6 sockets it creates. It also actively listens to all of these sockets and forwards the data it gets back asynchronously. The device doesn't poll or ask if it has data to be read. It just gets sent. To accomplish this, we created a relatively straightforward standard defining a number of commands, data structures, and algorithms for processing the data, along with a few rules on which side can process what? Looks like we got another question here. Can the host firewall restrict packets by the device's identity? Can USB devices be uniquely identified? There's probably a way to write the host driver so that the firewall knows it's coming from one of the USB devices, yes, but that isn't a use case we've considered yet. The USB devices can be uniquely identified and there may be a way to have the host socket manager pass that data onto the firewall. So yes, that is certainly something that should be able to be accomplished. Great question. Another one from Jan, could this be used to let the device listen on a port such as for a web UI? Yes, it could. That again would be something we'd have to expand into, but that definitely is a good use case I could see. All right, I'm going to try to keep this section relatively brief because reading a bunch of packet definitions to you doesn't make for a very interesting talk. The HSS packets that we use here all have the same 12 byte header. This header consists of an opcode describing the operation being done, a message ID that's used for acknowledgments to link an acknowledgement to the original command, a SOC ID to identify which SOC is being operated on, and a payload length indicating if there's any additional data to the packet. Payload data immediately proceeds the actual packet. For all packets, all numbers are unsigned integers and all multi byte fields are little endian unless otherwise specified. There's two types of commands here. There's two types of packets. There are command packets that have a maximum payload of 52 bytes. So we'll discuss why in a few minutes. These are your open, closed, shut down connect commands and acknowledgments. And then there's data packets which have an arbitrary length and are ideal for sending larger amounts of data. The first type of command we have is an open command. This is the first thing that initially creates a socket on the host. This is always sent by the device to the host. In addition to the header, it always has a nine byte payload indicating the ID of the socket for future operations that's handle. The address family protocol and type as well. This pretty closely mirrors the POSIX interface for the open command on a socket. The next type of packet is the close command. This closes a socket and can be sent by either side. When sent by the host, it indicates the remote peer has closed the socket. When sent by the device, it orders the host to close the socket. These return an acknowledgement but like the POSIX interface don't have an actual return code. The next command is shut down. This is a lot like close except it only indicates one direction. If sent by the device, it means the device will no longer send data. If sent by the host, it means the remote peer will no longer send data. Looks like we have another question. I'm sorry. I misread that. That packet again returns an acknowledgement but it doesn't have a return code just like the POSIX interface. Next is connect. This connects to an address on an already open socket and like open is only sent from the device to the host. In the case of an IPv4 address, it contains an 8 byte payload indicating the family, the port, and the IP address. It's important to note that connect packets always send their addresses in network byte order because no matter what the endianness of the host, it is expected to be in that format. The connect for IPv6 is very similar except it accommodates the much larger IPv6 address with the family, port, flow info, scope, and the IPv6 address. We've alluded to an acknowledgement a few times already and that is the ACC command. It acknowledges a given opcode and either sends a one byte response or a custom payload depending on the opcode it's responding to. Right now we're mostly responding to these one bytes, not defining terribly complex returns, but it has the ability. Finally, there's the transmit command. This sends and receives actual data from one side to the other for the sockets. This is the header with an arbitrary payload that has the actual data on it. Looks like a question came in. What about linkscope IPv6 addresses? You went to... Sorry, let me go back on that slide there. This has all the fields that you use to connect. As far as the linkscope goes, I am not exactly familiar with what that is. We can talk about that afterwards. I can't spend too much time on that right now. Do we have any other questions about the packets before we move on? My apologies. I'm having a little trouble sifting through questions here the way they're coming up. Okay, yeah, Claudio, let's discuss this afterwards. If I've made an omission, I will make sure to correct that. In terms of requirements, this requires USB 2.0, although if you're dealing with anything that's remotely fast, you're going to want USB 3.0. It requires two bulk endpoints for transferring the data packets and two interrupt endpoints for transferring the command packets. Because not everyone's here is going to be too familiar with USB development, it's worth quickly going on inside of what is an endpoint. In USB driver development, an endpoint is a buffer provided by USB to communicate from one side to the other. These are unidirectional buffers and have a few different types that give you different guarantees with different restrictions. Bulk endpoints are ideal for handling large data packets without tight latency requirements. Writing data to a flash drive is a great example of this. You don't particularly care how many milliseconds it takes for the packet to get there, but you do care how quickly it can transfer a large final. Interrupt packets are ideal for small packets that need to arrive very quickly. As the name suggests, it triggers an actual interrupt on the USB interface and causes them to be read quickly. There are interfaces that restrict these packets to 64 bytes, thus the 52 byte requirement that I mentioned a bit earlier. While we don't deal with them, there's also isosynchronous packets that deal with data streams. They lack a transmission guarantee, so they're completely unsuitable for these purposes. And then there's command endpoints which are used for configuring the device. For more detailed info, you can go to the USB standard. Chapter 5 describes this in a lot of detail. Anyway, so for this implementation, you need the two data, the two bulk endpoints for transferring data packets and two interrupt endpoints for transferring command packets. You also need a way to direct traffic from the device side socket onto the USB link. We've, for our purposes, we've created a new type of socket that does that. Do we have any questions on the implementation so far? Why do you need, why do you need two extra interrupt endpoints for the command? Could the command also be used over the bulk? The answer is yes, you could, but the data endpoints may be transferring a large amount of data, and you want to relay these much smaller commands with tighter latency requirements. It does raise the resource requirements of the device a little, but we didn't want to make these commands wait a long time for other sockets that may be processing some large portion of data. Good question. All right, then now I'm going to, sorry, one more question from Sophia. Sorry, one more popped up and I'm having some trouble reading the interface. I'm sorry, I'm just going to continue. I'm going to get into our implementation right now. For this, there's four basic components. There's the network driver on the device side, a USB driver on each side, and a host HSS driver that connects to the actual internet. All these components are bi-directional in that they send and receive data. The HSS network driver on the device side operates the socket that the user space device is talked to. It exports a number of functions that the USB driver knows to call, and it accepts an interface for the USB driver to provide callbacks to be sent data. The USB driver on the host and device do essentially the same thing. They connect, they maintain the USB interface, and they pass data to their respective HSS drivers. On the host, the HSS driver is split into two logical parts. There's one that unpacks the packets, handles the operation, and has a manager to deal with the actual iNet sockets on the device side. So for the device network driver, as I've mentioned a few times already, it presents a new type of domain located on our tree at the net HSS directory. It behaves as similar as we can to an iNet socket when dealing with user space applications. However, after that, it behaves quite differently. Rather than packetizing things in TCP or UDP and sending them to the IP where it sends them, sorry, it packetizes them as HSS and sends them to the USB driver. It also has to keep track of socks so it knows what it's dealing with when it gets an incoming packet. The host and USB driver, as I mentioned, just maintain the channels. And the host HSS proxy, I went over the slide here. My apologies, I made some last minute changes to these slides. Before I go into what the endpoints look like as they connect, are there any questions on what I'm talking about so far? All right, let's continue that. The flow of this happening when a USB device is plugged in is that the USB driver obviously is the first software to get the knowledge that it's been plugged in. So the host USB driver sets everything up with the device USB driver, and you have your endpoints. The device USB driver calls the exported functions from the HSS driver on the device and registers some of its functions for callback purposes. That's how the HSS driver knows how to send data to USB. And at this point, both sides are ready to send and receive data. Let's go through the flow of a open packet that would be used to initially set up a socket for communication. This is identical to the flow of other packets, but this is probably one of the simplest to go through. The first thing that happens is on the device a socket command is made with the HSS socket type. The HSS driver stores the new ID with this socket and uses the callbacks that were given to it by the USB driver to send an open packet. The USB driver receives the open packet and sends it over the wire to the host USB driver. The host USB driver passes the packet onto the host HSS proxy, which will also store the socket ID and correlate it to a new actual INET socket it creates. Upon completion, it will either succeed or fail and create an ACK packet indicating what happened. This ACK packet is passed back to the USB driver on the host, transported to the USB driver on the device, which passes it to the HSS driver on the device, which looks up the socket in its database and returns to the actual socket either by unblocking or updating its information so the next time it pulls, it will return either success or failure. That's the portion I had to describe the way we're implementing this. Are there any questions on this? Moving forward, there's a few challenges we have in terms of trying to integrate this with what other people are doing and perhaps even upstreaming the software. The first and probably most looks like we have another question. Is this HSS change related code proprietary or are we going to upstream the changes? This is all open source. I am going to link to our GitHub repose in just a minute. We would love to see this upstreamed as the project becomes more mature. The most fundamental difference between this and other USB software is that USB is a very directional protocol. There is a master, there is a slave and the host does not usually provide functionality to its device. That makes this very different than other CDC protocols. The other main difference from CDC protocols is that we are dealing with transport layer packets instead of the physical Ethernet packets. Furthermore, from an implementation standpoint, network drivers and USB drivers don't typically talk together. The CDC classes have a relatively inflexible glue between an Ethernet and it isn't really designed to go the other way around, but drivers do make direct calls to the network layer. Another question we have, how is DNS resolution handled? That is a problem for the host to resolve. You're sending data to TCP, UDP and other sockets on the host. However, it handles DNS resolution is the answer to that. And we only have one user, us. We're very excited to hear what other people might have and use cases that they could bring. Moving forward, there are still a few more features we need to build to get this ready for production. There is traffic flow control. We have a couple ideas for this, but I didn't have time to implement them before the talk. Things to apply TCP back pressure or other things to make sure that the USB link doesn't flood one side or the other. Considerations for high traffic systems are another thing. So for larger, large embedded devices having many bulk pairs to transport data across SOCs. A question from Robert is the HSS proxy running in Linux user space or as a part of the kernel? Because it's a new type of socket, it has to run as a part of the kernel. Another thing we do need to add is handling IO controls and a few other socket operations. We also need to make our distribution a bit more mature. And that a better way to distribute HSS until we're upstreamed because a new network device does require some kernel modifications. Looks like we have another question from Brent. What can I do with this that I cannot accomplish with existing CDC protocols? The primary benefit to this is that you don't have to know a lot about the device or sorry about the local network that you're talking to. If you're sending Ethernet packets, you usually have to have some identity with the router and an embedded device may not want to have to do that. This provides a very generic plug and play way to send data over your network. From William. Use case, USB armory. USB arm board that would benefit greatly when can device requests be made? Shoot me an email or contact me on Slack after this. I'll see what I can do. From Sophia. As a user tethering this reminder or sorry, that's an old comment. All right. And yeah, and again, part of the purpose of this is to see what we want to do moving forward the comments I'm getting from you all are excellent so far. So where to find it. The the Zaptum HSS repo has the host side implementation and the actual standard as a PDF it goes into more detail about some of the packets. And some algorithms to provide guarantees for which side processes what our device side implementation we currently have on top of our on top of the Linux distribution we use to deal with our use case. I want to have this moved into the HSS repo at some point, but I wasn't able to get a good way to integrate that in time for the speech. But these are the two places you can go to to find the software. All right. And if you want to contact me, this is my contact info information up here. Someone's indicating that the first link is broken. I will look into that immediate. I will look into that as soon as I'm done with this slide and try to provide a correction during the talk. All right, if you want to contact me my email GitHub and mostly empty personal website is up here and my employer who is paying me to be here and sponsoring obviously the production of this project Zaptum. I can take any further questions before ending the talk here. All right, well, it looks like it looks like that's it. Thank you very much for coming out to hear the talk. I'm going to look into the link being broken and post something in Slack as soon as I, as soon as I figure out what's going on with that. Thank you. Thank you, Marvin. Let me see if I can quickly figure out the link right here. I just typed the link in and it appears to be working without any problems. Maybe there's an issue if you're if you're clicking on the actual PowerPoint, perhaps it's pointing to the wrong location. Yes, there is a single quote at the beginning of that address in the actual PowerPoint. My apologies for that.