mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
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 <lkp@intel.com> Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
971f5c4079
commit
99ce45d5e7
@@ -434,6 +434,7 @@ static unsigned int mctp_route_mtu(struct mctp_route *rt)
|
||||
|
||||
static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb)
|
||||
{
|
||||
struct mctp_skb_cb *cb = mctp_cb(skb);
|
||||
struct mctp_hdr *hdr = mctp_hdr(skb);
|
||||
char daddr_buf[MAX_ADDR_LEN];
|
||||
char *daddr = NULL;
|
||||
@@ -448,9 +449,14 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb)
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* If lookup fails let the device handle daddr==NULL */
|
||||
if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0)
|
||||
daddr = daddr_buf;
|
||||
if (cb->ifindex) {
|
||||
/* direct route; use the hwaddr we stashed in sendmsg */
|
||||
daddr = cb->haddr;
|
||||
} else {
|
||||
/* If lookup fails let the device handle daddr==NULL */
|
||||
if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0)
|
||||
daddr = daddr_buf;
|
||||
}
|
||||
|
||||
rc = dev_hard_header(skb, skb->dev, ntohs(skb->protocol),
|
||||
daddr, skb->dev->dev_addr, skb->len);
|
||||
@@ -649,16 +655,6 @@ static struct mctp_route *mctp_route_lookup_null(struct net *net,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sends a skb to rt and releases the route. */
|
||||
int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = rt->output(rt, skb);
|
||||
mctp_route_release(rt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb,
|
||||
unsigned int mtu, u8 tag)
|
||||
{
|
||||
@@ -725,7 +721,7 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb,
|
||||
/* copy message payload */
|
||||
skb_copy_bits(skb, pos, skb_transport_header(skb2), size);
|
||||
|
||||
/* do route, but don't drop the rt reference */
|
||||
/* do route */
|
||||
rc = rt->output(rt, skb2);
|
||||
if (rc)
|
||||
break;
|
||||
@@ -734,7 +730,6 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb,
|
||||
pos += size;
|
||||
}
|
||||
|
||||
mctp_route_release(rt);
|
||||
consume_skb(skb);
|
||||
return rc;
|
||||
}
|
||||
@@ -744,15 +739,51 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt,
|
||||
{
|
||||
struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
|
||||
struct mctp_skb_cb *cb = mctp_cb(skb);
|
||||
struct mctp_route tmp_rt;
|
||||
struct net_device *dev;
|
||||
struct mctp_hdr *hdr;
|
||||
unsigned long flags;
|
||||
unsigned int mtu;
|
||||
mctp_eid_t saddr;
|
||||
bool ext_rt;
|
||||
int rc;
|
||||
u8 tag;
|
||||
|
||||
if (WARN_ON(!rt->dev))
|
||||
rc = -ENODEV;
|
||||
|
||||
if (rt) {
|
||||
ext_rt = false;
|
||||
dev = NULL;
|
||||
|
||||
if (WARN_ON(!rt->dev))
|
||||
goto out_release;
|
||||
|
||||
} else if (cb->ifindex) {
|
||||
ext_rt = true;
|
||||
rt = &tmp_rt;
|
||||
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(sock_net(sk), cb->ifindex);
|
||||
if (!dev) {
|
||||
rcu_read_unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
rt->dev = __mctp_dev_get(dev);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!rt->dev)
|
||||
goto out_release;
|
||||
|
||||
/* establish temporary route - we set up enough to keep
|
||||
* mctp_route_output happy
|
||||
*/
|
||||
rt->output = mctp_route_output;
|
||||
rt->mtu = 0;
|
||||
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rt->dev->addrs_lock, flags);
|
||||
if (rt->dev->num_addrs == 0) {
|
||||
@@ -765,18 +796,17 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt,
|
||||
spin_unlock_irqrestore(&rt->dev->addrs_lock, flags);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out_release;
|
||||
|
||||
if (req_tag & MCTP_HDR_FLAG_TO) {
|
||||
rc = mctp_alloc_local_tag(msk, saddr, daddr, &tag);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out_release;
|
||||
tag |= MCTP_HDR_FLAG_TO;
|
||||
} else {
|
||||
tag = req_tag;
|
||||
}
|
||||
|
||||
|
||||
skb->protocol = htons(ETH_P_MCTP);
|
||||
skb->priority = 0;
|
||||
skb_reset_transport_header(skb);
|
||||
@@ -796,12 +826,22 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt,
|
||||
mtu = mctp_route_mtu(rt);
|
||||
|
||||
if (skb->len + sizeof(struct mctp_hdr) <= mtu) {
|
||||
hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM |
|
||||
tag;
|
||||
return mctp_do_route(rt, skb);
|
||||
hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
|
||||
MCTP_HDR_FLAG_EOM | tag;
|
||||
rc = rt->output(rt, skb);
|
||||
} else {
|
||||
return mctp_do_fragment_route(rt, skb, mtu, tag);
|
||||
rc = mctp_do_fragment_route(rt, skb, mtu, tag);
|
||||
}
|
||||
|
||||
out_release:
|
||||
if (!ext_rt)
|
||||
mctp_route_release(rt);
|
||||
|
||||
if (dev)
|
||||
dev_put(dev);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
/* route management */
|
||||
@@ -942,8 +982,15 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev,
|
||||
if (mh->ver < MCTP_VER_MIN || mh->ver > MCTP_VER_MAX)
|
||||
goto err_drop;
|
||||
|
||||
cb = __mctp_cb(skb);
|
||||
/* MCTP drivers must populate halen/haddr */
|
||||
if (dev->type == ARPHRD_MCTP) {
|
||||
cb = mctp_cb(skb);
|
||||
} else {
|
||||
cb = __mctp_cb(skb);
|
||||
cb->halen = 0;
|
||||
}
|
||||
cb->net = READ_ONCE(mdev->net);
|
||||
cb->ifindex = dev->ifindex;
|
||||
|
||||
rt = mctp_route_lookup(net, cb->net, mh->dest);
|
||||
|
||||
@@ -954,7 +1001,8 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev,
|
||||
if (!rt)
|
||||
goto err_drop;
|
||||
|
||||
mctp_do_route(rt, skb);
|
||||
rt->output(rt, skb);
|
||||
mctp_route_release(rt);
|
||||
|
||||
return NET_RX_SUCCESS;
|
||||
|
||||
|
Reference in New Issue
Block a user