docs/76399: [PATCH] sendto(2) is missing possible error EISCONN

Rudolf Cejka cejkar at fit.vutbr.cz
Wed Jan 19 07:50:04 PST 2005


Hello to freebsd-net,
  please, do you have some net-points to our discussion? It groved from
docs-only problem ( http://www.freebsd.org/cgi/query-pr.cgi?pr=76399 )
to net-related questions too.

Thanks.

Giorgos Keramidas wrote (2005/01/19):
> On 2005-01-19 14:20, Rudolf Cejka <cejkar at fit.vutbr.cz> wrote:
> >Giorgos Keramidas wrote (2005/01/19):
> >> Ah, I see now.  We need to expand the description of sendto() a bit.
> >
> > I think that very good source would be
> > http://www.opengroup.org/onlinepubs/009695399/functions/sendto.html
> > if we have really permission to use it ;o)
> 
> I think we do have their permission.  I will ask around at freebsd-doc
> to see if anyone remembers more clearly than me.
> 
> > > SOCK_DGRAM sockets are a bit different.  The handling of sendto() for
> > > already connected UDP sockets is different than TCP.
> >
> > Hmm, it really seems that SOCK_DGRAM and SOCK_STREAM are handled in
> > the different way and maybe it would not be a bad idea to change the
> > behaviour of FreeBSD to just one unified way, like SUSv3 looks like:
> >
> > - If the socket is connection-mode, dest_addr shall be ignored.
> > - [EISCONN] A destination address was specified and the socket is
> >   already connected. This error may or may not be returned for
> >   connection mode sockets.
> 
> I'm not sure.  You may have to bring this up to freebsd-net and ask if
> there is something that will break by the change in behavior.  As far
> as I can tell, by reading the sys/netinet/udp_usrreq.c source, the
> steps taken when udp_send() is called are:
> 
>   - If the socket has an attached inpcb it is passed to udp_output().
> 
>     All UDP sockets have an inpcb attached to them, since they have
>     gone through udp_attach() at socket creation time.
> 
>   - In udp_output(), the part that makes sure packets cannot be sent
>     with a non-NULL destination address, after a socket has gone
>     through a connect() is:
> 
>     791         if (addr) {
>     792                 sin = (struct sockaddr_in *)addr;
>     793                 if (td && jailed(td->td_ucred))
>     794                         prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
>     795                 if (inp->inp_faddr.s_addr != INADDR_ANY) {
>     796                         error = EISCONN;
>     797                         goto release;
>     798                 }
>     ...
> 
> Lines 795-798 are the ones that enforce this.
> 
> The TCP protocol does a similar check, but a bit earlier, since it
> doesn't need to allow sending to multiple addresses for sockets that
> are not connected (there aren't such TCP sockets anyway):
> 
>     117 static int
>     118 tcp_usr_attach(struct socket *so, int proto, struct thread *td)
>     119 {
>     120         int error;
>     121         struct inpcb *inp;
>     122         struct tcpcb *tp = 0;
>     123         TCPDEBUG0;
>     124
>     125         INP_INFO_WLOCK(&tcbinfo);
>     126         TCPDEBUG1();
>     127         inp = sotoinpcb(so);
>     128         if (inp) {
>     129                 error = EISCONN;
>     130                 goto out;
>     131         }
> 
> This is a bit early.  I haven't checked the tcp_output.c source to see
> what happens later on.  I honestly have to admit that tcp_output()
> still scares the hell out of me :-)
> 
> >> to any number of addresses.  After connect() is used to bind the
> >> socket to a particular destination address it's not valid to
> >> sendto() packets to any random address any more.
> >
> > Yes, target address has to be ignored from sendto() and the problem
> > is that OS may or may not return an error.
> 
> For connected SOCK_STREAM sockets no error is returned AFAICT.
> The packet is just dropped.

I tried it and it seems to me that TCP packet is sent to connected
address, so TCP is SUSv3 compliant too, but just in the other way
from UDP case, which I think is not very systematic.

> Unconnected SOCK_STREAM sockets cannot send packets anyway (ENOTCONN).
> 
> SOCK_DGRAM sockets need special documentation of their behavior :-)

-- 
Rudolf Cejka <cejkar at fit.vutbr.cz> http://www.fit.vutbr.cz/~cejkar
Brno University of Technology, Faculty of Information Technology
Bozetechova 2, 612 66  Brno, Czech Republic


More information about the freebsd-net mailing list