blob: b3aeca6486e37ce2d96e9b30a20507a2b4697b20 [file] [log] [blame]
Jeremy Kerrbc49d812021-07-29 10:20:39 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Management Component Transport Protocol (MCTP)
4 *
5 * Copyright (c) 2021 Code Construct
6 * Copyright (c) 2021 Google
7 */
8
Jeremy Kerr8f601a12021-07-29 10:20:40 +08009#include <linux/net.h>
10#include <linux/mctp.h>
Jeremy Kerrbc49d812021-07-29 10:20:39 +080011#include <linux/module.h>
Jeremy Kerr8f601a12021-07-29 10:20:40 +080012#include <linux/socket.h>
13
14#include <net/sock.h>
15
16struct mctp_sock {
17 struct sock sk;
18};
19
20static int mctp_release(struct socket *sock)
21{
22 struct sock *sk = sock->sk;
23
24 if (sk) {
25 sock->sk = NULL;
26 sk->sk_prot->close(sk, 0);
27 }
28
29 return 0;
30}
31
32static int mctp_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
33{
34 return 0;
35}
36
37static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
38{
39 return 0;
40}
41
42static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
43 int flags)
44{
45 return 0;
46}
47
48static int mctp_setsockopt(struct socket *sock, int level, int optname,
49 sockptr_t optval, unsigned int optlen)
50{
51 return -EINVAL;
52}
53
54static int mctp_getsockopt(struct socket *sock, int level, int optname,
55 char __user *optval, int __user *optlen)
56{
57 return -EINVAL;
58}
59
60static const struct proto_ops mctp_dgram_ops = {
61 .family = PF_MCTP,
62 .release = mctp_release,
63 .bind = mctp_bind,
64 .connect = sock_no_connect,
65 .socketpair = sock_no_socketpair,
66 .accept = sock_no_accept,
67 .getname = sock_no_getname,
68 .poll = datagram_poll,
69 .ioctl = sock_no_ioctl,
70 .gettstamp = sock_gettstamp,
71 .listen = sock_no_listen,
72 .shutdown = sock_no_shutdown,
73 .setsockopt = mctp_setsockopt,
74 .getsockopt = mctp_getsockopt,
75 .sendmsg = mctp_sendmsg,
76 .recvmsg = mctp_recvmsg,
77 .mmap = sock_no_mmap,
78 .sendpage = sock_no_sendpage,
79};
80
81static void mctp_sk_close(struct sock *sk, long timeout)
82{
83 sk_common_release(sk);
84}
85
86static struct proto mctp_proto = {
87 .name = "MCTP",
88 .owner = THIS_MODULE,
89 .obj_size = sizeof(struct mctp_sock),
90 .close = mctp_sk_close,
91};
92
93static int mctp_pf_create(struct net *net, struct socket *sock,
94 int protocol, int kern)
95{
96 const struct proto_ops *ops;
97 struct proto *proto;
98 struct sock *sk;
99 int rc;
100
101 if (protocol)
102 return -EPROTONOSUPPORT;
103
104 /* only datagram sockets are supported */
105 if (sock->type != SOCK_DGRAM)
106 return -ESOCKTNOSUPPORT;
107
108 proto = &mctp_proto;
109 ops = &mctp_dgram_ops;
110
111 sock->state = SS_UNCONNECTED;
112 sock->ops = ops;
113
114 sk = sk_alloc(net, PF_MCTP, GFP_KERNEL, proto, kern);
115 if (!sk)
116 return -ENOMEM;
117
118 sock_init_data(sock, sk);
119
120 rc = 0;
121 if (sk->sk_prot->init)
122 rc = sk->sk_prot->init(sk);
123
124 if (rc)
125 goto err_sk_put;
126
127 return 0;
128
129err_sk_put:
130 sock_orphan(sk);
131 sock_put(sk);
132 return rc;
133}
134
135static struct net_proto_family mctp_pf = {
136 .family = PF_MCTP,
137 .create = mctp_pf_create,
138 .owner = THIS_MODULE,
139};
140
141static __init int mctp_init(void)
142{
143 int rc;
144
145 pr_info("mctp: management component transport protocol core\n");
146
147 rc = sock_register(&mctp_pf);
148 if (rc)
149 return rc;
150
151 rc = proto_register(&mctp_proto, 0);
152 if (rc)
153 goto err_unreg_sock;
154
155 return 0;
156
157err_unreg_sock:
158 sock_unregister(PF_MCTP);
159
160 return rc;
161}
162
163static __exit void mctp_exit(void)
164{
165 proto_unregister(&mctp_proto);
166 sock_unregister(PF_MCTP);
167}
168
169module_init(mctp_init);
170module_exit(mctp_exit);
Jeremy Kerrbc49d812021-07-29 10:20:39 +0800171
172MODULE_DESCRIPTION("MCTP core");
173MODULE_LICENSE("GPL v2");
174MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
Jeremy Kerr8f601a12021-07-29 10:20:40 +0800175
176MODULE_ALIAS_NETPROTO(PF_MCTP);