Libreswan code related to NAT-T support detection in the kernel looks very confusing to me. Could someone explain why we need to compile in KLIPS in order for NAT-T to be detected with NETKEY?
NAT-T support gets detected in nat_traversal_espinudp_socket() as follows (I'm omitting irrelevant code to reduce clutter): int nat_traversal_espinudp_socket(int sk, const char *fam) { int r; struct ifreq ifr; int *fdp = (int *) &ifr.ifr_data; const char *ifn; DBG(DBG_NATT, DBG_log("NAT-Traversal: Trying new style NAT-T")); zero(&ifr); switch (kern_interface) { /* ... OR: omitted for brevity */ case USE_NETKEY: /* Let's hope we have at least one ethernet device */ ifn = "eth0"; break; /* ... OR: omitted for brevity */ } strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name)); fdp[0] = sk; fdp[1] = ESPINUDP_WITH_NON_ESP; /* no longer support non-ike or non-floating */ r = ioctl(sk, IPSEC_UDP_ENCAP_CONVERT, &ifr); if (r == -1) { /* OR: signal failure to support new style NAT-T and errno */ } else { /* OR: signal success */ return r; } /* OR: If we failed to detect new style NAT-T, try old style NAT-T detection... */ } As far as I can see, the above code is bound to fail with NETKEY. The ioctl() system call on the socket is serviced in the kernel by sock_ioctl() and then subsequently by dev_ifsioc() as follows. static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) { int err; struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); const struct net_device_ops *ops; if (!dev) return -ENODEV; ops = dev->netdev_ops; switch (cmd) { /* OR: omitted for brevity */ default: if ((cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 15) /* omitted */ err = -EOPNOTSUPP; if (ops->ndo_do_ioctl) { if (netif_device_present(dev)) err = ops->ndo_do_ioctl(dev, ifr, cmd); else err = -ENODEV; } } } First of all, we hard-code "eth0" in our struct ifreq that gets passed to the kernel. On a machine with no "eth0", this will fail with ENODEV, as the above code illustrates. On a machine that does have "eth0", this is most probably going to fail with EOPNOTSUPP, since SIOCDEVPRIVATE + 3 means nothing to an average NIC driver (?). The question is: is new NAT-T detection really supposed to work with NETKEY? The test for the old style NAT-T is compiled conditionally: #if defined(KLIPS) DBG(DBG_NATT, DBG_log("NAT-Traversal: Trying old style NAT-T")); const int type = ESPINUDP_WITH_NON_ESP; r = setsockopt(sk, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type)); if (r == -1) { /* OR: signal failure to support old style NAT-T */ } else { /* OR: signal success */ return r; } # else DBG(DBG_NATT, DBG_log("NAT-Traversal: ESPINUDP() setup for old style NAT-T family not available - KLIPS support not compiled in")); #endif Setting the socket option works perfectly with NETKEY. At first sight I'd say the KLIPS-related #if directives rather belong around the new style NAT-T detection portion. Could anybody explain the reason of the conditional compilation for old-style NAT-T? Many thanks, Oleg Rosowiecki _______________________________________________ Swan-dev mailing list Swan-dev@lists.libreswan.org https://lists.libreswan.org/mailman/listinfo/swan-dev