chiark / gitweb /
found on davenant in /usr/local/src/misc
[chiark-utils.git] / cprogs / smtpallow.c
1 /**/
2
3 #include <syscall.h>
4 #include <sys/socketcall.h>
5 #include <netinet/in.h>
6 #include <string.h>
7
8 _syscall2(long,socketcall,int,call,unsigned long *,args);
9
10 int real_connect(int sockfd, const struct sockaddr *saddr, int addrlen)
11 {
12         unsigned long args[3];
13
14         args[0] = sockfd;
15         args[1] = (unsigned long)saddr;
16         args[2] = addrlen;
17         return socketcall(SYS_CONNECT, args);
18 }
19
20 int connect(int fd, const struct sockaddr *them_any, int addrlen) {
21   struct sockaddr_in *them= (struct sockaddr_in*)them_any;
22   int r,l,i;
23   struct sockaddr_in us;
24   
25   if (addrlen == sizeof(us) &&
26       them->sin_family == AF_INET &&
27       them->sin_port == htons(25)) {
28     memset(&us,0,sizeof(us));
29     us.sin_port= 0;
30     us.sin_family= AF_INET;
31     us.sin_addr.s_addr= INADDR_ANY;
32     r= getsockname(fd,(struct sockaddr*)&us,&l);
33     if (r<0 && errno != EINVAL) return r;
34     if (!ntohs(us.sin_port)) {
35       for (i=1023; i>0; i--) {
36         us.sin_port= htons(i);
37         if (!bind(fd,(struct sockaddr*)&us,sizeof(us))) break;
38         if (errno != EADDRINUSE) return -1;
39       }
40       if (!i) return -1;
41     } else if (r<0) return r;
42   }
43   return real_connect(fd,them_any,addrlen);
44 }