Date: Thu, 19 Feb 2004 16:06:03 -0800 (PST) From: Naveen Kumar <g_naveen_k@yahoo.com> To: Vincent Jardin <vjardin@free.fr>, Andreas T <andreto@olsr.org>, freebsd-net@freebsd.org Subject: Re: Binding sockets to devices in FreeBSD Message-ID: <20040220000603.29033.qmail@web13606.mail.yahoo.com> In-Reply-To: <200402200028.04226.vjardin@free.fr>
next in thread | previous in thread | raw e-mail | index | archive | help
Well it doesn't look like it would work for IPV4. If you look at the following code there is no place to specify the interface index at packet level in send as in IPV6. If the broadcast addresses on the different interfaces were different then there is no problem the sendto would work but if broadcast addresses are the same then it wouldn't int rip_send_packet (caddr_t buf, int size, struct sockaddr_in *to, struct interface *ifp, struct connected *connected) { int ret, send_sock; struct sockaddr_in sin; if (IS_RIP_DEBUG_PACKET) { char dst[20]; if (to) { strcpy(dst, inet_ntoa(to->sin_addr)); } else { sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); strcpy(dst, inet_ntoa(sin.sin_addr)); } zlog_info("rip_send_packet %s > %s (%s)", inet_ntoa(connected->address->u.prefix4), dst, ifp->name); } if (connected->flags & ZEBRA_IFA_SECONDARY) { /* * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured * with multiple addresses on the same subnet: the first address * on the subnet is configured "primary", and all subsequent addresses * on that subnet are treated as "secondary" addresses. * In order to avoid routing-table bloat on other rip listeners, * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs. * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY * flag is set, we would end up sending a packet for a "secondary" * source address on non-linux systems. */ if (IS_RIP_DEBUG_PACKET) zlog_info("duplicate dropped"); return 0; } /* Make destination address. */ memset (&sin, 0, sizeof (struct sockaddr_in)); sin.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ /* When destination is specified, use it's port and address. */ if (to) { sin.sin_port = to->sin_port; sin.sin_addr = to->sin_addr; send_sock = rip->sock; } else { sin.sin_port = htons (RIP_PORT_DEFAULT); sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP); /* * we have to open a new socket for each packet because this * is the most portable way to bind to a different source * ipv4 address for each packet. */ send_sock = socket(AF_INET, SOCK_DGRAM, 0); if (send_sock < 0) { zlog_warn("rip_send_packet could not create socket %s", strerror(errno)); return -1; } sockopt_broadcast (send_sock); sockopt_reuseaddr (send_sock); sockopt_reuseport (send_sock); #ifdef RIP_RECVMSG setsockopt_pktinfo (send_sock); #endif /* RIP_RECVMSG */ rip_interface_multicast_set(send_sock, connected, if_is_pointopoint(ifp)); } ret = sendto (send_sock, buf, size, 0, (struct sockaddr *)&sin, sizeof (struct sockaddr_in)); --- Vincent Jardin <vjardin@free.fr> wrote: > 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 > _______________________________________________ > freebsd-net@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-net > To unsubscribe, send any mail to "freebsd-net-unsubscribe@freebsd.org" __________________________________ Do you Yahoo!? Yahoo! Mail SpamGuard - Read only the mail you want. http://antispam.yahoo.com/tools
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040220000603.29033.qmail>