2 * smtpallow.c - ld_preload for hacking with connect() !
4 * Copyright (C) 1994,1995 Ian Jackson <ian@davenant.greenend.org.uk>
6 * This is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3,
9 * or (at your option) any later version.
11 * This is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this file; if not, consult the Free Software
18 * Foundation's website at www.fsf.org, or the GNU Project website at
23 #include <sys/socketcall.h>
24 #include <netinet/in.h>
27 _syscall2(long,socketcall,int,call,unsigned long *,args);
29 int real_connect(int sockfd, const struct sockaddr *saddr, int addrlen)
31 unsigned long args[3];
34 args[1] = (unsigned long)saddr;
36 return socketcall(SYS_CONNECT, args);
39 int connect(int fd, const struct sockaddr *them_any, int addrlen) {
40 struct sockaddr_in *them= (struct sockaddr_in*)them_any;
42 struct sockaddr_in us;
44 if (addrlen == sizeof(us) &&
45 them->sin_family == AF_INET &&
46 them->sin_port == htons(25)) {
47 memset(&us,0,sizeof(us));
49 us.sin_family= AF_INET;
50 us.sin_addr.s_addr= INADDR_ANY;
51 r= getsockname(fd,(struct sockaddr*)&us,&l);
52 if (r<0 && errno != EINVAL) return r;
53 if (!ntohs(us.sin_port)) {
54 for (i=1023; i>0; i--) {
55 us.sin_port= htons(i);
56 if (!bind(fd,(struct sockaddr*)&us,sizeof(us))) break;
57 if (errno != EADDRINUSE) return -1;
60 } else if (r<0) return r;
62 return real_connect(fd,them_any,addrlen);