Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Management Component Transport Protocol (MCTP)
0004  *
0005  * Copyright (c) 2021 Code Construct
0006  * Copyright (c) 2021 Google
0007  */
0008 
0009 #include <linux/compat.h>
0010 #include <linux/if_arp.h>
0011 #include <linux/net.h>
0012 #include <linux/mctp.h>
0013 #include <linux/module.h>
0014 #include <linux/socket.h>
0015 
0016 #include <net/mctp.h>
0017 #include <net/mctpdevice.h>
0018 #include <net/sock.h>
0019 
0020 #define CREATE_TRACE_POINTS
0021 #include <trace/events/mctp.h>
0022 
0023 /* socket implementation */
0024 
0025 static void mctp_sk_expire_keys(struct timer_list *timer);
0026 
0027 static int mctp_release(struct socket *sock)
0028 {
0029     struct sock *sk = sock->sk;
0030 
0031     if (sk) {
0032         sock->sk = NULL;
0033         sk->sk_prot->close(sk, 0);
0034     }
0035 
0036     return 0;
0037 }
0038 
0039 /* Generic sockaddr checks, padding checks only so far */
0040 static bool mctp_sockaddr_is_ok(const struct sockaddr_mctp *addr)
0041 {
0042     return !addr->__smctp_pad0 && !addr->__smctp_pad1;
0043 }
0044 
0045 static bool mctp_sockaddr_ext_is_ok(const struct sockaddr_mctp_ext *addr)
0046 {
0047     return !addr->__smctp_pad0[0] &&
0048            !addr->__smctp_pad0[1] &&
0049            !addr->__smctp_pad0[2];
0050 }
0051 
0052 static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
0053 {
0054     struct sock *sk = sock->sk;
0055     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0056     struct sockaddr_mctp *smctp;
0057     int rc;
0058 
0059     if (addrlen < sizeof(*smctp))
0060         return -EINVAL;
0061 
0062     if (addr->sa_family != AF_MCTP)
0063         return -EAFNOSUPPORT;
0064 
0065     if (!capable(CAP_NET_BIND_SERVICE))
0066         return -EACCES;
0067 
0068     /* it's a valid sockaddr for MCTP, cast and do protocol checks */
0069     smctp = (struct sockaddr_mctp *)addr;
0070 
0071     if (!mctp_sockaddr_is_ok(smctp))
0072         return -EINVAL;
0073 
0074     lock_sock(sk);
0075 
0076     /* TODO: allow rebind */
0077     if (sk_hashed(sk)) {
0078         rc = -EADDRINUSE;
0079         goto out_release;
0080     }
0081     msk->bind_net = smctp->smctp_network;
0082     msk->bind_addr = smctp->smctp_addr.s_addr;
0083     msk->bind_type = smctp->smctp_type & 0x7f; /* ignore the IC bit */
0084 
0085     rc = sk->sk_prot->hash(sk);
0086 
0087 out_release:
0088     release_sock(sk);
0089 
0090     return rc;
0091 }
0092 
0093 static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
0094 {
0095     DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name);
0096     int rc, addrlen = msg->msg_namelen;
0097     struct sock *sk = sock->sk;
0098     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0099     struct mctp_skb_cb *cb;
0100     struct mctp_route *rt;
0101     struct sk_buff *skb = NULL;
0102     int hlen;
0103 
0104     if (addr) {
0105         const u8 tagbits = MCTP_TAG_MASK | MCTP_TAG_OWNER |
0106             MCTP_TAG_PREALLOC;
0107 
0108         if (addrlen < sizeof(struct sockaddr_mctp))
0109             return -EINVAL;
0110         if (addr->smctp_family != AF_MCTP)
0111             return -EINVAL;
0112         if (!mctp_sockaddr_is_ok(addr))
0113             return -EINVAL;
0114         if (addr->smctp_tag & ~tagbits)
0115             return -EINVAL;
0116         /* can't preallocate a non-owned tag */
0117         if (addr->smctp_tag & MCTP_TAG_PREALLOC &&
0118             !(addr->smctp_tag & MCTP_TAG_OWNER))
0119             return -EINVAL;
0120 
0121     } else {
0122         /* TODO: connect()ed sockets */
0123         return -EDESTADDRREQ;
0124     }
0125 
0126     if (!capable(CAP_NET_RAW))
0127         return -EACCES;
0128 
0129     if (addr->smctp_network == MCTP_NET_ANY)
0130         addr->smctp_network = mctp_default_net(sock_net(sk));
0131 
0132     /* direct addressing */
0133     if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) {
0134         DECLARE_SOCKADDR(struct sockaddr_mctp_ext *,
0135                  extaddr, msg->msg_name);
0136         struct net_device *dev;
0137 
0138         rc = -EINVAL;
0139         rcu_read_lock();
0140         dev = dev_get_by_index_rcu(sock_net(sk), extaddr->smctp_ifindex);
0141         /* check for correct halen */
0142         if (dev && extaddr->smctp_halen == dev->addr_len) {
0143             hlen = LL_RESERVED_SPACE(dev) + sizeof(struct mctp_hdr);
0144             rc = 0;
0145         }
0146         rcu_read_unlock();
0147         if (rc)
0148             goto err_free;
0149         rt = NULL;
0150     } else {
0151         rt = mctp_route_lookup(sock_net(sk), addr->smctp_network,
0152                        addr->smctp_addr.s_addr);
0153         if (!rt) {
0154             rc = -EHOSTUNREACH;
0155             goto err_free;
0156         }
0157         hlen = LL_RESERVED_SPACE(rt->dev->dev) + sizeof(struct mctp_hdr);
0158     }
0159 
0160     skb = sock_alloc_send_skb(sk, hlen + 1 + len,
0161                   msg->msg_flags & MSG_DONTWAIT, &rc);
0162     if (!skb)
0163         return rc;
0164 
0165     skb_reserve(skb, hlen);
0166 
0167     /* set type as fist byte in payload */
0168     *(u8 *)skb_put(skb, 1) = addr->smctp_type;
0169 
0170     rc = memcpy_from_msg((void *)skb_put(skb, len), msg, len);
0171     if (rc < 0)
0172         goto err_free;
0173 
0174     /* set up cb */
0175     cb = __mctp_cb(skb);
0176     cb->net = addr->smctp_network;
0177 
0178     if (!rt) {
0179         /* fill extended address in cb */
0180         DECLARE_SOCKADDR(struct sockaddr_mctp_ext *,
0181                  extaddr, msg->msg_name);
0182 
0183         if (!mctp_sockaddr_ext_is_ok(extaddr) ||
0184             extaddr->smctp_halen > sizeof(cb->haddr)) {
0185             rc = -EINVAL;
0186             goto err_free;
0187         }
0188 
0189         cb->ifindex = extaddr->smctp_ifindex;
0190         /* smctp_halen is checked above */
0191         cb->halen = extaddr->smctp_halen;
0192         memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen);
0193     }
0194 
0195     rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr,
0196                    addr->smctp_tag);
0197 
0198     return rc ? : len;
0199 
0200 err_free:
0201     kfree_skb(skb);
0202     return rc;
0203 }
0204 
0205 static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
0206             int flags)
0207 {
0208     DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name);
0209     struct sock *sk = sock->sk;
0210     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0211     struct sk_buff *skb;
0212     size_t msglen;
0213     u8 type;
0214     int rc;
0215 
0216     if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK))
0217         return -EOPNOTSUPP;
0218 
0219     skb = skb_recv_datagram(sk, flags, &rc);
0220     if (!skb)
0221         return rc;
0222 
0223     if (!skb->len) {
0224         rc = 0;
0225         goto out_free;
0226     }
0227 
0228     /* extract message type, remove from data */
0229     type = *((u8 *)skb->data);
0230     msglen = skb->len - 1;
0231 
0232     if (len < msglen)
0233         msg->msg_flags |= MSG_TRUNC;
0234     else
0235         len = msglen;
0236 
0237     rc = skb_copy_datagram_msg(skb, 1, msg, len);
0238     if (rc < 0)
0239         goto out_free;
0240 
0241     sock_recv_cmsgs(msg, sk, skb);
0242 
0243     if (addr) {
0244         struct mctp_skb_cb *cb = mctp_cb(skb);
0245         /* TODO: expand mctp_skb_cb for header fields? */
0246         struct mctp_hdr *hdr = mctp_hdr(skb);
0247 
0248         addr = msg->msg_name;
0249         addr->smctp_family = AF_MCTP;
0250         addr->__smctp_pad0 = 0;
0251         addr->smctp_network = cb->net;
0252         addr->smctp_addr.s_addr = hdr->src;
0253         addr->smctp_type = type;
0254         addr->smctp_tag = hdr->flags_seq_tag &
0255                     (MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO);
0256         addr->__smctp_pad1 = 0;
0257         msg->msg_namelen = sizeof(*addr);
0258 
0259         if (msk->addr_ext) {
0260             DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, ae,
0261                      msg->msg_name);
0262             msg->msg_namelen = sizeof(*ae);
0263             ae->smctp_ifindex = cb->ifindex;
0264             ae->smctp_halen = cb->halen;
0265             memset(ae->__smctp_pad0, 0x0, sizeof(ae->__smctp_pad0));
0266             memset(ae->smctp_haddr, 0x0, sizeof(ae->smctp_haddr));
0267             memcpy(ae->smctp_haddr, cb->haddr, cb->halen);
0268         }
0269     }
0270 
0271     rc = len;
0272 
0273     if (flags & MSG_TRUNC)
0274         rc = msglen;
0275 
0276 out_free:
0277     skb_free_datagram(sk, skb);
0278     return rc;
0279 }
0280 
0281 /* We're done with the key; invalidate, stop reassembly, and remove from lists.
0282  */
0283 static void __mctp_key_remove(struct mctp_sk_key *key, struct net *net,
0284                   unsigned long flags, unsigned long reason)
0285 __releases(&key->lock)
0286 __must_hold(&net->mctp.keys_lock)
0287 {
0288     struct sk_buff *skb;
0289 
0290     trace_mctp_key_release(key, reason);
0291     skb = key->reasm_head;
0292     key->reasm_head = NULL;
0293     key->reasm_dead = true;
0294     key->valid = false;
0295     mctp_dev_release_key(key->dev, key);
0296     spin_unlock_irqrestore(&key->lock, flags);
0297 
0298     hlist_del(&key->hlist);
0299     hlist_del(&key->sklist);
0300 
0301     /* unref for the lists */
0302     mctp_key_unref(key);
0303 
0304     kfree_skb(skb);
0305 }
0306 
0307 static int mctp_setsockopt(struct socket *sock, int level, int optname,
0308                sockptr_t optval, unsigned int optlen)
0309 {
0310     struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
0311     int val;
0312 
0313     if (level != SOL_MCTP)
0314         return -EINVAL;
0315 
0316     if (optname == MCTP_OPT_ADDR_EXT) {
0317         if (optlen != sizeof(int))
0318             return -EINVAL;
0319         if (copy_from_sockptr(&val, optval, sizeof(int)))
0320             return -EFAULT;
0321         msk->addr_ext = val;
0322         return 0;
0323     }
0324 
0325     return -ENOPROTOOPT;
0326 }
0327 
0328 static int mctp_getsockopt(struct socket *sock, int level, int optname,
0329                char __user *optval, int __user *optlen)
0330 {
0331     struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
0332     int len, val;
0333 
0334     if (level != SOL_MCTP)
0335         return -EINVAL;
0336 
0337     if (get_user(len, optlen))
0338         return -EFAULT;
0339 
0340     if (optname == MCTP_OPT_ADDR_EXT) {
0341         if (len != sizeof(int))
0342             return -EINVAL;
0343         val = !!msk->addr_ext;
0344         if (copy_to_user(optval, &val, len))
0345             return -EFAULT;
0346         return 0;
0347     }
0348 
0349     return -EINVAL;
0350 }
0351 
0352 static int mctp_ioctl_alloctag(struct mctp_sock *msk, unsigned long arg)
0353 {
0354     struct net *net = sock_net(&msk->sk);
0355     struct mctp_sk_key *key = NULL;
0356     struct mctp_ioc_tag_ctl ctl;
0357     unsigned long flags;
0358     u8 tag;
0359 
0360     if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl)))
0361         return -EFAULT;
0362 
0363     if (ctl.tag)
0364         return -EINVAL;
0365 
0366     if (ctl.flags)
0367         return -EINVAL;
0368 
0369     key = mctp_alloc_local_tag(msk, ctl.peer_addr, MCTP_ADDR_ANY,
0370                    true, &tag);
0371     if (IS_ERR(key))
0372         return PTR_ERR(key);
0373 
0374     ctl.tag = tag | MCTP_TAG_OWNER | MCTP_TAG_PREALLOC;
0375     if (copy_to_user((void __user *)arg, &ctl, sizeof(ctl))) {
0376         spin_lock_irqsave(&key->lock, flags);
0377         __mctp_key_remove(key, net, flags, MCTP_TRACE_KEY_DROPPED);
0378         mctp_key_unref(key);
0379         return -EFAULT;
0380     }
0381 
0382     mctp_key_unref(key);
0383     return 0;
0384 }
0385 
0386 static int mctp_ioctl_droptag(struct mctp_sock *msk, unsigned long arg)
0387 {
0388     struct net *net = sock_net(&msk->sk);
0389     struct mctp_ioc_tag_ctl ctl;
0390     unsigned long flags, fl2;
0391     struct mctp_sk_key *key;
0392     struct hlist_node *tmp;
0393     int rc;
0394     u8 tag;
0395 
0396     if (copy_from_user(&ctl, (void __user *)arg, sizeof(ctl)))
0397         return -EFAULT;
0398 
0399     if (ctl.flags)
0400         return -EINVAL;
0401 
0402     /* Must be a local tag, TO set, preallocated */
0403     if ((ctl.tag & ~MCTP_TAG_MASK) != (MCTP_TAG_OWNER | MCTP_TAG_PREALLOC))
0404         return -EINVAL;
0405 
0406     tag = ctl.tag & MCTP_TAG_MASK;
0407     rc = -EINVAL;
0408 
0409     spin_lock_irqsave(&net->mctp.keys_lock, flags);
0410     hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) {
0411         /* we do an irqsave here, even though we know the irq state,
0412          * so we have the flags to pass to __mctp_key_remove
0413          */
0414         spin_lock_irqsave(&key->lock, fl2);
0415         if (key->manual_alloc &&
0416             ctl.peer_addr == key->peer_addr &&
0417             tag == key->tag) {
0418             __mctp_key_remove(key, net, fl2,
0419                       MCTP_TRACE_KEY_DROPPED);
0420             rc = 0;
0421         } else {
0422             spin_unlock_irqrestore(&key->lock, fl2);
0423         }
0424     }
0425     spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
0426 
0427     return rc;
0428 }
0429 
0430 static int mctp_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
0431 {
0432     struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
0433 
0434     switch (cmd) {
0435     case SIOCMCTPALLOCTAG:
0436         return mctp_ioctl_alloctag(msk, arg);
0437     case SIOCMCTPDROPTAG:
0438         return mctp_ioctl_droptag(msk, arg);
0439     }
0440 
0441     return -EINVAL;
0442 }
0443 
0444 #ifdef CONFIG_COMPAT
0445 static int mctp_compat_ioctl(struct socket *sock, unsigned int cmd,
0446                  unsigned long arg)
0447 {
0448     void __user *argp = compat_ptr(arg);
0449 
0450     switch (cmd) {
0451     /* These have compatible ptr layouts */
0452     case SIOCMCTPALLOCTAG:
0453     case SIOCMCTPDROPTAG:
0454         return mctp_ioctl(sock, cmd, (unsigned long)argp);
0455     }
0456 
0457     return -ENOIOCTLCMD;
0458 }
0459 #endif
0460 
0461 static const struct proto_ops mctp_dgram_ops = {
0462     .family     = PF_MCTP,
0463     .release    = mctp_release,
0464     .bind       = mctp_bind,
0465     .connect    = sock_no_connect,
0466     .socketpair = sock_no_socketpair,
0467     .accept     = sock_no_accept,
0468     .getname    = sock_no_getname,
0469     .poll       = datagram_poll,
0470     .ioctl      = mctp_ioctl,
0471     .gettstamp  = sock_gettstamp,
0472     .listen     = sock_no_listen,
0473     .shutdown   = sock_no_shutdown,
0474     .setsockopt = mctp_setsockopt,
0475     .getsockopt = mctp_getsockopt,
0476     .sendmsg    = mctp_sendmsg,
0477     .recvmsg    = mctp_recvmsg,
0478     .mmap       = sock_no_mmap,
0479     .sendpage   = sock_no_sendpage,
0480 #ifdef CONFIG_COMPAT
0481     .compat_ioctl   = mctp_compat_ioctl,
0482 #endif
0483 };
0484 
0485 static void mctp_sk_expire_keys(struct timer_list *timer)
0486 {
0487     struct mctp_sock *msk = container_of(timer, struct mctp_sock,
0488                          key_expiry);
0489     struct net *net = sock_net(&msk->sk);
0490     unsigned long next_expiry, flags, fl2;
0491     struct mctp_sk_key *key;
0492     struct hlist_node *tmp;
0493     bool next_expiry_valid = false;
0494 
0495     spin_lock_irqsave(&net->mctp.keys_lock, flags);
0496 
0497     hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) {
0498         /* don't expire. manual_alloc is immutable, no locking
0499          * required.
0500          */
0501         if (key->manual_alloc)
0502             continue;
0503 
0504         spin_lock_irqsave(&key->lock, fl2);
0505         if (!time_after_eq(key->expiry, jiffies)) {
0506             __mctp_key_remove(key, net, fl2,
0507                       MCTP_TRACE_KEY_TIMEOUT);
0508             continue;
0509         }
0510 
0511         if (next_expiry_valid) {
0512             if (time_before(key->expiry, next_expiry))
0513                 next_expiry = key->expiry;
0514         } else {
0515             next_expiry = key->expiry;
0516             next_expiry_valid = true;
0517         }
0518         spin_unlock_irqrestore(&key->lock, fl2);
0519     }
0520 
0521     spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
0522 
0523     if (next_expiry_valid)
0524         mod_timer(timer, next_expiry);
0525 }
0526 
0527 static int mctp_sk_init(struct sock *sk)
0528 {
0529     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0530 
0531     INIT_HLIST_HEAD(&msk->keys);
0532     timer_setup(&msk->key_expiry, mctp_sk_expire_keys, 0);
0533     return 0;
0534 }
0535 
0536 static void mctp_sk_close(struct sock *sk, long timeout)
0537 {
0538     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0539 
0540     del_timer_sync(&msk->key_expiry);
0541     sk_common_release(sk);
0542 }
0543 
0544 static int mctp_sk_hash(struct sock *sk)
0545 {
0546     struct net *net = sock_net(sk);
0547 
0548     mutex_lock(&net->mctp.bind_lock);
0549     sk_add_node_rcu(sk, &net->mctp.binds);
0550     mutex_unlock(&net->mctp.bind_lock);
0551 
0552     return 0;
0553 }
0554 
0555 static void mctp_sk_unhash(struct sock *sk)
0556 {
0557     struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
0558     struct net *net = sock_net(sk);
0559     unsigned long flags, fl2;
0560     struct mctp_sk_key *key;
0561     struct hlist_node *tmp;
0562 
0563     /* remove from any type-based binds */
0564     mutex_lock(&net->mctp.bind_lock);
0565     sk_del_node_init_rcu(sk);
0566     mutex_unlock(&net->mctp.bind_lock);
0567 
0568     /* remove tag allocations */
0569     spin_lock_irqsave(&net->mctp.keys_lock, flags);
0570     hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) {
0571         spin_lock_irqsave(&key->lock, fl2);
0572         __mctp_key_remove(key, net, fl2, MCTP_TRACE_KEY_CLOSED);
0573     }
0574     spin_unlock_irqrestore(&net->mctp.keys_lock, flags);
0575 }
0576 
0577 static struct proto mctp_proto = {
0578     .name       = "MCTP",
0579     .owner      = THIS_MODULE,
0580     .obj_size   = sizeof(struct mctp_sock),
0581     .init       = mctp_sk_init,
0582     .close      = mctp_sk_close,
0583     .hash       = mctp_sk_hash,
0584     .unhash     = mctp_sk_unhash,
0585 };
0586 
0587 static int mctp_pf_create(struct net *net, struct socket *sock,
0588               int protocol, int kern)
0589 {
0590     const struct proto_ops *ops;
0591     struct proto *proto;
0592     struct sock *sk;
0593     int rc;
0594 
0595     if (protocol)
0596         return -EPROTONOSUPPORT;
0597 
0598     /* only datagram sockets are supported */
0599     if (sock->type != SOCK_DGRAM)
0600         return -ESOCKTNOSUPPORT;
0601 
0602     proto = &mctp_proto;
0603     ops = &mctp_dgram_ops;
0604 
0605     sock->state = SS_UNCONNECTED;
0606     sock->ops = ops;
0607 
0608     sk = sk_alloc(net, PF_MCTP, GFP_KERNEL, proto, kern);
0609     if (!sk)
0610         return -ENOMEM;
0611 
0612     sock_init_data(sock, sk);
0613 
0614     rc = 0;
0615     if (sk->sk_prot->init)
0616         rc = sk->sk_prot->init(sk);
0617 
0618     if (rc)
0619         goto err_sk_put;
0620 
0621     return 0;
0622 
0623 err_sk_put:
0624     sock_orphan(sk);
0625     sock_put(sk);
0626     return rc;
0627 }
0628 
0629 static struct net_proto_family mctp_pf = {
0630     .family = PF_MCTP,
0631     .create = mctp_pf_create,
0632     .owner = THIS_MODULE,
0633 };
0634 
0635 static __init int mctp_init(void)
0636 {
0637     int rc;
0638 
0639     /* ensure our uapi tag definitions match the header format */
0640     BUILD_BUG_ON(MCTP_TAG_OWNER != MCTP_HDR_FLAG_TO);
0641     BUILD_BUG_ON(MCTP_TAG_MASK != MCTP_HDR_TAG_MASK);
0642 
0643     pr_info("mctp: management component transport protocol core\n");
0644 
0645     rc = sock_register(&mctp_pf);
0646     if (rc)
0647         return rc;
0648 
0649     rc = proto_register(&mctp_proto, 0);
0650     if (rc)
0651         goto err_unreg_sock;
0652 
0653     rc = mctp_routes_init();
0654     if (rc)
0655         goto err_unreg_proto;
0656 
0657     rc = mctp_neigh_init();
0658     if (rc)
0659         goto err_unreg_proto;
0660 
0661     mctp_device_init();
0662 
0663     return 0;
0664 
0665 err_unreg_proto:
0666     proto_unregister(&mctp_proto);
0667 err_unreg_sock:
0668     sock_unregister(PF_MCTP);
0669 
0670     return rc;
0671 }
0672 
0673 static __exit void mctp_exit(void)
0674 {
0675     mctp_device_exit();
0676     mctp_neigh_exit();
0677     mctp_routes_exit();
0678     proto_unregister(&mctp_proto);
0679     sock_unregister(PF_MCTP);
0680 }
0681 
0682 subsys_initcall(mctp_init);
0683 module_exit(mctp_exit);
0684 
0685 MODULE_DESCRIPTION("MCTP core");
0686 MODULE_LICENSE("GPL v2");
0687 MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
0688 
0689 MODULE_ALIAS_NETPROTO(PF_MCTP);