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