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 [EMAIL PROTECTED]
> 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 _ __ ___ ____ ___ ___ ___
[EMAIL PROTECTED] _ __ ___ | _ ) __| \
FreeBSD: The Power to Serve! _ __ | _ \._ \ |) |
http://www.FreeBSD.org/ _ |___/___/___/
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message