Re: Binding sockets to devices in FreeBSD

From: Naveen Kumar (g_naveen_k_at_yahoo.com)
Date: 02/20/04

  • Next message: Andreas Tønnesen: "Re: Binding sockets to devices in FreeBSD"
    Date: Thu, 19 Feb 2004 16:06:03 -0800 (PST)
    To: Vincent Jardin <vjardin@free.fr>, Andreas T <andreto@olsr.org>, freebsd-net@freebsd.org
    
    

    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
    _______________________________________________
    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"


  • Next message: Andreas Tønnesen: "Re: Binding sockets to devices in FreeBSD"

    Relevant Pages