Re: UDP sockets bound to ANY send answers with wrong src ip address

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Friday 11 June 2004 13:31, Henrik Nordstrom wrote:
> On Fri, 11 Jun 2004, Denis Vlasenko wrote:
> > The problem is, how to _send replies_ with correct src ip?
>
> By using IP_PKTINFO in a sendmsg() call. See ip(7) for details.
>
> You can also use this in recvmsg if you prefer only one extra address
> structure type in sending/receiving messages and less complex code..
>
> Regards
> Henrik

manpage says:


SOCKET OPTIONS
IP  supports  some protocol specific socket options
that can be set with setsockopt(2) and read with
getsockopt(2). The socket option level for IP is
SOL_IP.
...
IP_PKTINFO
Pass an IP_PKTINFO ancillary message that  contains
a  pktinfo structure that supplies some information
about the incoming  packet.  This  only  works  for
datagram oriented sockets.

struct in_pktinfo
{
    unsigned int   ipi_ifindex;  /* Interface index */
    struct in_addr ipi_spec_dst; /* Routing destination a
    struct in_addr ipi_addr;     /* Header Destination ad
};

ipi_ifindex  is  the  unique index of the interface
the packet was received on.   ipi_spec_dst  is  the
destination  address of the routing table entry and
ipi_addr is the destination address in  the  packet
header.  If IP_PKTINFO is passed to sendmsg(2) then
the outgoing packet will be sent over the interface
specified   in  ipi_ifindex  with  the  destination
address set to ipi_spec_dst

i.e. it does not tell anything about using IP_PKTINFO
for sending.

I am trying to figure it out, currently I'm getting
-EINVAL in sendmsg in this code:

# define SRCADDR_SOCKOPT IP_PKTINFO
# define SRCADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
# define srcaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_spec_dst))

union control_data {
    struct cmsghdr cmsg;
    u_char data[SRCADDR_DATASIZE];
};

int socket_send4_src2(int s,const char *buf,int len,const char ip[4],uint16 port,const char ip_src[4])
{
  struct sockaddr_in sa;
  struct iovec iov[1];
  union control_data cmsg;
  struct msghdr msg;
  struct cmsghdr* cmsgptr;
  int r;

  byte_zero(&sa,sizeof sa);
  sa.sin_family = AF_INET;
  uint16_pack_big((char *) &sa.sin_port,port);
  byte_copy((char *) &sa.sin_addr,4,ip);

  iov[0].iov_base = buf;
  iov[0].iov_len = len;

  memset(&msg, 0, sizeof msg);
  msg.msg_name = &sa;
  msg.msg_namelen = sizeof sa;
  msg.msg_iov = iov;
  msg.msg_iovlen = 1;
  msg.msg_control = &cmsg;
  msg.msg_controllen = sizeof cmsg;

  cmsgptr = CMSG_FIRSTHDR(&msg);
  byte_zero(&cmsg,sizeof cmsg);
  cmsgptr->cmsg_len = SRCADDR_DATASIZE;         /* data byte count, including hdr */
  cmsgptr->cmsg_level = IPPROTO_IP;             /* originating protocol */
  cmsgptr->cmsg_type = SRCADDR_SOCKOPT;         /* protocol-specific type */
  byte_copy((char *) srcaddr(cmsgptr),4,ip);    /* followed by u_char cmsg_data[]; */

  { // FIXME: needs to be done only once...
    int sockopt;
    sockopt = 1;
    if (setsockopt(s, IPPROTO_IP, SRCADDR_SOCKOPT, &sockopt, sizeof sockopt) == -1) {
      perror("setsockopt problem");
      return -1;
    }
  }

  r = sendmsg(s, &msg, 0);
  if(r)
    perror("sendmsg problem");
  return r;
}
--
vda
-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux