From: Andre Nathan Date: 2008-08-26T04:30:18+09:00 Subject: Calling sendmsg() from Ruby Hello I'm trying to call the sendmsg() system call from ruby in a way that allocates space for the kernel to set the user credentials in the appropriate structures (this is in FreeBSD i386). I'm using the code below, which gives me an EFAULT (bad address) error, and I cannot see what I'm doing wrong here... any help would be awesome. The equivalent C code (which works) follows after the ruby attempt. def pointer(buf) [buf].pack("P").unpack("L_").first end def sendmsg(fd, buf) iov = [buf, buf.length].pack("PI_") cmsg_len = 96 # CMSG_LEN(sizeof(struct cmsgcred)) cmsg_space = 96 # CMSG_SPACE(sizeof(struct cmsgcred)) cmsg_level = 0xffff # SOL_SOCKET cmsg_type = 0x03 # SCM_CREDS cmsg_data = ["\x00" * cmsg_space].pack("P") cmsghdr = [ cmsg_len, cmsg_level, cmsg_type, cmsg_data ].pack("I_i_i_P") msg_control_ptr = pointer(cmsghdr) msg_controllen = cmsg_space msghdr = [ 0, # msg_name 0, # msg_namelen pointer(iov), # msg_iov 1, # msg_iovlen pointer(cmsghdr), # msg_control cmsg_space, # msg_controllen 0 # msg_flags ].pack("L_i_L_i_L_i_i_") syscall(28, pointer(msghdr), 0) # 28 is sendmsg() end Here's the C snippet: union { struct cmsghdr hdr; char cred[CMSG_SPACE(sizeof(struct cmsgcred))]; } cmsg; struct iovec iov[1]; struct msghdr msg; iov[0].iov_base = (void *)buf; iov[0].iov_len = count; memset(&msg, 0, sizeof(msg)); msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = (caddr_t)&cmsg; msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred)); memset(&cmsg, 0, sizeof(cmsg)); cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct cmsgcred)); cmsg.hdr.cmsg_level = SOL_SOCKET; cmsg.hdr.cmsg_type = SCM_CREDS; sendmsg(fd, &msg, 0); Thanks in advance, Andre