2 * smtpallow.c - ld_preload for hacking with connect() !
4 * Copyright (C) 1994,1995 Ian Jackson <iwj10@cus.cam.ac.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 2,
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, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <sys/socketcall.h>
23 #include <netinet/in.h>
26 _syscall2(long,socketcall,int,call,unsigned long *,args);
28 int real_connect(int sockfd, const struct sockaddr *saddr, int addrlen)
30 unsigned long args[3];
33 args[1] = (unsigned long)saddr;
35 return socketcall(SYS_CONNECT, args);
38 int connect(int fd, const struct sockaddr *them_any, int addrlen) {
39 struct sockaddr_in *them= (struct sockaddr_in*)them_any;
41 struct sockaddr_in us;
43 if (addrlen == sizeof(us) &&
44 them->sin_family == AF_INET &&
45 them->sin_port == htons(25)) {
46 memset(&us,0,sizeof(us));
48 us.sin_family= AF_INET;
49 us.sin_addr.s_addr= INADDR_ANY;
50 r= getsockname(fd,(struct sockaddr*)&us,&l);
51 if (r<0 && errno != EINVAL) return r;
52 if (!ntohs(us.sin_port)) {
53 for (i=1023; i>0; i--) {
54 us.sin_port= htons(i);
55 if (!bind(fd,(struct sockaddr*)&us,sizeof(us))) break;
56 if (errno != EADDRINUSE) return -1;
59 } else if (r<0) return r;
61 return real_connect(fd,them_any,addrlen);