Subject: kern/7004: sendto() on connected socket fails
To: None <gnats-bugs@gnats.netbsd.org>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: netbsd-bugs
Date: 02/14/1999 20:40:41
>Number: 7004
>Category: kern
>Synopsis: sendto() on connected socket fails
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sun Feb 14 20:50:01 1999
>Last-Modified:
>Originator: Jonathan Stone
>Organization:
>Release: NetBSD-current as at 1999-02-14; probably also 1.3.x
>Environment:
System: NetBSD Cuisinart.Stanford.EDU 1.3I NetBSD 1.3I (TEST-OLD-AS) #2: Sun Feb 14 16:39:20 PST 1999 jonathan@Cuisinart.Stanford.EDU:/cuisinart/compile/TEST-OLD-AS pmax
>Description:
From the manual page for sendto(2):
DESCRIPTION
send(), sendto(), and sendmsg() are used to transmit a message to another
socket. send() may be used only when the socket is in a connected state,
while sendto() and sendmsg() may be used at any time.
howver, in NetBSD 1.3I, calling sendto() (and presumably sendmsg) on a
connected socket fails.
>How-To-Repeat:
The appended trivial program demonstrates the bug.
>Fix:
I dunno.
(i) Back out the fragment
if ((so->so_state & SS_ISCONNECTED) != 0) {
error = EISCONN;
goto die;
}
in sys/netinet/udp_usrreq, rev 1.32, in udp_usrreq()'s handler for
case PRU_SEND?
(ii) Just go back to the old behaviour from 4.3BSD, 4.4-Lite, FreeBSD,
for sendmsg() and sendto()? ie., dont fake up a connect(), and then
undo it, for a PRU_SEND with an explicit non-null destination address?
------ begin sample program
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PKTLEN 1024
const int mcast_ntp_addr = 0xe0000101; /* 224.0.1.1 */
int verbose = 0;
int
main()
{
int s;
struct sockaddr_in sin, sin2;
char pkt [PKTLEN];
struct udp *pkthdr;
int i, result;
for (i = 0; i < PKTLEN; i++)
pkt[i] = i % 256;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket()");
exit(-1);
}
/* build address for our sends */
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(mcast_ntp_addr);
sin.sin_port = htons(4004); /* XXX */
#ifdef BSD /* XXX when exactly did sin_len appear? */
sin.sin_len = sizeof(struct sockaddr_in);
#endif
/* Create a second, distinct sockaddr_in for connect() */
sin2 = sin;
sin2.sin_port = htons(8008);
/* do a sendto() on the unconnected socket */
if (verbose)
printf ("first sendto...\n");
result = sendto(s, &pkt, PKTLEN, 0, (struct sockaddr *)&sin,
sizeof(struct sockaddr_in));
if (result < 0)
perror("first sendto");
/* Do connect() in preparation for sendto() on a connected socket. */
if (verbose)
printf ("connect()ing socket...\n");
if (connect(s, (struct sockaddr *)&sin2, sizeof(sin2)) == -1) {
perror("connect");
exit(-1);
}
/* Do sendto() on a connected socket. Supposed to work. */
if (verbose)
printf ("second sendto..\n");
result = sendto(s, &pkt, PKTLEN, 0, (struct sockaddr *)&sin,
sizeof(struct sockaddr_in));
if (result < 0) {
perror("second sendto");
exit(errno);
}
exit(0);
}
------ end sample program
>Audit-Trail:
>Unformatted: