1*9b7a920aSLexi Winter /* 2*9b7a920aSLexi Winter * Copyright (c) 2000 3*9b7a920aSLexi Winter * The Regents of the University of California. All rights reserved. 4*9b7a920aSLexi Winter * 5*9b7a920aSLexi Winter * Redistribution and use in source and binary forms, with or without 6*9b7a920aSLexi Winter * modification, are permitted provided that the following conditions 7*9b7a920aSLexi Winter * are met: 8*9b7a920aSLexi Winter * 1. Redistributions of source code must retain the above copyright 9*9b7a920aSLexi Winter * notice, this list of conditions and the following disclaimer. 10*9b7a920aSLexi Winter * 2. Redistributions in binary form must reproduce the above copyright 11*9b7a920aSLexi Winter * notice, this list of conditions and the following disclaimer in the 12*9b7a920aSLexi Winter * documentation and/or other materials provided with the distribution. 13*9b7a920aSLexi Winter * 3. All advertising materials mentioning features or use of this software 14*9b7a920aSLexi Winter * must display the following acknowledgement: 15*9b7a920aSLexi Winter * This product includes software developed by the Computer Systems 16*9b7a920aSLexi Winter * Engineering Group at Lawrence Berkeley Laboratory. 17*9b7a920aSLexi Winter * 4. Neither the name of the University nor of the Laboratory may be used 18*9b7a920aSLexi Winter * to endorse or promote products derived from this software without 19*9b7a920aSLexi Winter * specific prior written permission. 20*9b7a920aSLexi Winter * 21*9b7a920aSLexi Winter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22*9b7a920aSLexi Winter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23*9b7a920aSLexi Winter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24*9b7a920aSLexi Winter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25*9b7a920aSLexi Winter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26*9b7a920aSLexi Winter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27*9b7a920aSLexi Winter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28*9b7a920aSLexi Winter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29*9b7a920aSLexi Winter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30*9b7a920aSLexi Winter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*9b7a920aSLexi Winter * SUCH DAMAGE. 32*9b7a920aSLexi Winter */ 33*9b7a920aSLexi Winter 34*9b7a920aSLexi Winter /* XXX Yes this is WAY too complicated */ 35*9b7a920aSLexi Winter 36*9b7a920aSLexi Winter #ifndef lint 37*9b7a920aSLexi Winter static const char rcsid[] = 38*9b7a920aSLexi Winter "@(#) $Id: findsaddr-socket.c,v 1.1 2000/11/23 20:17:12 leres Exp $ (LBL)"; 39*9b7a920aSLexi Winter #endif 40*9b7a920aSLexi Winter 41*9b7a920aSLexi Winter #include <sys/param.h> 42*9b7a920aSLexi Winter #include <sys/file.h> 43*9b7a920aSLexi Winter #include <sys/ioctl.h> 44*9b7a920aSLexi Winter #include <sys/socket.h> 45*9b7a920aSLexi Winter #ifdef HAVE_SYS_SOCKIO_H 46*9b7a920aSLexi Winter #include <sys/sockio.h> 47*9b7a920aSLexi Winter #endif 48*9b7a920aSLexi Winter #include <sys/time.h> /* concession to AIX */ 49*9b7a920aSLexi Winter 50*9b7a920aSLexi Winter #if __STDC__ 51*9b7a920aSLexi Winter struct mbuf; 52*9b7a920aSLexi Winter struct rtentry; 53*9b7a920aSLexi Winter #endif 54*9b7a920aSLexi Winter 55*9b7a920aSLexi Winter #include <net/if.h> 56*9b7a920aSLexi Winter #include <net/if_dl.h> 57*9b7a920aSLexi Winter #include <net/route.h> 58*9b7a920aSLexi Winter #include <netinet/in.h> 59*9b7a920aSLexi Winter 60*9b7a920aSLexi Winter #include <errno.h> 61*9b7a920aSLexi Winter #include <stdio.h> 62*9b7a920aSLexi Winter #include <stdlib.h> 63*9b7a920aSLexi Winter #include <string.h> 64*9b7a920aSLexi Winter #include <unistd.h> 65*9b7a920aSLexi Winter 66*9b7a920aSLexi Winter #include "gnuc.h" 67*9b7a920aSLexi Winter #ifdef HAVE_OS_PROTO_H 68*9b7a920aSLexi Winter #include "os-proto.h" 69*9b7a920aSLexi Winter #endif 70*9b7a920aSLexi Winter 71*9b7a920aSLexi Winter #include "findsaddr.h" 72*9b7a920aSLexi Winter 73*9b7a920aSLexi Winter #ifdef HAVE_SOCKADDR_SA_LEN 74*9b7a920aSLexi Winter #define SALEN(sa) ((sa)->sa_len) 75*9b7a920aSLexi Winter #else 76*9b7a920aSLexi Winter #define SALEN(sa) salen(sa) 77*9b7a920aSLexi Winter #endif 78*9b7a920aSLexi Winter 79*9b7a920aSLexi Winter #ifndef roundup 80*9b7a920aSLexi Winter #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ 81*9b7a920aSLexi Winter #endif 82*9b7a920aSLexi Winter 83*9b7a920aSLexi Winter struct rtmsg { 84*9b7a920aSLexi Winter struct rt_msghdr rtmsg; 85*9b7a920aSLexi Winter u_char data[512]; 86*9b7a920aSLexi Winter }; 87*9b7a920aSLexi Winter 88*9b7a920aSLexi Winter static struct rtmsg rtmsg = { 89*9b7a920aSLexi Winter { 0, RTM_VERSION, RTM_GET, 0, 90*9b7a920aSLexi Winter RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_STATIC, 91*9b7a920aSLexi Winter RTA_DST | RTA_IFA, 0, 0, 0, 0, 0, { 0 } }, 92*9b7a920aSLexi Winter { 0 } 93*9b7a920aSLexi Winter }; 94*9b7a920aSLexi Winter 95*9b7a920aSLexi Winter #ifndef HAVE_SOCKADDR_SA_LEN 96*9b7a920aSLexi Winter static int salen(struct sockaddr *); 97*9b7a920aSLexi Winter #endif 98*9b7a920aSLexi Winter 99*9b7a920aSLexi Winter /* 100*9b7a920aSLexi Winter * Return the source address for the given destination address 101*9b7a920aSLexi Winter */ 102*9b7a920aSLexi Winter const char * 103*9b7a920aSLexi Winter findsaddr(register const struct sockaddr_in *to, 104*9b7a920aSLexi Winter register struct sockaddr_in *from) 105*9b7a920aSLexi Winter { 106*9b7a920aSLexi Winter register struct rt_msghdr *rp; 107*9b7a920aSLexi Winter register u_char *cp; 108*9b7a920aSLexi Winter 109*9b7a920aSLexi Winter register struct sockaddr_in *sp, *ifa; 110*9b7a920aSLexi Winter register struct sockaddr *sa; 111*9b7a920aSLexi Winter register int s, size, cc, seq, i; 112*9b7a920aSLexi Winter register pid_t pid; 113*9b7a920aSLexi Winter static char errbuf[512]; 114*9b7a920aSLexi Winter 115*9b7a920aSLexi Winter s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); 116*9b7a920aSLexi Winter if (s < 0) { 117*9b7a920aSLexi Winter sprintf(errbuf, "socket: %.128s", strerror(errno)); 118*9b7a920aSLexi Winter return (errbuf); 119*9b7a920aSLexi Winter } 120*9b7a920aSLexi Winter 121*9b7a920aSLexi Winter seq = 0; 122*9b7a920aSLexi Winter pid = getpid(); 123*9b7a920aSLexi Winter 124*9b7a920aSLexi Winter rp = &rtmsg.rtmsg; 125*9b7a920aSLexi Winter rp->rtm_seq = ++seq; 126*9b7a920aSLexi Winter cp = (u_char *)(rp + 1); 127*9b7a920aSLexi Winter 128*9b7a920aSLexi Winter sp = (struct sockaddr_in *)cp; 129*9b7a920aSLexi Winter *sp = *to; 130*9b7a920aSLexi Winter cp += roundup(SALEN((struct sockaddr *)sp), sizeof(u_int32_t)); 131*9b7a920aSLexi Winter 132*9b7a920aSLexi Winter size = cp - (u_char *)rp; 133*9b7a920aSLexi Winter rp->rtm_msglen = size; 134*9b7a920aSLexi Winter 135*9b7a920aSLexi Winter cc = write(s, (char *)rp, size); 136*9b7a920aSLexi Winter if (cc < 0) { 137*9b7a920aSLexi Winter sprintf(errbuf, "write: %.128s", strerror(errno)); 138*9b7a920aSLexi Winter close(s); 139*9b7a920aSLexi Winter return (errbuf); 140*9b7a920aSLexi Winter } 141*9b7a920aSLexi Winter if (cc != size) { 142*9b7a920aSLexi Winter sprintf(errbuf, "short write (%d != %d)", cc, size); 143*9b7a920aSLexi Winter close(s); 144*9b7a920aSLexi Winter return (errbuf); 145*9b7a920aSLexi Winter } 146*9b7a920aSLexi Winter 147*9b7a920aSLexi Winter size = sizeof(rtmsg); 148*9b7a920aSLexi Winter do { 149*9b7a920aSLexi Winter memset(rp, 0, size); 150*9b7a920aSLexi Winter cc = read(s, (char *)rp, size); 151*9b7a920aSLexi Winter if (cc < 0) { 152*9b7a920aSLexi Winter sprintf(errbuf, "read: %.128s", strerror(errno)); 153*9b7a920aSLexi Winter close(s); 154*9b7a920aSLexi Winter return (errbuf); 155*9b7a920aSLexi Winter } 156*9b7a920aSLexi Winter 157*9b7a920aSLexi Winter } while (rp->rtm_type != RTM_GET || rp->rtm_seq != seq || 158*9b7a920aSLexi Winter rp->rtm_pid != pid); 159*9b7a920aSLexi Winter close(s); 160*9b7a920aSLexi Winter 161*9b7a920aSLexi Winter 162*9b7a920aSLexi Winter if (rp->rtm_version != RTM_VERSION) { 163*9b7a920aSLexi Winter sprintf(errbuf, "bad version %d", rp->rtm_version); 164*9b7a920aSLexi Winter return (errbuf); 165*9b7a920aSLexi Winter } 166*9b7a920aSLexi Winter if (rp->rtm_msglen > cc) { 167*9b7a920aSLexi Winter sprintf(errbuf, "bad msglen %d > %d", rp->rtm_msglen, cc); 168*9b7a920aSLexi Winter return (errbuf); 169*9b7a920aSLexi Winter } 170*9b7a920aSLexi Winter if (rp->rtm_errno != 0) { 171*9b7a920aSLexi Winter sprintf(errbuf, "rtm_errno: %.128s", strerror(rp->rtm_errno)); 172*9b7a920aSLexi Winter return (errbuf); 173*9b7a920aSLexi Winter } 174*9b7a920aSLexi Winter 175*9b7a920aSLexi Winter /* Find the interface sockaddr */ 176*9b7a920aSLexi Winter cp = (u_char *)(rp + 1); 177*9b7a920aSLexi Winter for (i = 1; i != 0; i <<= 1) 178*9b7a920aSLexi Winter if ((i & rp->rtm_addrs) != 0) { 179*9b7a920aSLexi Winter sa = (struct sockaddr *)cp; 180*9b7a920aSLexi Winter switch (i) { 181*9b7a920aSLexi Winter 182*9b7a920aSLexi Winter case RTA_IFA: 183*9b7a920aSLexi Winter if (sa->sa_family == AF_INET) { 184*9b7a920aSLexi Winter ifa = (struct sockaddr_in *)cp; 185*9b7a920aSLexi Winter if (ifa->sin_addr.s_addr != 0) { 186*9b7a920aSLexi Winter *from = *ifa; 187*9b7a920aSLexi Winter return (NULL); 188*9b7a920aSLexi Winter } 189*9b7a920aSLexi Winter } 190*9b7a920aSLexi Winter break; 191*9b7a920aSLexi Winter 192*9b7a920aSLexi Winter } 193*9b7a920aSLexi Winter 194*9b7a920aSLexi Winter if (SALEN(sa) == 0) 195*9b7a920aSLexi Winter cp += sizeof(long); 196*9b7a920aSLexi Winter else 197*9b7a920aSLexi Winter cp += roundup(SALEN(sa), sizeof(long)); 198*9b7a920aSLexi Winter } 199*9b7a920aSLexi Winter 200*9b7a920aSLexi Winter return ("failed!"); 201*9b7a920aSLexi Winter } 202*9b7a920aSLexi Winter 203*9b7a920aSLexi Winter #ifndef HAVE_SOCKADDR_SA_LEN 204*9b7a920aSLexi Winter static int 205*9b7a920aSLexi Winter salen(struct sockaddr *sa) 206*9b7a920aSLexi Winter { 207*9b7a920aSLexi Winter switch (sa->sa_family) { 208*9b7a920aSLexi Winter 209*9b7a920aSLexi Winter case AF_INET: 210*9b7a920aSLexi Winter return (sizeof(struct sockaddr_in)); 211*9b7a920aSLexi Winter 212*9b7a920aSLexi Winter case AF_LINK: 213*9b7a920aSLexi Winter return (sizeof(struct sockaddr_dl)); 214*9b7a920aSLexi Winter 215*9b7a920aSLexi Winter default: 216*9b7a920aSLexi Winter return (sizeof(struct sockaddr)); 217*9b7a920aSLexi Winter } 218*9b7a920aSLexi Winter } 219*9b7a920aSLexi Winter #endif 220