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