]>
Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
84314fd4 JS |
2 | /* |
3 | * scsi_netlink.c - SCSI Transport Netlink Interface | |
4 | * | |
5 | * Copyright (C) 2006 James Smart, Emulex Corporation | |
84314fd4 JS |
6 | */ |
7 | #include <linux/time.h> | |
8 | #include <linux/jiffies.h> | |
9 | #include <linux/security.h> | |
22447be7 | 10 | #include <linux/delay.h> |
5a0e3ad6 | 11 | #include <linux/slab.h> |
09703660 | 12 | #include <linux/export.h> |
84314fd4 JS |
13 | #include <net/sock.h> |
14 | #include <net/netlink.h> | |
15 | ||
16 | #include <scsi/scsi_netlink.h> | |
17 | #include "scsi_priv.h" | |
18 | ||
19 | struct sock *scsi_nl_sock = NULL; | |
20 | EXPORT_SYMBOL_GPL(scsi_nl_sock); | |
21 | ||
84314fd4 | 22 | /** |
eb44820c RL |
23 | * scsi_nl_rcv_msg - Receive message handler. |
24 | * @skb: socket receive buffer | |
25 | * | |
26 | * Description: Extracts message from a receive buffer. | |
84314fd4 JS |
27 | * Validates message header and calls appropriate transport message handler |
28 | * | |
84314fd4 JS |
29 | * |
30 | **/ | |
31 | static void | |
32 | scsi_nl_rcv_msg(struct sk_buff *skb) | |
33 | { | |
34 | struct nlmsghdr *nlh; | |
35 | struct scsi_nl_hdr *hdr; | |
22447be7 JS |
36 | u32 rlen; |
37 | int err, tport; | |
84314fd4 | 38 | |
e07ebea0 | 39 | while (skb->len >= NLMSG_HDRLEN) { |
84314fd4 JS |
40 | err = 0; |
41 | ||
b529ccf2 | 42 | nlh = nlmsg_hdr(skb); |
84314fd4 JS |
43 | if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) || |
44 | (skb->len < nlh->nlmsg_len)) { | |
45 | printk(KERN_WARNING "%s: discarding partial skb\n", | |
cadbd4a5 | 46 | __func__); |
84314fd4 JS |
47 | return; |
48 | } | |
49 | ||
50 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | |
51 | if (rlen > skb->len) | |
52 | rlen = skb->len; | |
53 | ||
54 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { | |
55 | err = -EBADMSG; | |
22447be7 | 56 | goto next_msg; |
84314fd4 JS |
57 | } |
58 | ||
e07ebea0 | 59 | hdr = nlmsg_data(nlh); |
84314fd4 JS |
60 | if ((hdr->version != SCSI_NL_VERSION) || |
61 | (hdr->magic != SCSI_NL_MAGIC)) { | |
62 | err = -EPROTOTYPE; | |
63 | goto next_msg; | |
64 | } | |
65 | ||
90f62cf3 | 66 | if (!netlink_capable(skb, CAP_SYS_ADMIN)) { |
84314fd4 JS |
67 | err = -EPERM; |
68 | goto next_msg; | |
69 | } | |
70 | ||
71 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { | |
72 | printk(KERN_WARNING "%s: discarding partial message\n", | |
cadbd4a5 | 73 | __func__); |
22447be7 | 74 | goto next_msg; |
84314fd4 JS |
75 | } |
76 | ||
77 | /* | |
22447be7 | 78 | * Deliver message to the appropriate transport |
84314fd4 | 79 | */ |
22447be7 | 80 | tport = hdr->transport; |
8289bab1 EB |
81 | if (tport == SCSI_NL_TRANSPORT) { |
82 | switch (hdr->msgtype) { | |
83 | case SCSI_NL_SHOST_VENDOR: | |
84 | /* Locate the driver that corresponds to the message */ | |
85 | err = -ESRCH; | |
86 | break; | |
87 | default: | |
88 | err = -EBADR; | |
89 | break; | |
90 | } | |
91 | if (err) | |
92 | printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", | |
93 | __func__, hdr->msgtype, err); | |
94 | } | |
95 | else | |
22447be7 JS |
96 | err = -ENOENT; |
97 | ||
84314fd4 JS |
98 | next_msg: |
99 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) | |
2d4bc933 | 100 | netlink_ack(skb, nlh, err, NULL); |
84314fd4 JS |
101 | |
102 | skb_pull(skb, rlen); | |
103 | } | |
104 | } | |
105 | ||
22447be7 | 106 | /** |
b595076a | 107 | * scsi_netlink_init - Called by SCSI subsystem to initialize |
22447be7 | 108 | * the SCSI transport netlink interface |
84314fd4 JS |
109 | * |
110 | **/ | |
111 | void | |
112 | scsi_netlink_init(void) | |
113 | { | |
a31f2d17 PNA |
114 | struct netlink_kernel_cfg cfg = { |
115 | .input = scsi_nl_rcv_msg, | |
116 | .groups = SCSI_NL_GRP_CNT, | |
117 | }; | |
84314fd4 | 118 | |
b4b51029 | 119 | scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, |
9f00d977 | 120 | &cfg); |
84314fd4 | 121 | if (!scsi_nl_sock) { |
25985edc | 122 | printk(KERN_ERR "%s: register of receive handler failed\n", |
cadbd4a5 | 123 | __func__); |
22447be7 | 124 | return; |
84314fd4 JS |
125 | } |
126 | ||
127 | return; | |
128 | } | |
129 | ||
130 | ||
131 | /** | |
eb44820c | 132 | * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface |
84314fd4 JS |
133 | * |
134 | **/ | |
135 | void | |
136 | scsi_netlink_exit(void) | |
137 | { | |
138 | if (scsi_nl_sock) { | |
b7c6ba6e | 139 | netlink_kernel_release(scsi_nl_sock); |
84314fd4 JS |
140 | } |
141 | ||
142 | return; | |
143 | } | |
144 |