1/*
| 1/*
|
2 * $Id: ip_rcmd_pxy.c,v 1.4.2.4 2000/11/01 14:34:20 darrenr Exp $
| 2 * $Id: ip_rcmd_pxy.c,v 1.4.2.5 2001/10/30 16:38:14 darrenr Exp $
|
3 */ 4/* 5 * Simple RCMD transparent proxy for in-kernel use. For use with the NAT 6 * code.
| 3 */ 4/* 5 * Simple RCMD transparent proxy for in-kernel use. For use with the NAT 6 * code.
|
7 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c 72006 2001-02-04 14:26:56Z darrenr $
| 7 * $FreeBSD: head/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c 92685 2002-03-19 11:44:16Z darrenr $
|
8 */ 9#if SOLARIS && defined(_KERNEL) 10extern kmutex_t ipf_rw; 11#endif 12 13#define isdigit(x) ((x) >= '0' && (x) <= '9') 14 15#define IPF_RCMD_PROXY 16 17 18int ippr_rcmd_init __P((void)); 19int ippr_rcmd_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 20int ippr_rcmd_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 21u_short ipf_rcmd_atoi __P((char *)); 22int ippr_rcmd_portmsg __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 23 24static frentry_t rcmdfr; 25 26 27/* 28 * RCMD application proxy initialization. 29 */ 30int 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 */ 42int ippr_rcmd_new(fin, ip, aps, nat) 43fr_info_t *fin; 44ip_t *ip; 45ap_session_t *aps; 46nat_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 */ 64u_short ipf_rcmd_atoi(ptr) 65char *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 78int ippr_rcmd_portmsg(fin, ip, aps, nat) 79fr_info_t *fin; 80ip_t *ip; 81ap_session_t *aps; 82nat_t *nat; 83{ 84 char portbuf[8], *s; 85 struct in_addr swip;
| 8 */ 9#if SOLARIS && defined(_KERNEL) 10extern kmutex_t ipf_rw; 11#endif 12 13#define isdigit(x) ((x) >= '0' && (x) <= '9') 14 15#define IPF_RCMD_PROXY 16 17 18int ippr_rcmd_init __P((void)); 19int ippr_rcmd_new __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 20int ippr_rcmd_out __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 21u_short ipf_rcmd_atoi __P((char *)); 22int ippr_rcmd_portmsg __P((fr_info_t *, ip_t *, ap_session_t *, nat_t *)); 23 24static frentry_t rcmdfr; 25 26 27/* 28 * RCMD application proxy initialization. 29 */ 30int 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 */ 42int ippr_rcmd_new(fin, ip, aps, nat) 43fr_info_t *fin; 44ip_t *ip; 45ap_session_t *aps; 46nat_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 */ 64u_short ipf_rcmd_atoi(ptr) 65char *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 78int ippr_rcmd_portmsg(fin, ip, aps, nat) 79fr_info_t *fin; 80ip_t *ip; 81ap_session_t *aps; 82nat_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;
| 86 int off, dlen; 87 tcphdr_t *tcp, tcph, *tcp2 = &tcph; 88 fr_info_t fi;
|
| 89 u_short sp;
|
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 98 if (tcp->th_flags & TH_SYN) { 99 *(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1); 100 return 0; 101 } 102 103 if ((*(u_32_t *)aps->aps_data != 0) && 104 (tcp->th_seq != *(u_32_t *)aps->aps_data)) 105 return 0; 106
| 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 98 if (tcp->th_flags & TH_SYN) { 99 *(u_32_t *)aps->aps_data = htonl(ntohl(tcp->th_seq) + 1); 100 return 0; 101 } 102 103 if ((*(u_32_t *)aps->aps_data != 0) && 104 (tcp->th_seq != *(u_32_t *)aps->aps_data)) 105 return 0; 106
|
107 off = (ip->ip_hl << 2) + (tcp->th_off << 2);
| 107 off = fin->fin_hlen + (tcp->th_off << 2);
|
108 109#if SOLARIS 110 m = fin->fin_qfm; 111 112 dlen = msgdsize(m) - off; 113 bzero(portbuf, sizeof(portbuf)); 114 copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); 115#else 116 m = *(mb_t **)fin->fin_mp; 117 dlen = mbufchainlen(m) - off; 118 bzero(portbuf, sizeof(portbuf)); 119 m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); 120#endif 121 122 portbuf[sizeof(portbuf) - 1] = '\0'; 123 s = portbuf; 124 sp = ipf_rcmd_atoi(s); 125 if (!sp) 126 return 0; 127 128 /* 129 * Add skeleton NAT entry for connection which will come back the 130 * other way. 131 */
| 108 109#if SOLARIS 110 m = fin->fin_qfm; 111 112 dlen = msgdsize(m) - off; 113 bzero(portbuf, sizeof(portbuf)); 114 copyout_mblk(m, off, MIN(sizeof(portbuf), dlen), portbuf); 115#else 116 m = *(mb_t **)fin->fin_mp; 117 dlen = mbufchainlen(m) - off; 118 bzero(portbuf, sizeof(portbuf)); 119 m_copydata(m, off, MIN(sizeof(portbuf), dlen), portbuf); 120#endif 121 122 portbuf[sizeof(portbuf) - 1] = '\0'; 123 s = portbuf; 124 sp = ipf_rcmd_atoi(s); 125 if (!sp) 126 return 0; 127 128 /* 129 * Add skeleton NAT entry for connection which will come back the 130 * other way. 131 */
|
132 sp = htons(sp); 133 dp = htons(fin->fin_data[1]); 134 ipn = nat_outlookup(fin->fin_ifp, IPN_TCP, nat->nat_p, nat->nat_inip, 135 ip->ip_dst, (dp << 16) | sp, 0);
| 132 bcopy((char *)fin, (char *)&fi, sizeof(fi)); 133 fi.fin_data[0] = sp; 134 fi.fin_data[1] = fin->fin_data[1]; 135 ipn = nat_outlookup(&fi, IPN_TCP, nat->nat_p, nat->nat_inip, 136 ip->ip_dst, 0);
|
136 if (ipn == NULL) { 137 int slen; 138 139 slen = ip->ip_len; 140 ip->ip_len = fin->fin_hlen + sizeof(*tcp);
| 137 if (ipn == NULL) { 138 int slen; 139 140 slen = ip->ip_len; 141 ip->ip_len = fin->fin_hlen + sizeof(*tcp);
|
141 bcopy((char *)fin, (char *)&fi, sizeof(fi));
| |
142 bzero((char *)tcp2, sizeof(*tcp2)); 143 tcp2->th_win = htons(8192);
| 142 bzero((char *)tcp2, sizeof(*tcp2)); 143 tcp2->th_win = htons(8192);
|
144 tcp2->th_sport = sp;
| 144 tcp2->th_sport = htons(sp);
|
145 tcp2->th_dport = 0; /* XXX - don't specify remote port */ 146 tcp2->th_off = 5;
| 145 tcp2->th_dport = 0; /* XXX - don't specify remote port */ 146 tcp2->th_off = 5;
|
147 fi.fin_data[0] = ntohs(sp);
| |
148 fi.fin_data[1] = 0; 149 fi.fin_dp = (char *)tcp2; 150 fi.fin_dlen = sizeof(*tcp2); 151 swip = ip->ip_src; 152 ip->ip_src = nat->nat_inip;
| 147 fi.fin_data[1] = 0; 148 fi.fin_dp = (char *)tcp2; 149 fi.fin_dlen = sizeof(*tcp2); 150 swip = ip->ip_src; 151 ip->ip_src = nat->nat_inip;
|
153 ipn = nat_new(nat->nat_ptr, ip, &fi, IPN_TCP|FI_W_DPORT,
| 152 ipn = nat_new(&fi, ip, nat->nat_ptr, NULL, IPN_TCP|FI_W_DPORT,
|
154 NAT_OUTBOUND); 155 if (ipn != NULL) { 156 ipn->nat_age = fr_defnatage; 157 fi.fin_fr = &rcmdfr;
| 153 NAT_OUTBOUND); 154 if (ipn != NULL) { 155 ipn->nat_age = fr_defnatage; 156 fi.fin_fr = &rcmdfr;
|
158 (void) fr_addstate(ip, &fi, FI_W_DPORT);
| 157 (void) fr_addstate(ip, &fi, NULL, 158 FI_W_DPORT|FI_IGNOREPKT);
|
159 } 160 ip->ip_len = slen; 161 ip->ip_src = swip; 162 } 163 return 0; 164} 165 166 167int ippr_rcmd_out(fin, ip, aps, nat) 168fr_info_t *fin; 169ip_t *ip; 170ap_session_t *aps; 171nat_t *nat; 172{ 173 return ippr_rcmd_portmsg(fin, ip, aps, nat); 174}
| 159 } 160 ip->ip_len = slen; 161 ip->ip_src = swip; 162 } 163 return 0; 164} 165 166 167int ippr_rcmd_out(fin, ip, aps, nat) 168fr_info_t *fin; 169ip_t *ip; 170ap_session_t *aps; 171nat_t *nat; 172{ 173 return ippr_rcmd_portmsg(fin, ip, aps, nat); 174}
|