Binding sockets to devices in FreeBSD

Vincent Jardin vjardin at free.fr
Thu Feb 19 15:24:20 PST 2004


Hi,

You need to use sendto or sendmsg.

For example, with IPv6, Quagga is sending IPv6 multicast packet on a per 
interface basis. The interface's ifindex is provided into the pktinfo 
structure.

int
ripng_send_packet (caddr_t buf, int bufsize, struct sockaddr_in6 *to,
                   struct interface *ifp)
{
  int ret;
  struct msghdr msg;
  struct iovec iov;
  struct cmsghdr  *cmsgptr;
  char adata [256];
  struct in6_pktinfo *pkt;
  struct sockaddr_in6 addr;

  [...]

  memset (&addr, 0, sizeof (struct sockaddr_in6));
  addr.sin6_family = AF_INET6;
#ifdef SIN6_LEN
  addr.sin6_len = sizeof (struct sockaddr_in6);
#endif /* SIN6_LEN */
  addr.sin6_flowinfo = htonl (RIPNG_PRIORITY_DEFAULT);

 [...]
      inet_pton(AF_INET6, RIPNG_GROUP, &addr.sin6_addr);
      addr.sin6_port = htons (RIPNG_PORT_DEFAULT);
 [...]

  msg.msg_name = (void *) &addr;
  msg.msg_namelen = sizeof (struct sockaddr_in6);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = (void *) adata;
  msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));

  iov.iov_base = buf;
  iov.iov_len = bufsize;

  cmsgptr = (struct cmsghdr *)adata;
  cmsgptr->cmsg_len = CMSG_LEN(sizeof (struct in6_pktinfo));
  cmsgptr->cmsg_level = IPPROTO_IPV6;
  cmsgptr->cmsg_type = IPV6_PKTINFO;

  pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
  pkt->ipi6_ifindex = ifp->ifindex;

  ret = sendmsg (ripng->sock, &msg, 0);

[...]

  return ret;
}

About IPv4, see the sendto() use case of ripd/ripd.c.

Moreover these solutions, which are used by Quagga, are portable on most of 
the OSes (Linux, FreeBSD, OpenBSD, NetBSD, Solaris, ...).

Regards,
  Vincent


On Thursday 19 February 2004 10:54, Andreas T wrote:
> Hi all,
>
> I am developing an implementation of the Optimized LinkState Routing
> protocol(RFC3626) for Linux(www.olsr.org). OLSR is a routing protocol
> for mobile, multihop, wireless ad-hoc networks.
>
> I would really like to have my code compile on FreeBSD - but there is
> one major issue.
>
> OLSR sends control traffic broadcasted(IPv4) or multicasted(IPv6) on a
> pr.interface basis. That means that a node running OLSR on two
> interfaces a and b, would not always broadcast the same content in
> messages sent on a and b. This works fine using IPv4 and broadcast as
> long as the interfaces uses different broadcast addresses - but as soon
> as two interfaces is set up with the same broadcastaddress(or as soon as
> one uses IPv6 with the same multicastgroup) any message (sent on the
> broadcastsocket) will be transmitted on both interfaces.
> I hope this made some sense :)
>
> Bottom line is that one has to be able to control on which interface
> packets are sent. To do this in Linux i use the SO_BINDTODEVICE
> flag(with setsockopt(2)). That way I can have one socket for each
> interface OLSR is to use regradless of destinationaddress.
>
> In FreeBSD there is no SO_BINDTODEVICE or equalivant as far as I can
> see. To me it seems like BPF could provide the functioning I need. Is
> this so? Can BPF in some way help me control on which interface packets
> are transmitted?
> If so I would really appreciate some (pseudo or real)code examples to
> get me started or some links to such material - as I am totally new to
> the BPF interface(and the concept).
>
> If BPF is not the way to go I would appreciate any help in finding a way
> of doing this in FreeBSD.
>
> I could ofcause try to figure this out by myself - but as FreeBSD
> porting is not too high prioritized for now I figured I'd rather be lazy
> and ask you experts :)
>
>
> Thanks!
>
> regards,
> Andreas T


More information about the freebsd-net mailing list