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