On 26/04/17(Wed) 12:29, Markert, Alexander wrote:
> Hi,
> 
> actually you are right that this issue is related to control messages and not 
> to the send buffer length. But the length of the control message is checked 
> in combination with the data to be sent in uip_socket.c:
> 
> Let's assume we are sending data with the maximum send buffer size (e.g. 
> 1024).
> Since clen is NOT evaluated in the first if statement, EMSGSIZE is NOT 
> returned.
> But the second if statement becomes true, since clen is considered here. 
> Hence either EWOULDBLOCK (snderr) is returned or sbwait() is called.
> 
>               if ((atomic && resid > so->so_snd.sb_hiwat) ||
>                   (so->so_proto->pr_domain->dom_family != AF_LOCAL &&
>                   clen > so->so_snd.sb_hiwat))
>                       snderr(EMSGSIZE);
>               if (space < clen ||
>                   (space - clen < resid &&
>                   (atomic || space < so->so_snd.sb_lowat))) {
>                       if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT))
>                               snderr(EWOULDBLOCK);
>                       sbunlock(&so->so_snd);
>                       error = sbwait(&so->so_snd);
> 
> I attached a small example, which
> - sets the sockets maximum buffer length
> - enables/disables non-blocking IO and
> - calls sendmsg with the maximum buffer size including a control message 
> (IP_SENDSRCADDR).

I KNF'ed & converted the test case to our framework.  I didn't include
it in the existing regress/sys/netinet/sendscraddr test because I don't
grok it.

Alexander I used our standard license template for your test, is it ok?

Vincent, Jeremie could you look at this?

Index: ip_sendsrcaddr/Makefile
===================================================================
RCS file: ip_sendsrcaddr/Makefile
diff -N ip_sendsrcaddr/Makefile
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ ip_sendsrcaddr/Makefile     8 May 2017 13:41:33 -0000
@@ -0,0 +1,5 @@
+#      $OpenBSD: Makefile,v 1.1 2017/04/30 09:03:58 mpi Exp $
+
+PROG=  ip_sendsrcaddr
+
+.include <bsd.regress.mk>
Index: ip_sendsrcaddr/ip_sendsrcaddr.c
===================================================================
RCS file: ip_sendsrcaddr/ip_sendsrcaddr.c
diff -N ip_sendsrcaddr/ip_sendsrcaddr.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ ip_sendsrcaddr/ip_sendsrcaddr.c     8 May 2017 13:39:54 -0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017 Alexander Markert <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CFG_SOURCE_ADDRESS             "192.168.88.135"
+#define CFG_DESTINATION_ADDRESS                "192.168.57.44"
+#define CFG_PORT                       5000
+#define CFG_SO_MAX_SEND_BUFFER         1024
+
+int blocking = 0;
+
+int main(int argc, char* argv[])
+{
+       char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];;
+       struct sockaddr_in to;
+       char data[CFG_SO_MAX_SEND_BUFFER] = {0};
+       unsigned int size = CFG_SO_MAX_SEND_BUFFER;
+       struct in_addr *source_address;
+       struct msghdr msg;
+       struct cmsghdr *cmsg;
+       struct iovec iov;
+       int so, bytes;
+
+       so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (so < 0)
+               err(-1, "opening socket failed");
+
+       if (setsockopt(so, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
+               err(-1, "adjusting socket send buffer failed");
+
+       if (!blocking) {
+               unsigned long on = 1;
+
+               if (ioctl(so, FIONBIO, &on) < 0)
+                       err(-1, "enabling non-blocking IO failed");
+       }
+
+       /* setup remote address */
+       memset(&to, 0, sizeof(to));
+       to.sin_family = AF_INET;
+       to.sin_addr.s_addr = inet_addr(CFG_DESTINATION_ADDRESS);
+       to.sin_port = htons(CFG_PORT);
+
+       /* setup buffer to be sent */
+       msg.msg_name = &to;
+       msg.msg_namelen = sizeof(to);
+       iov.iov_base = data;
+       iov.iov_len = sizeof(data);
+       msg.msg_iovlen = 1;
+       msg.msg_iov = &iov;
+
+       /* setup configuration for source address */
+       memset(cmsgbuf, 0, sizeof(cmsgbuf));
+       msg.msg_control = cmsgbuf;
+       msg.msg_controllen = sizeof(cmsgbuf);
+       cmsg = CMSG_FIRSTHDR(&msg);
+       cmsg->cmsg_level = IPPROTO_IP;
+       cmsg->cmsg_type = IP_SENDSRCADDR;
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+       source_address = (struct in_addr *)(CMSG_DATA(cmsg));
+       source_address->s_addr = inet_addr(CFG_SOURCE_ADDRESS);
+
+       if ((bytes = sendmsg(so, &msg, 0)) < 0) {
+               if (!blocking)
+                       if (errno != EMSGSIZE)
+                               err(-1, "incorrect errno");
+               else
+                       err(-1, "sendmsg failed");
+       } else {
+               printf("%d bytes sent\n", bytes);
+       }
+
+       close(so);
+       return 0;
+}

Reply via email to