SOCK_STREAM socket in kernel space
Mohammad Hedayati
hedayati.mo at gmail.com
Tue Dec 21 15:24:23 UTC 2010
On Tue, Dec 21, 2010 at 4:23 PM, John Baldwin <jhb at freebsd.org> wrote:
> On Tuesday, December 21, 2010 6:39:26 am Mohammad Hedayati wrote:
>> I'm about to use a char device for a kind of distributed processing,
>> so I've coded the open function as follows. The problem is that
>> soaccept returns 0 without populating the raddr. I've checked netstat,
>> everything seems to be fine, the socket is created, bound and the
>> state is LISTENING. Even the remote is connection is ESTABLISHED. But,
>> it cannot receive anything. it says that socket (sock variable) is
>> not connected.
>
> Yes, you are calling soaccept() on the wrong socket. You need to wait for a
> connection and dequeue the socket that connected and then call soaccept() on
> that new socket. Look at kern_accept() in sys/kern/uipc_syscalls.c.
>
> I wonder though if you wouldn't rather be calling soconnect instead? Do you
> really need to listen for new connections?
>
> --
> John Baldwin
>
Thanks, I have corrected it as follows. It now works fine.
int
open(struct cdev *dev, int flag, int otyp, struct thread *td)
{
uprintf("in open...\n");
int error = -1;
socktd = td;
error = socreate(AF_INET, &sock, SOCK_STREAM, IPPROTO_TCP,
td->td_proc->p_ucred, socktd);
if(error != 0)
return error;
sockaddr.sin_len = sizeof(struct sockaddr_in);
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(1234);
sockaddr.sin_addr.s_addr = INADDR_ANY;
error = sobind(sock, (struct sockaddr *)&sockaddr, socktd);
uprintf("sobind error = %d\n", error);
error = solisten(sock, 5, socktd);
uprintf("solisten error = %d\n", error);
/* Accepting the connection */
ACCEPT_LOCK();
// Block, waiting for connection ...
while (TAILQ_EMPTY(&sock->so_comp) && sock->so_error == 0)
{
// Check if the connection is already aborted?
if (sock->so_rcv.sb_state & SBS_CANTRCVMORE) {
sock->so_error = ECONNABORTED;
error = sock->so_error;
sock->so_error = 0;
ACCEPT_UNLOCK();
return(error);
}
error = msleep(&sock->so_timeo, &accept_mtx, PSOCK | PCATCH, "accept", 0);
if (error) {
ACCEPT_UNLOCK();
return(error);
}
}
rsock = TAILQ_FIRST(&sock->so_comp);
SOCK_LOCK(rsock);
soref(rsock);
TAILQ_REMOVE(&sock->so_comp, rsock, so_list);
sock->so_qlen--;
rsock->so_state |= (sock->so_state & SS_NBIO);
rsock->so_qstate &= ~SQ_COMP;
rsock->so_head = NULL;
SOCK_UNLOCK(rsock);
ACCEPT_UNLOCK();
error = soaccept(rsock, (struct sockaddr **)&raddr);
uprintf("soaccept error = %d, ip=%s\n", error, inet_ntoa(raddr->sin_addr));
uprintf("out open...\n");
return(error);
}
More information about the freebsd-net
mailing list