Skip to content

Commit c288752

Browse files
zhhyu7jerpelea
authored andcommitted
recvmsg: control msg support multi-attribute return
adapts to third-party code compilation. in the process of porting ConnMan, multiple control message options are enabled, such as IPV6_RECVPKTINFO and IPV6_RECVHOPLIMIT, so I changed the Filling implementation of the control message. Signed-off-by: zhanghongyu <[email protected]>
1 parent bac304a commit c288752

File tree

7 files changed

+164
-68
lines changed

7 files changed

+164
-68
lines changed

net/can/can_recvmsg.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848

4949
#ifdef CONFIG_NET_TIMESTAMP
5050
#include <sys/time.h>
51+
#include <utils/utils.h>
5152
#endif
5253

5354
/****************************************************************************
@@ -490,24 +491,14 @@ ssize_t can_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
490491
state.pr_buffer = msg->msg_iov->iov_base;
491492

492493
#ifdef CONFIG_NET_TIMESTAMP
493-
if (conn->timestamp && msg->msg_controllen >=
494-
(sizeof(struct cmsghdr) + sizeof(struct timeval)))
494+
if (conn->timestamp)
495495
{
496-
struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
497-
state.pr_msglen = sizeof(struct timeval);
498-
state.pr_msgbuf = CMSG_DATA(cmsg);
499-
cmsg->cmsg_level = SOL_SOCKET;
500-
cmsg->cmsg_type = SO_TIMESTAMP;
501-
cmsg->cmsg_len = state.pr_msglen;
502-
msg->msg_controllen = sizeof(struct cmsghdr) + sizeof(struct timeval);
503-
}
504-
else
505-
{
506-
/* Expected behavior is that the msg_controllen becomes 0,
507-
* otherwise CMSG_NXTHDR will go into a infinite loop
508-
*/
509-
510-
msg->msg_controllen = 0;
496+
state.pr_msgbuf = cmsg_append(msg, SOL_SOCKET, SO_TIMESTAMP,
497+
NULL, sizeof(struct timeval));
498+
if (state.pr_msgbuf != NULL)
499+
{
500+
state.pr_msglen = sizeof(struct timeval);
501+
}
511502
}
512503
#endif
513504

net/local/local_recvmsg.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040

4141
#include "socket/socket.h"
4242
#include "local/local.h"
43+
#include "utils/utils.h"
4344

4445
/****************************************************************************
4546
* Private Functions
@@ -117,22 +118,12 @@ static void local_recvctl(FAR struct local_conn_s *conn,
117118
FAR struct msghdr *msg, int flags)
118119
{
119120
FAR struct local_conn_s *peer;
120-
struct cmsghdr *cmsg;
121121
int count;
122122
int *fds;
123123
int i;
124124

125125
net_lock();
126126

127-
cmsg = CMSG_FIRSTHDR(msg);
128-
count = (cmsg->cmsg_len - sizeof(struct cmsghdr)) / sizeof(int);
129-
cmsg->cmsg_len = 0;
130-
131-
if (count == 0)
132-
{
133-
goto out;
134-
}
135-
136127
if (conn->lc_peer == NULL)
137128
{
138129
peer = local_peerconn(conn);
@@ -151,10 +142,14 @@ static void local_recvctl(FAR struct local_conn_s *conn,
151142
goto out;
152143
}
153144

154-
fds = (int *)CMSG_DATA(cmsg);
145+
fds = cmsg_append(msg, SOL_SOCKET, SCM_RIGHTS, NULL,
146+
sizeof(int) * peer->lc_cfpcount);
147+
if (fds == NULL)
148+
{
149+
goto out;
150+
}
155151

156-
count = count > peer->lc_cfpcount ?
157-
peer->lc_cfpcount : count;
152+
count = peer->lc_cfpcount;
158153
for (i = 0; i < count; i++)
159154
{
160155
fds[i] = file_dup(peer->lc_cfps[i], 0, !!(flags & MSG_CMSG_CLOEXEC));
@@ -176,10 +171,6 @@ static void local_recvctl(FAR struct local_conn_s *conn,
176171
memmove(peer->lc_cfps[0], peer->lc_cfps[i],
177172
sizeof(FAR void *) * peer->lc_cfpcount);
178173
}
179-
180-
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * i);
181-
cmsg->cmsg_level = SOL_SOCKET;
182-
cmsg->cmsg_type = SCM_RIGHTS;
183174
}
184175

185176
out:

net/socket/recvmsg.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@
6969
ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
7070
int flags)
7171
{
72+
unsigned long msg_controllen;
73+
FAR void *msg_control;
74+
int ret;
75+
7276
/* Verify that non-NULL pointers were passed */
7377

7478
if (msg == NULL || msg->msg_iov == NULL || msg->msg_iov->iov_base == NULL)
@@ -100,7 +104,19 @@ ssize_t psock_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg,
100104
DEBUGASSERT(psock->s_sockif != NULL &&
101105
psock->s_sockif->si_recvmsg != NULL);
102106

103-
return psock->s_sockif->si_recvmsg(psock, msg, flags);
107+
/* Save the original cmsg information */
108+
109+
msg_control = msg->msg_control;
110+
msg_controllen = msg->msg_controllen;
111+
112+
ret = psock->s_sockif->si_recvmsg(psock, msg, flags);
113+
114+
/* Recover the pointer and calculate the cmsg's true data length */
115+
116+
msg->msg_control = msg_control;
117+
msg->msg_controllen = msg_controllen - msg->msg_controllen;
118+
119+
return ret;
104120
}
105121

106122
/****************************************************************************

net/udp/udp_recvfrom.c

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "devif/devif.h"
4343
#include "udp/udp.h"
4444
#include "socket/socket.h"
45+
#include "utils/utils.h"
4546

4647
/****************************************************************************
4748
* Private Types
@@ -64,59 +65,41 @@ struct udp_recvfrom_s
6465
static void udp_recvpktinfo(FAR struct udp_recvfrom_s *pstate,
6566
FAR void *srcaddr, uint8_t ifindex)
6667
{
67-
FAR struct msghdr *msg = pstate->ir_msg;
68-
FAR struct udp_conn_s *conn = pstate->ir_conn;
69-
FAR struct cmsghdr *control = msg->msg_control;
70-
size_t cmsg_len = 0;
68+
FAR struct msghdr *msg = pstate->ir_msg;
69+
FAR struct udp_conn_s *conn = pstate->ir_conn;
7170

7271
if (!(conn->flags & _UDP_FLAG_PKTINFO))
7372
{
74-
goto out;
73+
return;
7574
}
7675

7776
#ifdef CONFIG_NET_IPv4
7877
if (conn->domain == PF_INET)
7978
{
80-
FAR struct sockaddr_in *infrom = srcaddr;
81-
FAR struct in_pktinfo *pkt_info = CMSG_DATA(control);
79+
FAR struct sockaddr_in *infrom = srcaddr;
80+
FAR struct in_pktinfo pktinfo;
8281

83-
if (msg->msg_controllen < CMSG_LEN(sizeof(struct in_pktinfo)))
84-
{
85-
goto out;
86-
}
82+
pktinfo.ipi_ifindex = ifindex;
83+
pktinfo.ipi_addr.s_addr = infrom->sin_addr.s_addr;
84+
pktinfo.ipi_spec_dst.s_addr = conn->u.ipv4.laddr;
8785

88-
cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
89-
control->cmsg_level = IPPROTO_IP;
90-
control->cmsg_type = IP_PKTINFO;
91-
control->cmsg_len = cmsg_len;
92-
pkt_info->ipi_ifindex = ifindex;
93-
pkt_info->ipi_addr.s_addr = infrom->sin_addr.s_addr;
94-
pkt_info->ipi_spec_dst.s_addr = conn->u.ipv4.laddr;
86+
cmsg_append(msg, IPPROTO_IP, IP_PKTINFO, &pktinfo, sizeof(pktinfo));
9587
}
9688
#endif
9789

9890
#ifdef CONFIG_NET_IPv6
9991
if (conn->domain == PF_INET6)
10092
{
101-
FAR struct sockaddr_in6 *infrom = srcaddr;
102-
FAR struct in6_pktinfo *pkt_info = CMSG_DATA(control);
93+
FAR struct sockaddr_in6 *infrom = srcaddr;
94+
FAR struct in6_pktinfo pktinfo;
10395

104-
if (msg->msg_controllen < CMSG_LEN(sizeof(struct in6_pktinfo)))
105-
{
106-
goto out;
107-
}
96+
pktinfo.ipi6_ifindex = ifindex;
97+
net_ipv6addr_copy(&pktinfo.ipi6_addr, infrom->sin6_addr.s6_addr);
10898

109-
cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
110-
control->cmsg_level = IPPROTO_IPV6;
111-
control->cmsg_type = IPV6_PKTINFO;
112-
control->cmsg_len = cmsg_len;
113-
pkt_info->ipi6_ifindex = ifindex;
114-
net_ipv6addr_copy(&pkt_info->ipi6_addr, infrom->sin6_addr.s6_addr);
99+
cmsg_append(msg, IPPROTO_IPV6, IPV6_PKTINFO, &pktinfo,
100+
sizeof(pktinfo));
115101
}
116102
#endif
117-
118-
out:
119-
msg->msg_controllen = cmsg_len;
120103
}
121104

122105
/****************************************************************************

net/utils/Make.defs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
NET_CSRCS += net_dsec2tick.c net_dsec2timeval.c net_timeval2dsec.c
2424
NET_CSRCS += net_chksum.c net_ipchksum.c net_incr32.c net_lock.c net_snoop.c
25+
NET_CSRCS += net_cmsg.c
2526

2627
# IPv6 utilities
2728

net/utils/net_cmsg.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/****************************************************************************
2+
* net/utils/net_cmsg.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <nuttx/config.h>
26+
27+
#include <sys/socket.h>
28+
29+
#include "utils/utils.h"
30+
31+
/****************************************************************************
32+
* Public Functions
33+
****************************************************************************/
34+
35+
/****************************************************************************
36+
* Name: cmsg_append
37+
*
38+
* Description:
39+
* Append specified data into the control message, msg_control and
40+
* msg_controllen will be changed to the appropriate value when success
41+
*
42+
* Input Parameters:
43+
* msg - Buffer to receive the message.
44+
* level - The level of control message.
45+
* type - The type of control message.
46+
* value - If the value is not NULL, this interface copies the data
47+
* to the appropriate location in msg_control, and modify
48+
* msg_control and msg_controllen.
49+
* If the value is NULL, just modify the corresponding value
50+
* of msg.
51+
* value_len - The value length of control message.
52+
*
53+
* Returned Value:
54+
* On success, a pointer to the start address of control message data,
55+
* the caller can copy the data in.
56+
* On failure, return NULL, because of msg_controllen is not enough
57+
*
58+
****************************************************************************/
59+
60+
FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type,
61+
FAR void *value, int value_len)
62+
{
63+
FAR struct cmsghdr *cmsg;
64+
unsigned long cmsgspace = CMSG_SPACE(value_len);
65+
FAR void *cmsgdata;
66+
67+
if (msg->msg_controllen < cmsgspace)
68+
{
69+
return NULL;
70+
}
71+
72+
cmsg = CMSG_FIRSTHDR(msg);
73+
cmsg->cmsg_level = level;
74+
cmsg->cmsg_type = type;
75+
cmsg->cmsg_len = CMSG_LEN(value_len);
76+
cmsgdata = CMSG_DATA(cmsg);
77+
if (value)
78+
{
79+
memcpy(cmsgdata, value, value_len);
80+
}
81+
82+
msg->msg_control += cmsgspace;
83+
msg->msg_controllen -= cmsgspace;
84+
85+
return cmsgdata;
86+
}

net/utils/utils.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,34 @@ uint16_t icmp_chksum_iob(FAR struct iob_s *iob);
311311
uint16_t icmpv6_chksum(FAR struct net_driver_s *dev, unsigned int iplen);
312312
#endif
313313

314+
/****************************************************************************
315+
* Name: cmsg_append
316+
*
317+
* Description:
318+
* Append specified data into the control message, msg_control and
319+
* msg_controllen will be changed to the appropriate value when success
320+
*
321+
* Input Parameters:
322+
* msg - Buffer to receive the message.
323+
* level - The level of control message.
324+
* type - The type of control message.
325+
* value - If the value is not NULL, this interface copies the data
326+
* to the appropriate location in msg_control, and modify
327+
* msg_control and msg_controllen.
328+
* If the value is NULL, just modify the corresponding value
329+
* of msg.
330+
* value_len - The value length of control message.
331+
*
332+
* Returned Value:
333+
* On success, a pointer to the start address of control message data,
334+
* the caller can copy the data in.
335+
* On failure, return NULL, because of msg_controllen is not enough
336+
*
337+
****************************************************************************/
338+
339+
FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type,
340+
FAR void *value, int value_len);
341+
314342
#undef EXTERN
315343
#ifdef __cplusplus
316344
}

0 commit comments

Comments
 (0)