a23a5cff7bbde9d606be89b9ae0381641aa52eb7
[overhosts.git] / overhosts.c
1 /* 
2  *  overhosts.c
3  * 
4  *  Copyright (C) 2012 
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * General Public License for more details. You should have received a
15  * copy of the GNU General Public License along with this program; if
16  * not, write to the Free Software Foundation, Inc, 59 Temple Place - 
17  * Suite 330, Boston, MA 02111-1307, USA.
18  * 
19  */
20
21 /*
22   compile like this:
23
24   gcc -c -fPIC preload_open.c
25   ld -shared -o preload_open.so preload_open.o -ldl
26   
27   export LD_PRELOAD=/etc/magic/preload_open.so 
28   myapp ARGS
29
30 */
31
32
33 #include <sys/mman.h>
34 #include <sys/types.h>
35 #include <dlfcn.h>
36 #include <fcntl.h>
37 #include <stdarg.h>
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <sys/types.h>
43 #include <signal.h>
44 #include <string.h>
45 #include <netdb.h>
46
47 #include "overhosts.h"
48
49 void  __attribute__ ((constructor)) overhosts_init(void);
50
51 struct hostent *(* ohreal_gethostbyname)(const char *name) = NULL;
52 struct hostent *(* ohreal_gethostbyname2)(const char *name, int af) = NULL;
53 int (*ohreal_getaddrinfo)(const char *node, const char *service,
54                        const struct addrinfo *hints,
55                        struct addrinfo **res) = NULL;
56 // void (* ohreal_freeaddrinfo)(struct addrinfo *res) = NULL;
57 #if 0
58 static struct hostent ohreal_he = { "bernoulli", 
59                                      (char *[]){ NULL }, 
60                                      AF_INET, 
61                                      4,
62                                      (char *[]){ "\x7f\x00\x00\x01", NULL }
63 };
64 #endif
65
66 /*
67 static struct addrinfo ohreal_ai = {
68     
69                int              ai_flags;
70                int              ai_family;
71                int              ai_socktype;
72                int              ai_protocol;
73                size_t           ai_addrlen;
74                struct sockaddr *ai_addr;
75                char            *ai_canonname;
76                struct addrinfo *ai_next;
77            };
78
79 */  
80
81 void  __attribute__ ((constructor)) overhosts_init(void)
82 {
83     ohreal_gethostbyname  = dlsym((void *)-1, "gethostbyname");
84     // printf("PREINTT\n");
85     ohreal_gethostbyname2 = dlsym((void *)-1, "gethostbyname2");
86     ohreal_getaddrinfo    = dlsym((void *)-1, "getaddrinfo");
87     // printf("INITT\n");
88 }
89
90 static int is_an_alias(const char *name);
91
92 static int is_an_alias(const char *name)
93 {
94     char *alias, *p, *e;
95     char bf[4096];
96
97     if ((alias = getenv("OVERHOSTS_ALIASES")) == NULL) {
98         // printf("fuori1 [%s]\n", name);
99         return 0;
100     }
101
102     strcpy(bf, "|");
103     strcat(bf, name);
104
105     // printf("in1 [%s][%s]\n", bf, name);
106
107     if (((p = strstr(alias, bf)) != NULL) || ((p = strstr(alias, name)) && p == alias)) {
108         e = p+strlen(name);
109         if (p > alias)
110             e++;
111         // printf("in2 [%s][%c]\n", bf, *e);
112         if (*e == '\0' || *e == '|') {
113             // printf("fuori2 [%s]\n", name);
114             return 1;
115         }
116     }
117     
118     return 0;
119 }
120        
121         
122
123 // struct hostent *gethostbyname(const char *name);
124 struct hostent *gethostbyname2(const char *name, int af);
125
126 struct hostent *gethostbyname2(const char *name, int af)
127 {
128     char *real;
129     if (is_an_alias(name) && (real = getenv("OVERHOSTS_REAL")) != NULL) {
130         return (gethostbyname2(real, af));
131     }
132     else {
133         return (gethostbyname2(name, af));
134     }
135 }
136
137 // struct hostent *gethostbyname(const char *name);
138 struct hostent *gethostbyname(const char *name);
139
140 struct hostent *gethostbyname(const char *name)
141 {
142     char *real;
143     if (is_an_alias(name) && (real = getenv("OVERHOSTS_REAL")) != NULL) {
144         return (gethostbyname(real));
145     }
146     else {
147         return (gethostbyname(name));
148     }
149 }
150
151 int getaddrinfo(const char *node, const char *service,
152                 const struct addrinfo *hints,
153                 struct addrinfo **res);
154
155 int getaddrinfo(const char *node, const char *service,
156                 const struct addrinfo *hints,
157                 struct addrinfo **res)
158 {
159     char *real;
160
161     if (is_an_alias(node) && (real = getenv("OVERHOSTS_REAL")) != NULL) {
162         
163         if (hints->ai_flags | AI_CANONNAME) {
164             printf("WARNING: AI_CANONAME set\n");
165         }
166         return ohreal_getaddrinfo(real, service,
167                                    hints, res);
168     }
169     else {
170         return ohreal_getaddrinfo(node, service,
171                                    hints, res);
172     }
173 }