rename functions that clash with reserved math procedures to avoid gcc3.4
[dragonfly.git] / sys / contrib / ipfilter / netinet / ip_rcmd_pxy.c
1 /*
2  * $Id: ip_rcmd_pxy.c,v 1.4.2.6 2002/10/01 15:24:59 darrenr Exp $
3  */
4 /*
5  * Simple RCMD transparent proxy for in-kernel use.  For use with the NAT
6  * code.
7  * $FreeBSD: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.8.2.3 2003/03/01 03:55:54 darrenr Exp $
8  * $DragonFly: src/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c,v 1.4 2003/08/27 11:02:14 rob Exp $
9  */
10 #if SOLARIS && defined(_KERNEL)
11 extern  kmutex_t        ipf_rw;
12 #endif
13
14 #define isdigit(x)      ((x) >= '0' && (x) <= '9')
15
16 #define IPF_RCMD_PROXY
17
18
19 int ippr_rcmd_init (void);
20 int ippr_rcmd_new (fr_info_t *, ip_t *, ap_session_t *, nat_t *);
21 int ippr_rcmd_out (fr_info_t *, ip_t *, ap_session_t *, nat_t *);
22 u_short ipf_rcmd_atoi (char *);
23 int ippr_rcmd_portmsg (fr_info_t *, ip_t *, ap_session_t *, nat_t *);
24
25 static  frentry_t       rcmdfr;
26
27
28 /*
29  * RCMD application proxy initialization.
30  */
31 int ippr_rcmd_init()
32 {
33         bzero((char *)&rcmdfr, sizeof(rcmdfr));
34         rcmdfr.fr_ref = 1;
35         rcmdfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
36         return 0;
37 }
38
39
40 /*
41  * Setup for a new RCMD proxy.
42  */
43 int ippr_rcmd_new(fin, ip, aps, nat)
44 fr_info_t *fin;
45 ip_t *ip;
46 ap_session_t *aps;
47 nat_t *nat;
48 {
49         tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp;
50
51         aps->aps_psiz = sizeof(u_32_t);
52         KMALLOCS(aps->aps_data, u_32_t *, sizeof(u_32_t));
53         if (aps->aps_data == NULL)
54                 return -1;
55         *(u_32_t *)aps->aps_data = 0;
56         aps->aps_sport = tcp->th_sport;
57         aps->aps_dport = tcp->th_dport;
58         return 0;
59 }
60
61
62 /*
63  * ipf_rcmd_atoi - implement a simple version of atoi
64  */
65 u_short ipf_rcmd_atoi(ptr)
66 char *ptr;
67 {
68         char *s = ptr, c;
69         u_short i = 0;
70
71         while ((c = *s++) && isdigit(c)) {
72                 i *= 10;
73                 i += c - '0';
74         }
75         return i;
76 }
77
78
79 int ippr_rcmd_portmsg(fin, ip, aps, nat)
80 fr_info_t *fin;
81 ip_t *ip;
82 ap_session_t *aps;
83 nat_t *nat;
84 {
85         char portbuf[8], *s;
86         struct in_addr swip;
87         int off, dlen;
88         tcphdr_t *tcp, tcph, *tcp2 = &tcph;
89         fr_info_t fi;
90         u_short sp;
91         nat_t *ipn;
92         mb_t *m;
93 #if     SOLARIS
94         mb_t *m1;
95 #endif
96
97         tcp = (tcphdr_t *)fin->fin_dp;
98
99         if (tcp->th_flags & TH_SYN) {
100                 *(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1);
101                 return 0;
102         }
103
104         if ((*(u_32_t *)aps->aps_data != 0) &&
105             (tcp->th_seq != *(u_32_t *)aps->aps_data))
106                 return 0;
107
108         off = fin->fin_hlen + (tcp->th_off << 2);
109
110 #if     SOLARIS
111         m = fin->fin_qfm;
112
113         dlen = msgdsize(m) - off;
114         bzero(portbuf, sizeof(portbuf));
115         copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf);
116 #else
117         m = *(mb_t **)fin->fin_mp;
118         dlen = mbufchainlen(m) - off;
119         bzero(portbuf, sizeof(portbuf));
120         m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf);
121 #endif
122
123         portbuf[sizeof(portbuf) - 1] = '\0';
124         s = portbuf;
125         sp = ipf_rcmd_atoi(s);
126         if (!sp)
127                 return 0;
128
129         /*
130          * Add skeleton NAT entry for connection which will come back the
131          * other way.
132          */
133         bcopy((char *)fin, (char *)&fi, sizeof(fi));
134         fi.fin_data[0] = sp;
135         fi.fin_data[1] = fin->fin_data[1];
136         ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip,
137                             ip->ip_dst, 0);
138         if (ipn == NULL) {
139                 int slen;
140
141                 slen = ip->ip_len;
142                 ip->ip_len = fin->fin_hlen + sizeof(*tcp);
143                 bzero((char *)tcp2, sizeof(*tcp2));
144                 tcp2->th_win = htons(8192);
145                 tcp2->th_sport = htons(sp);
146                 tcp2->th_dport = 0; /* XXX - don't specify remote port */
147                 tcp2->th_off = 5;
148                 tcp2->th_flags = TH_SYN;
149                 fi.fin_data[1] = 0;
150                 fi.fin_dp = (char *)tcp2;
151                 fi.fin_dlen = sizeof(*tcp2);
152                 swip = ip->ip_src;
153                 ip->ip_src = nat->nat_inip;
154                 ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_DPORT,
155                               NAT_OUTBOUND);
156                 if (ipn != NULL) {
157                         ipn->nat_age = fr_defnatage;
158                         fi.fin_fr = &rcmdfr;
159                         (void) fr_addstate(ip, &fi, NULL,
160                                            FI_W_DPORT|FI_IGNOREPKT);
161                 }
162                 ip->ip_len = slen;
163                 ip->ip_src = swip;
164         }
165         return 0;
166 }
167
168
169 int ippr_rcmd_out(fin, ip, aps, nat)
170 fr_info_t *fin;
171 ip_t *ip;
172 ap_session_t *aps;
173 nat_t *nat;
174 {
175         return ippr_rcmd_portmsg(fin, ip, aps, nat);
176 }