Skip to content

Commit 99ce45d

Browse files
jk-ozlabsdavem330
authored andcommitted
mctp: Implement extended addressing
This change allows an extended address struct - struct sockaddr_mctp_ext - to be passed to sendmsg/recvmsg. This allows userspace to specify output ifindex and physical address information (for sendmsg) or receive the input ifindex/physaddr for incoming messages (for recvmsg). This is typically used by userspace for MCTP address discovery and assignment operations. The extended addressing facility is conditional on a new sockopt: MCTP_OPT_ADDR_EXT; userspace must explicitly enable addressing before the kernel will consume/populate the extended address data. Includes a fix for an uninitialised var: Reported-by: kernel test robot <[email protected]> Signed-off-by: Jeremy Kerr <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 971f5c4 commit 99ce45d

File tree

5 files changed

+170
-39
lines changed

5 files changed

+170
-39
lines changed

include/linux/socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ struct ucred {
365365
#define SOL_TLS 282
366366
#define SOL_XDP 283
367367
#define SOL_MPTCP 284
368+
#define SOL_MCTP 285
368369

369370
/* IPX options */
370371
#define IPX_TYPE 1

include/net/mctp.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <linux/bits.h>
1313
#include <linux/mctp.h>
14+
#include <linux/netdevice.h>
1415
#include <net/net_namespace.h>
1516
#include <net/sock.h>
1617

@@ -58,6 +59,9 @@ struct mctp_sock {
5859
mctp_eid_t bind_addr;
5960
__u8 bind_type;
6061

62+
/* sendmsg()/recvmsg() uses struct sockaddr_mctp_ext */
63+
bool addr_ext;
64+
6165
/* list of mctp_sk_key, for incoming tag lookup. updates protected
6266
* by sk->net->keys_lock
6367
*/
@@ -153,7 +157,10 @@ struct mctp_sk_key {
153157
struct mctp_skb_cb {
154158
unsigned int magic;
155159
unsigned int net;
160+
int ifindex; /* extended/direct addressing if set */
156161
mctp_eid_t src;
162+
unsigned char halen;
163+
unsigned char haddr[MAX_ADDR_LEN];
157164
};
158165

159166
/* skb control-block accessors with a little extra debugging for initial
@@ -177,6 +184,7 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
177184
{
178185
struct mctp_skb_cb *cb = (void *)skb->cb;
179186

187+
BUILD_BUG_ON(sizeof(struct mctp_skb_cb) > sizeof(skb->cb));
180188
WARN_ON(cb->magic != 0x4d435450);
181189
return (void *)(skb->cb);
182190
}
@@ -189,8 +197,7 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
189197
*
190198
* Updates to the route table are performed under rtnl; all reads under RCU,
191199
* so routes cannot be referenced over a RCU grace period. Specifically: A
192-
* caller cannot block between mctp_route_lookup and passing the route to
193-
* mctp_do_route.
200+
* caller cannot block between mctp_route_lookup and mctp_route_release()
194201
*/
195202
struct mctp_route {
196203
mctp_eid_t min, max;
@@ -210,8 +217,6 @@ struct mctp_route {
210217
struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet,
211218
mctp_eid_t daddr);
212219

213-
int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb);
214-
215220
int mctp_local_output(struct sock *sk, struct mctp_route *rt,
216221
struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);
217222

include/uapi/linux/mctp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <linux/types.h>
1313
#include <linux/socket.h>
14+
#include <linux/netdevice.h>
1415

1516
typedef __u8 mctp_eid_t;
1617

@@ -28,6 +29,14 @@ struct sockaddr_mctp {
2829
__u8 __smctp_pad1;
2930
};
3031

32+
struct sockaddr_mctp_ext {
33+
struct sockaddr_mctp smctp_base;
34+
int smctp_ifindex;
35+
__u8 smctp_halen;
36+
__u8 __smctp_pad0[3];
37+
__u8 smctp_haddr[MAX_ADDR_LEN];
38+
};
39+
3140
#define MCTP_NET_ANY 0x0
3241

3342
#define MCTP_ADDR_NULL 0x00
@@ -36,4 +45,6 @@ struct sockaddr_mctp {
3645
#define MCTP_TAG_MASK 0x07
3746
#define MCTP_TAG_OWNER 0x08
3847

48+
#define MCTP_OPT_ADDR_EXT 1
49+
3950
#endif /* __UAPI_MCTP_H */

net/mctp/af_mctp.c

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
7777
const int hlen = MCTP_HEADER_MAXLEN + sizeof(struct mctp_hdr);
7878
int rc, addrlen = msg->msg_namelen;
7979
struct sock *sk = sock->sk;
80+
struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
8081
struct mctp_skb_cb *cb;
8182
struct mctp_route *rt;
8283
struct sk_buff *skb;
@@ -100,11 +101,6 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
100101
if (addr->smctp_network == MCTP_NET_ANY)
101102
addr->smctp_network = mctp_default_net(sock_net(sk));
102103

103-
rt = mctp_route_lookup(sock_net(sk), addr->smctp_network,
104-
addr->smctp_addr.s_addr);
105-
if (!rt)
106-
return -EHOSTUNREACH;
107-
108104
skb = sock_alloc_send_skb(sk, hlen + 1 + len,
109105
msg->msg_flags & MSG_DONTWAIT, &rc);
110106
if (!skb)
@@ -116,26 +112,53 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
116112
*(u8 *)skb_put(skb, 1) = addr->smctp_type;
117113

118114
rc = memcpy_from_msg((void *)skb_put(skb, len), msg, len);
119-
if (rc < 0) {
120-
kfree_skb(skb);
121-
return rc;
122-
}
115+
if (rc < 0)
116+
goto err_free;
123117

124118
/* set up cb */
125119
cb = __mctp_cb(skb);
126120
cb->net = addr->smctp_network;
127121

122+
/* direct addressing */
123+
if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) {
124+
DECLARE_SOCKADDR(struct sockaddr_mctp_ext *,
125+
extaddr, msg->msg_name);
126+
127+
if (extaddr->smctp_halen > sizeof(cb->haddr)) {
128+
rc = -EINVAL;
129+
goto err_free;
130+
}
131+
132+
cb->ifindex = extaddr->smctp_ifindex;
133+
cb->halen = extaddr->smctp_halen;
134+
memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen);
135+
136+
rt = NULL;
137+
} else {
138+
rt = mctp_route_lookup(sock_net(sk), addr->smctp_network,
139+
addr->smctp_addr.s_addr);
140+
if (!rt) {
141+
rc = -EHOSTUNREACH;
142+
goto err_free;
143+
}
144+
}
145+
128146
rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr,
129147
addr->smctp_tag);
130148

131149
return rc ? : len;
150+
151+
err_free:
152+
kfree_skb(skb);
153+
return rc;
132154
}
133155

134156
static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
135157
int flags)
136158
{
137159
DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name);
138160
struct sock *sk = sock->sk;
161+
struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
139162
struct sk_buff *skb;
140163
size_t msglen;
141164
u8 type;
@@ -181,6 +204,16 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
181204
addr->smctp_tag = hdr->flags_seq_tag &
182205
(MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO);
183206
msg->msg_namelen = sizeof(*addr);
207+
208+
if (msk->addr_ext) {
209+
DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, ae,
210+
msg->msg_name);
211+
msg->msg_namelen = sizeof(*ae);
212+
ae->smctp_ifindex = cb->ifindex;
213+
ae->smctp_halen = cb->halen;
214+
memset(ae->smctp_haddr, 0x0, sizeof(ae->smctp_haddr));
215+
memcpy(ae->smctp_haddr, cb->haddr, cb->halen);
216+
}
184217
}
185218

186219
rc = len;
@@ -196,12 +229,45 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
196229
static int mctp_setsockopt(struct socket *sock, int level, int optname,
197230
sockptr_t optval, unsigned int optlen)
198231
{
199-
return -EINVAL;
232+
struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
233+
int val;
234+
235+
if (level != SOL_MCTP)
236+
return -EINVAL;
237+
238+
if (optname == MCTP_OPT_ADDR_EXT) {
239+
if (optlen != sizeof(int))
240+
return -EINVAL;
241+
if (copy_from_sockptr(&val, optval, sizeof(int)))
242+
return -EFAULT;
243+
msk->addr_ext = val;
244+
return 0;
245+
}
246+
247+
return -ENOPROTOOPT;
200248
}
201249

202250
static int mctp_getsockopt(struct socket *sock, int level, int optname,
203251
char __user *optval, int __user *optlen)
204252
{
253+
struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk);
254+
int len, val;
255+
256+
if (level != SOL_MCTP)
257+
return -EINVAL;
258+
259+
if (get_user(len, optlen))
260+
return -EFAULT;
261+
262+
if (optname == MCTP_OPT_ADDR_EXT) {
263+
if (len != sizeof(int))
264+
return -EINVAL;
265+
val = !!msk->addr_ext;
266+
if (copy_to_user(optval, &val, len))
267+
return -EFAULT;
268+
return 0;
269+
}
270+
205271
return -EINVAL;
206272
}
207273

0 commit comments

Comments
 (0)