From df4e01a579663cd726eb2b3c2d5d8800cf2c3f0c Mon Sep 17 00:00:00 2001 From: "fredrik@DOLDA2000.COM" Date: Fri, 29 Apr 2005 17:47:24 +0000 Subject: [PATCH] Fill in the source address properly. git-svn-id: svn+ssh://svn.dolda2000.com/srv/svn/repos/src/icmp-dn@229 959494ce-11ee-0310-bf91-de5d638817bd --- icmpdnd.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/icmpdnd.c b/icmpdnd.c index dd99326..1dfb028 100644 --- a/icmpdnd.c +++ b/icmpdnd.c @@ -132,13 +132,16 @@ void cksum(void *hdr, size_t len) int main(int argc, char **argv) { int i, n, ret; - int c, cs, s4, s6, namelen, datalen; + int c, cs, s4, s6, datalen; int daemonize, ttl; unsigned char buf[65536]; struct sockaddr_storage name; struct reqhdr req; struct rephdr rep; struct iphdr iphdr; + struct msghdr mhdr; + struct iovec iov; + char cmsgbuf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; size_t hdrlen; struct pollfd pfd[2]; time_t curtime, lasterr; @@ -168,6 +171,13 @@ int main(int argc, char **argv) perror("could not open raw socket"); exit(1); } + if(s6 >= 0) { + i = 1; + if(setsockopt(s6, IPPROTO_IPV6, IPV6_PKTINFO, &i, sizeof(i))) { + perror("could not set IPV6_PKTINFO sockopt"); + exit(1); + } + } if(daemonize) daemon(0, 0); @@ -206,9 +216,18 @@ int main(int argc, char **argv) if((pfd[i].revents & POLLIN) == 0) continue; cs = pfd[i].fd; - namelen = sizeof(name); memset(&name, 0, sizeof(name)); - ret = recvfrom(cs, buf, sizeof(buf), 0, (struct sockaddr *)&name, &namelen); + + iov.iov_len = sizeof(buf); + iov.iov_base = buf; + mhdr.msg_name = &name; + mhdr.msg_namelen = sizeof(name); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = cmsgbuf; + mhdr.msg_controllen = sizeof(cmsgbuf); + + ret = recvmsg(cs, &mhdr, 0); if(ret < 0) { syslog(LOG_WARNING, "error while receiving datagram: %m"); continue; @@ -221,11 +240,14 @@ int main(int argc, char **argv) memcpy(&iphdr, buf, sizeof(iphdr)); if(iphdr.protocol != IPPROTO_ICMP) continue; + mhdr.msg_control = NULL; + mhdr.msg_controllen = 0; } else if(cs == s6) { if(ret < sizeof(req)) continue; ((struct sockaddr_in6 *)&name)->sin6_port = 0; hdrlen = 0; + /* Just keep mhdr.msg_control. */ } else { syslog(LOG_CRIT, "strangeness!"); abort(); @@ -242,10 +264,12 @@ int main(int argc, char **argv) datalen = filldn(buf + sizeof(rep)); cksum(buf, datalen + sizeof(rep)); - - /* XXX: The correct source address needs to be filled in from - * the request's destination address. */ - ret = sendto(cs, buf, datalen + sizeof(rep), 0, (struct sockaddr *)&name, namelen); + + iov.iov_len = sizeof(rep) + datalen; + iov.iov_base = buf; + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + ret = sendmsg(cs, &mhdr, 0); if(ret < 0) syslog(LOG_WARNING, "error in sending reply: %m"); } -- 2.11.0