Lines Matching +full:mctp +full:- +full:handling

1 // SPDX-License-Identifier: GPL-2.0
3 * Management Component Transport Protocol (MCTP)
12 #include <linux/mctp.h>
16 #include <net/mctp.h>
21 #include <trace/events/mctp.h>
29 struct sock *sk = sock->sk; in mctp_release()
32 sock->sk = NULL; in mctp_release()
33 sk->sk_prot->close(sk, 0); in mctp_release()
42 return !addr->__smctp_pad0 && !addr->__smctp_pad1; in mctp_sockaddr_is_ok()
47 return !addr->__smctp_pad0[0] && in mctp_sockaddr_ext_is_ok()
48 !addr->__smctp_pad0[1] && in mctp_sockaddr_ext_is_ok()
49 !addr->__smctp_pad0[2]; in mctp_sockaddr_ext_is_ok()
54 struct sock *sk = sock->sk; in mctp_bind()
60 return -EINVAL; in mctp_bind()
62 if (addr->sa_family != AF_MCTP) in mctp_bind()
63 return -EAFNOSUPPORT; in mctp_bind()
66 return -EACCES; in mctp_bind()
68 /* it's a valid sockaddr for MCTP, cast and do protocol checks */ in mctp_bind()
72 return -EINVAL; in mctp_bind()
78 rc = -EADDRINUSE; in mctp_bind()
81 msk->bind_net = smctp->smctp_network; in mctp_bind()
82 msk->bind_addr = smctp->smctp_addr.s_addr; in mctp_bind()
83 msk->bind_type = smctp->smctp_type & 0x7f; /* ignore the IC bit */ in mctp_bind()
85 rc = sk->sk_prot->hash(sk); in mctp_bind()
95 DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name); in mctp_sendmsg()
96 int rc, addrlen = msg->msg_namelen; in mctp_sendmsg()
97 struct sock *sk = sock->sk; in mctp_sendmsg()
109 return -EINVAL; in mctp_sendmsg()
110 if (addr->smctp_family != AF_MCTP) in mctp_sendmsg()
111 return -EINVAL; in mctp_sendmsg()
113 return -EINVAL; in mctp_sendmsg()
114 if (addr->smctp_tag & ~tagbits) in mctp_sendmsg()
115 return -EINVAL; in mctp_sendmsg()
116 /* can't preallocate a non-owned tag */ in mctp_sendmsg()
117 if (addr->smctp_tag & MCTP_TAG_PREALLOC && in mctp_sendmsg()
118 !(addr->smctp_tag & MCTP_TAG_OWNER)) in mctp_sendmsg()
119 return -EINVAL; in mctp_sendmsg()
123 return -EDESTADDRREQ; in mctp_sendmsg()
127 return -EACCES; in mctp_sendmsg()
129 if (addr->smctp_network == MCTP_NET_ANY) in mctp_sendmsg()
130 addr->smctp_network = mctp_default_net(sock_net(sk)); in mctp_sendmsg()
133 if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) { in mctp_sendmsg()
135 extaddr, msg->msg_name); in mctp_sendmsg()
138 rc = -EINVAL; in mctp_sendmsg()
140 dev = dev_get_by_index_rcu(sock_net(sk), extaddr->smctp_ifindex); in mctp_sendmsg()
142 if (dev && extaddr->smctp_halen == dev->addr_len) { in mctp_sendmsg()
151 rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, in mctp_sendmsg()
152 addr->smctp_addr.s_addr); in mctp_sendmsg()
154 rc = -EHOSTUNREACH; in mctp_sendmsg()
157 hlen = LL_RESERVED_SPACE(rt->dev->dev) + sizeof(struct mctp_hdr); in mctp_sendmsg()
161 msg->msg_flags & MSG_DONTWAIT, &rc); in mctp_sendmsg()
168 *(u8 *)skb_put(skb, 1) = addr->smctp_type; in mctp_sendmsg()
176 cb->net = addr->smctp_network; in mctp_sendmsg()
181 extaddr, msg->msg_name); in mctp_sendmsg()
184 extaddr->smctp_halen > sizeof(cb->haddr)) { in mctp_sendmsg()
185 rc = -EINVAL; in mctp_sendmsg()
189 cb->ifindex = extaddr->smctp_ifindex; in mctp_sendmsg()
191 cb->halen = extaddr->smctp_halen; in mctp_sendmsg()
192 memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen); in mctp_sendmsg()
195 rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr, in mctp_sendmsg()
196 addr->smctp_tag); in mctp_sendmsg()
208 DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name); in mctp_recvmsg()
209 struct sock *sk = sock->sk; in mctp_recvmsg()
217 return -EOPNOTSUPP; in mctp_recvmsg()
223 if (!skb->len) { in mctp_recvmsg()
229 type = *((u8 *)skb->data); in mctp_recvmsg()
230 msglen = skb->len - 1; in mctp_recvmsg()
233 msg->msg_flags |= MSG_TRUNC; in mctp_recvmsg()
248 addr = msg->msg_name; in mctp_recvmsg()
249 addr->smctp_family = AF_MCTP; in mctp_recvmsg()
250 addr->__smctp_pad0 = 0; in mctp_recvmsg()
251 addr->smctp_network = cb->net; in mctp_recvmsg()
252 addr->smctp_addr.s_addr = hdr->src; in mctp_recvmsg()
253 addr->smctp_type = type; in mctp_recvmsg()
254 addr->smctp_tag = hdr->flags_seq_tag & in mctp_recvmsg()
256 addr->__smctp_pad1 = 0; in mctp_recvmsg()
257 msg->msg_namelen = sizeof(*addr); in mctp_recvmsg()
259 if (msk->addr_ext) { in mctp_recvmsg()
261 msg->msg_name); in mctp_recvmsg()
262 msg->msg_namelen = sizeof(*ae); in mctp_recvmsg()
263 ae->smctp_ifindex = cb->ifindex; in mctp_recvmsg()
264 ae->smctp_halen = cb->halen; in mctp_recvmsg()
265 memset(ae->__smctp_pad0, 0x0, sizeof(ae->__smctp_pad0)); in mctp_recvmsg()
266 memset(ae->smctp_haddr, 0x0, sizeof(ae->smctp_haddr)); in mctp_recvmsg()
267 memcpy(ae->smctp_haddr, cb->haddr, cb->halen); in mctp_recvmsg()
285 __releases(&key->lock) in __mctp_key_remove()
286 __must_hold(&net->mctp.keys_lock) in __mctp_key_remove()
291 skb = key->reasm_head; in __mctp_key_remove()
292 key->reasm_head = NULL; in __mctp_key_remove()
293 key->reasm_dead = true; in __mctp_key_remove()
294 key->valid = false; in __mctp_key_remove()
295 mctp_dev_release_key(key->dev, key); in __mctp_key_remove()
296 spin_unlock_irqrestore(&key->lock, flags); in __mctp_key_remove()
298 if (!hlist_unhashed(&key->hlist)) { in __mctp_key_remove()
299 hlist_del_init(&key->hlist); in __mctp_key_remove()
300 hlist_del_init(&key->sklist); in __mctp_key_remove()
311 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); in mctp_setsockopt()
315 return -EINVAL; in mctp_setsockopt()
319 return -EINVAL; in mctp_setsockopt()
321 return -EFAULT; in mctp_setsockopt()
322 msk->addr_ext = val; in mctp_setsockopt()
326 return -ENOPROTOOPT; in mctp_setsockopt()
332 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); in mctp_getsockopt()
336 return -EINVAL; in mctp_getsockopt()
339 return -EFAULT; in mctp_getsockopt()
343 return -EINVAL; in mctp_getsockopt()
344 val = !!msk->addr_ext; in mctp_getsockopt()
346 return -EFAULT; in mctp_getsockopt()
350 return -EINVAL; in mctp_getsockopt()
353 /* helpers for reading/writing the tag ioc, handling compatibility across the
375 return -EFAULT; in mctp_ioctl_tag_copy_from_user()
379 ctl->net = MCTP_INITIAL_DEFAULT_NET; in mctp_ioctl_tag_copy_from_user()
380 ctl->peer_addr = ctl_compat.peer_addr; in mctp_ioctl_tag_copy_from_user()
381 ctl->local_addr = MCTP_ADDR_ANY; in mctp_ioctl_tag_copy_from_user()
382 ctl->flags = ctl_compat.flags; in mctp_ioctl_tag_copy_from_user()
383 ctl->tag = ctl_compat.tag; in mctp_ioctl_tag_copy_from_user()
386 if (ctl->flags) in mctp_ioctl_tag_copy_from_user()
387 return -EINVAL; in mctp_ioctl_tag_copy_from_user()
389 if (ctl->local_addr != MCTP_ADDR_ANY && in mctp_ioctl_tag_copy_from_user()
390 ctl->local_addr != MCTP_ADDR_NULL) in mctp_ioctl_tag_copy_from_user()
391 return -EINVAL; in mctp_ioctl_tag_copy_from_user()
409 ctl_compat.peer_addr = ctl->peer_addr; in mctp_ioctl_tag_copy_to_user()
410 ctl_compat.tag = ctl->tag; in mctp_ioctl_tag_copy_to_user()
411 ctl_compat.flags = ctl->flags; in mctp_ioctl_tag_copy_to_user()
419 return -EFAULT; in mctp_ioctl_tag_copy_to_user()
427 struct net *net = sock_net(&msk->sk); in mctp_ioctl_alloctag()
439 return -EINVAL; in mctp_ioctl_alloctag()
455 spin_lock_irqsave(&net->mctp.keys_lock, flags); in mctp_ioctl_alloctag()
456 spin_lock_irqsave(&key->lock, fl2); in mctp_ioctl_alloctag()
459 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); in mctp_ioctl_alloctag()
470 struct net *net = sock_net(&msk->sk); in mctp_ioctl_droptag()
484 return -EINVAL; in mctp_ioctl_droptag()
487 rc = -EINVAL; in mctp_ioctl_droptag()
492 spin_lock_irqsave(&net->mctp.keys_lock, flags); in mctp_ioctl_droptag()
493 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { in mctp_ioctl_droptag()
497 spin_lock_irqsave(&key->lock, fl2); in mctp_ioctl_droptag()
498 if (key->manual_alloc && in mctp_ioctl_droptag()
499 ctl.net == key->net && in mctp_ioctl_droptag()
500 ctl.peer_addr == key->peer_addr && in mctp_ioctl_droptag()
501 tag == key->tag) { in mctp_ioctl_droptag()
506 spin_unlock_irqrestore(&key->lock, fl2); in mctp_ioctl_droptag()
509 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); in mctp_ioctl_droptag()
516 struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); in mctp_ioctl()
530 return -EINVAL; in mctp_ioctl()
546 return -ENOIOCTLCMD; in mctp_compat_ioctl()
577 struct net *net = sock_net(&msk->sk); in mctp_sk_expire_keys()
583 spin_lock_irqsave(&net->mctp.keys_lock, flags); in mctp_sk_expire_keys()
585 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { in mctp_sk_expire_keys()
589 if (key->manual_alloc) in mctp_sk_expire_keys()
592 spin_lock_irqsave(&key->lock, fl2); in mctp_sk_expire_keys()
593 if (!time_after_eq(key->expiry, jiffies)) { in mctp_sk_expire_keys()
600 if (time_before(key->expiry, next_expiry)) in mctp_sk_expire_keys()
601 next_expiry = key->expiry; in mctp_sk_expire_keys()
603 next_expiry = key->expiry; in mctp_sk_expire_keys()
606 spin_unlock_irqrestore(&key->lock, fl2); in mctp_sk_expire_keys()
609 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); in mctp_sk_expire_keys()
619 INIT_HLIST_HEAD(&msk->keys); in mctp_sk_init()
620 timer_setup(&msk->key_expiry, mctp_sk_expire_keys, 0); in mctp_sk_init()
633 mutex_lock(&net->mctp.bind_lock); in mctp_sk_hash()
634 sk_add_node_rcu(sk, &net->mctp.binds); in mctp_sk_hash()
635 mutex_unlock(&net->mctp.bind_lock); in mctp_sk_hash()
648 /* remove from any type-based binds */ in mctp_sk_unhash()
649 mutex_lock(&net->mctp.bind_lock); in mctp_sk_unhash()
651 mutex_unlock(&net->mctp.bind_lock); in mctp_sk_unhash()
654 spin_lock_irqsave(&net->mctp.keys_lock, flags); in mctp_sk_unhash()
655 hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) { in mctp_sk_unhash()
656 spin_lock_irqsave(&key->lock, fl2); in mctp_sk_unhash()
660 spin_unlock_irqrestore(&net->mctp.keys_lock, flags); in mctp_sk_unhash()
663 * keys), stop any pending expiry events. the timer cannot be re-queued in mctp_sk_unhash()
666 del_timer_sync(&msk->key_expiry); in mctp_sk_unhash()
671 skb_queue_purge(&sk->sk_receive_queue); in mctp_sk_destruct()
675 .name = "MCTP",
693 return -EPROTONOSUPPORT; in mctp_pf_create()
696 if (sock->type != SOCK_DGRAM) in mctp_pf_create()
697 return -ESOCKTNOSUPPORT; in mctp_pf_create()
702 sock->state = SS_UNCONNECTED; in mctp_pf_create()
703 sock->ops = ops; in mctp_pf_create()
707 return -ENOMEM; in mctp_pf_create()
710 sk->sk_destruct = mctp_sk_destruct; in mctp_pf_create()
713 if (sk->sk_prot->init) in mctp_pf_create()
714 rc = sk->sk_prot->init(sk); in mctp_pf_create()
741 pr_info("mctp: management component transport protocol core\n"); in mctp_init()
789 MODULE_DESCRIPTION("MCTP core");