/*- * Copyright (c) 2002, Matt Rosenfeld * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of this program nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "TracerouteReader.h" #include #include #include #include #include #include #include class TraceroutePacket* TracerouteReader::readPacket(int fd) { char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))]; struct sockaddr_in remoteAddress; struct sockaddr_in localAddress; struct msghdr msg; unsigned int size = sizeof(remoteAddress); memset((void*)&remoteAddress, 0, size); memset((void*)&localAddress, 0, size); memset((void*)&msg, 0, sizeof(msg)); // get local address if ((getsockname(fd, (struct sockaddr*)&localAddress, &size)) < 0) { fprintf(stderr, "Error getting local name."); exit(1); } // read message msg.msg_name = &remoteAddress; msg.msg_namelen = size; msg.msg_control = &cmsg; msg.msg_controllen = sizeof(cmsg); if (recvmsg(fd, &msg, 0) < 0) { fprintf(stderr, "Error receiving datagram."); exit(1); } // get actual IP address for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cmsg); localAddress.sin_addr = pi->ipi_spec_dst; break; } } return new TraceroutePacket(inet_ntoa(remoteAddress.sin_addr), inet_ntoa(localAddress.sin_addr), ntohs(remoteAddress.sin_port), ntohs(localAddress.sin_port)); }