}
 EXPORT_SYMBOL_GPL(l2tp_tunnel_free);
 
+/* Create a socket for the tunnel, if one isn't set up by
+ * userspace. This is used for static tunnels where there is no
+ * managing L2TP daemon.
+ */
+static int l2tp_tunnel_sock_create(u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct socket **sockp)
+{
+       int err = -EINVAL;
+       struct sockaddr_in udp_addr;
+       struct sockaddr_l2tpip ip_addr;
+       struct socket *sock;
+
+       switch (cfg->encap) {
+       case L2TP_ENCAPTYPE_UDP:
+               err = sock_create(AF_INET, SOCK_DGRAM, 0, sockp);
+               if (err < 0)
+                       goto out;
+
+               sock = *sockp;
+
+               memset(&udp_addr, 0, sizeof(udp_addr));
+               udp_addr.sin_family = AF_INET;
+               udp_addr.sin_addr = cfg->local_ip;
+               udp_addr.sin_port = htons(cfg->local_udp_port);
+               err = kernel_bind(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr));
+               if (err < 0)
+                       goto out;
+
+               udp_addr.sin_family = AF_INET;
+               udp_addr.sin_addr = cfg->peer_ip;
+               udp_addr.sin_port = htons(cfg->peer_udp_port);
+               err = kernel_connect(sock, (struct sockaddr *) &udp_addr, sizeof(udp_addr), 0);
+               if (err < 0)
+                       goto out;
+
+               if (!cfg->use_udp_checksums)
+                       sock->sk->sk_no_check = UDP_CSUM_NOXMIT;
+
+               break;
+
+       case L2TP_ENCAPTYPE_IP:
+               err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_L2TP, sockp);
+               if (err < 0)
+                       goto out;
+
+               sock = *sockp;
+
+               memset(&ip_addr, 0, sizeof(ip_addr));
+               ip_addr.l2tp_family = AF_INET;
+               ip_addr.l2tp_addr = cfg->local_ip;
+               ip_addr.l2tp_conn_id = tunnel_id;
+               err = kernel_bind(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr));
+               if (err < 0)
+                       goto out;
+
+               ip_addr.l2tp_family = AF_INET;
+               ip_addr.l2tp_addr = cfg->peer_ip;
+               ip_addr.l2tp_conn_id = peer_tunnel_id;
+               err = kernel_connect(sock, (struct sockaddr *) &ip_addr, sizeof(ip_addr), 0);
+               if (err < 0)
+                       goto out;
+
+               break;
+
+       default:
+               goto out;
+       }
+
+out:
+       if ((err < 0) && sock) {
+               sock_release(sock);
+               *sockp = NULL;
+       }
+
+       return err;
+}
+
 int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
 {
        struct l2tp_tunnel *tunnel = NULL;
        enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP;
 
        /* Get the tunnel socket from the fd, which was opened by
-        * the userspace L2TP daemon.
+        * the userspace L2TP daemon. If not specified, create a
+        * kernel socket.
         */
-       err = -EBADF;
-       sock = sockfd_lookup(fd, &err);
-       if (!sock) {
-               printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
-                      tunnel_id, fd, err);
-               goto err;
+       if (fd < 0) {
+               err = l2tp_tunnel_sock_create(tunnel_id, peer_tunnel_id, cfg, &sock);
+               if (err < 0)
+                       goto err;
+       } else {
+               err = -EBADF;
+               sock = sockfd_lookup(fd, &err);
+               if (!sock) {
+                       printk(KERN_ERR "tunl %hu: sockfd_lookup(fd=%d) returned %d\n",
+                              tunnel_id, fd, err);
+                       goto err;
+               }
        }
 
        sk = sock->sk;
        if (tunnelp)
                *tunnelp = tunnel;
 
-       if (sock)
+       /* If tunnel's socket was created by the kernel, it doesn't
+        *  have a file.
+        */
+       if (sock && sock->file)
                sockfd_put(sock);
 
        return err;
 int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
        int err = 0;
+       struct socket *sock = tunnel->sock ? tunnel->sock->sk_socket : NULL;
 
        /* Force the tunnel socket to close. This will eventually
         * cause the tunnel to be deleted via the normal socket close
         * mechanisms when userspace closes the tunnel socket.
         */
-       if ((tunnel->sock != NULL) && (tunnel->sock->sk_socket != NULL))
-               err = inet_shutdown(tunnel->sock->sk_socket, 2);
+       if (sock != NULL) {
+               err = inet_shutdown(sock, 2);
+
+               /* If the tunnel's socket was created by the kernel,
+                * close the socket here since the socket was not
+                * created by userspace.
+                */
+               if (sock->file == NULL)
+                       err = inet_release(sock);
+       }
 
        return err;
 }
 
        }
        cfg.encap = nla_get_u16(info->attrs[L2TP_ATTR_ENCAP_TYPE]);
 
-       if (!info->attrs[L2TP_ATTR_FD]) {
-               ret = -EINVAL;
-               goto out;
+       fd = -1;
+       if (info->attrs[L2TP_ATTR_FD]) {
+               fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
+       } else {
+               if (info->attrs[L2TP_ATTR_IP_SADDR])
+                       cfg.local_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_SADDR]);
+               if (info->attrs[L2TP_ATTR_IP_DADDR])
+                       cfg.peer_ip.s_addr = nla_get_be32(info->attrs[L2TP_ATTR_IP_DADDR]);
+               if (info->attrs[L2TP_ATTR_UDP_SPORT])
+                       cfg.local_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_SPORT]);
+               if (info->attrs[L2TP_ATTR_UDP_DPORT])
+                       cfg.peer_udp_port = nla_get_u16(info->attrs[L2TP_ATTR_UDP_DPORT]);
+               if (info->attrs[L2TP_ATTR_UDP_CSUM])
+                       cfg.use_udp_checksums = nla_get_flag(info->attrs[L2TP_ATTR_UDP_CSUM]);
        }
-       fd = nla_get_u32(info->attrs[L2TP_ATTR_FD]);
 
        if (info->attrs[L2TP_ATTR_DEBUG])
                cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]);