1 /* SCTP kernel Implementation: User API extensions.
2  *
3  * sctp_recvmsg.c
4  *
5  * Distributed under the terms of the LGPL v2.1 as described in
6  *    http://www.gnu.org/copyleft/lesser.txt
7  *
8  * This file is part of the user library that offers support for the
9  * SCTP kernel Implementation. The main purpose of this
10  * code is to provide the SCTP Socket API mappings for user
11  * application to interface with the SCTP in kernel.
12  *
13  * This implementation is based on the Socket API Extensions for SCTP
14  * defined in <draft-ietf-tsvwg-sctpsocket-10.txt>
15  *
16  * Copyright (c) 2003 International Business Machines, Corp.
17  *
18  * Written or modified by:
19  *  Ryan Layer	<rmlayer@us.ibm.com>
20  *
21  * An implementation may provide a library function (or possibly system
22  * call) to assist the user with the advanced features of SCTP. Note
23  * that in order for the sctp_sndrcvinfo structure to be filled in by
24  * sctp_recvmsg() the caller must enable the sctp_data_io_events with
25  * the SCTP_EVENTS option.
26  *
27  * sctp_recvmsg(). Its syntax is,
28  *
29  * int sctp_recvmsg(int s,
30  *		    void *msg,
31  *		    size_t len,
32  *		    struct sockaddr *from,
33  *		    socklen_t *fromlen,
34  *		    struct sctp_sndrcvinfo *sinfo,
35  *		    int *msg_flags)
36  *
37  *
38  * s          - is the socket descriptor
39  * msg        - is a message buffer to be filled.
40  * len        - is the length of the message buffer.
41  * from       - is a pointer to a address to be filled with
42  *		the sender of this messages address.
43  * fromlen    - is the from length.
44  * sinfo      - A pointer to a sctp_sndrcvinfo structure
45  *		to be filled upon receipt of the message.
46  * msg_flags  - A pointer to a integer to be filled with
47  *		any message flags (e.g. MSG_NOTIFICATION).
48  */
49 
50 #include <string.h>
51 #include <errno.h>
52 #include <sys/socket.h>   /* struct sockaddr_storage, setsockopt() */
53 #include <netinet/sctp.h>
54 
sctp_recvmsg(int s,void * msg,size_t len,struct sockaddr * from,socklen_t * fromlen,struct sctp_sndrcvinfo * sinfo,int * msg_flags)55 int sctp_recvmsg(int s, void *msg, size_t len, struct sockaddr *from,
56 		 socklen_t *fromlen, struct sctp_sndrcvinfo *sinfo,
57 		 int *msg_flags)
58 {
59 	int error;
60 	struct iovec iov;
61 	struct msghdr inmsg;
62 	char incmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
63 	struct cmsghdr *cmsg = NULL;
64 
65 	memset(&inmsg, 0, sizeof (inmsg));
66 
67 	iov.iov_base = msg;
68 	iov.iov_len = len;
69 
70 	inmsg.msg_name = from;
71 	inmsg.msg_namelen = fromlen ? *fromlen : 0;
72 	inmsg.msg_iov = &iov;
73 	inmsg.msg_iovlen = 1;
74 	inmsg.msg_control = incmsg;
75 	inmsg.msg_controllen = sizeof(incmsg);
76 
77 	error = recvmsg(s, &inmsg, msg_flags ? *msg_flags : 0);
78 	if (error < 0)
79 		return error;
80 
81 	if (fromlen)
82 		*fromlen = inmsg.msg_namelen;
83 	if (msg_flags)
84 		*msg_flags = inmsg.msg_flags;
85 
86 	if (!sinfo)
87 		return error;
88 
89 	for (cmsg = CMSG_FIRSTHDR(&inmsg); cmsg != NULL;
90 				 cmsg = CMSG_NXTHDR(&inmsg, cmsg)){
91 		if ((IPPROTO_SCTP == cmsg->cmsg_level) &&
92 		    (SCTP_SNDRCV == cmsg->cmsg_type))
93 			break;
94 	}
95 
96         /* Copy sinfo. */
97 	if (cmsg)
98 		memcpy(sinfo, CMSG_DATA(cmsg), sizeof(struct sctp_sndrcvinfo));
99 
100 	return (error);
101 }
102