On Wed, 23 Jun 1999, Dan Seguin wrote:

> 
> 
> Hi All.
> 
> I'm trying to create a system call that will burst a (pseudo) quick tcp
> message out to a remote host every time that it is called. I've got the
> system call all worked out as a kld, it loads and restores without a
> hitch.

Good, you're mostly there then!

> 
> I use the calling proc's table as it is passed to the system call, and am
> trying to call socket and connect as if the user process originally called
> them one by one (from userland syscall 97 and 98). I seem to be getting
> the correct behaviour from socket, but the connect call fails. After
> DDB'ing and breaking on the call to connect, it appears to fail at copyin
> with an EFAULT (invalid address). Call stack: copyin from getsockaddr from
> connect. What am I missing here, and/or what incorrect assumptions have I
> made? I'm including the actual system call function below.

copyin() is done to get the sockaddr from the connect call. A copyin() is a 
user-space
to kernel-space memory copy, so you have a problem in your code (I'll point out 
where
below).

> 
> Thanks!
> 
> Dan
> 
> P.S. I test the system call from userland with a small C prog that uses
> syscall().
> 
> -------- CODE starts ----------------
> 
> static int init_comms(p, uap)
> struct proc *p;
> register struct nosys_args *uap;
> {
>   int sockfd1, stat; 
>   struct socket_args socket_uap;
>   struct connect_args connect_uap;
>   static struct sockaddr_in servaddr;

This needs to be a valid structure in USER space, not kernel.

>  
>   socket_uap.domain = PF_LOCAL;
>   socket_uap.type = SOCK_STREAM;
>   socket_uap.protocol = 0; 
> 
>   stat = socket(p, &socket_uap);
if (stat)
        return stat;
>      
>   sockfd1 = p->p_retval[0];
>      
>   bzero(&servaddr, sizeof(servaddr));
>   
>   servaddr.sin_family = AF_LOCAL;
>   servaddr.sin_port   = htons(13);
>   servaddr.sin_len    = sizeof servaddr;
>   
> 
>  if ( inet_aton((char *) "127.0.0.1", &servaddr.sin_addr) <= 0 )
This is a bogus cast. const char * to char *?
>     printf("\ninet_aton failed.\n");
So return EINVAL.
>   
>    
>   printf("\nservaddr: %x\n", servaddr.sin_addr.s_addr);
AHEM! Why??
>   
>   /* Prints 100007e */

Try using servaddr.sin_addr.saddr = 0;

>   
>   connect_uap.s = sockfd1;
>   connect_uap.name = (caddr_t) &servaddr;

That's the problem. It needs to point to (say) uap->servaddr;

>   connect_uap.namelen = sizeof servaddr;
>   
>   stat = 0;
>   stat = connect(p, &connect_uap);
>   
>   printf("\nConnect Stat: %d\n", stat);
>   
Take that out.
>   /* Prints 14 (EFAULT) */
>   
>   return 0;
return stat instead. The standard is to use a variable named "error".
>  
> }
> 
> ------------------------- Code Ends -----------------------
> 
> 
> 
> To Unsubscribe: send mail to majord...@freebsd.org
> with "unsubscribe freebsd-hackers" in the body of the message
> 
Note that I haven't checked the correctness of the code other than a quick 
glance.
These errors are real, though.

 Brian Fundakowski Feldman      _ __ ___ ____  ___ ___ ___  
 gr...@freebsd.org                   _ __ ___ | _ ) __|   \ 
     FreeBSD: The Power to Serve!        _ __ | _ \._ \ |) |
       http://www.FreeBSD.org/              _ |___/___/___/ 



To Unsubscribe: send mail to majord...@freebsd.org
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to