# Calling sendmsg() from Ruby

**URL:** <https://www.ruby-forum.com/t/calling-sendmsg-from-ruby/146820>\
**Category:** Ruby\
**Created:** [August 25, 2008, 9:34pm UTC](https://www.ruby-forum.com/t/calling-sendmsg-from-ruby/146820 "2008-08-25T21:34:57Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![reflex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f05b48/32.png) [@reflex](https://www.ruby-forum.com/u/reflex)\
**Post date:** [August 25, 2008, 9:34pm UTC](https://www.ruby-forum.com/t/calling-sendmsg-from-ruby/146820/1 "2008-08-25T21:34:57Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![reflex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f05b48/32.png) [@reflex](https://www.ruby-forum.com/u/reflex)\
**Post date:** [August 29, 2008, 2:29am UTC](https://www.ruby-forum.com/t/calling-sendmsg-from-ruby/146820/2 "2008-08-29T02:29:32Z")

</div>

On Tue, 2008-08-26 at 04:30 +0900, Andre N. wrote:

> 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).

For the record, this is how I got it to work. I was wrong in the way I  
was packing cmsg\_data, and I also had forgotten passing an argument to  
the syscall (duh).

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_len = 84

cmsghdr = ([
  cmsg_len,
  cmsg_level,
  cmsg_type
] + [0] * cmsg_data_len).pack("I_i_i_C#{cmsg_data_len}")

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, fd.fileno, pointer(msghdr), 0)

```

end
