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