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