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