ip_rcmd_pxy.c revision 110916
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: head/sys/contrib/ipfilter/netinet/ip_rcmd_pxy.c 110916 2003-02-15 06:25:25Z 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; 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 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 */ 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); 137 if (ipn == NULL) { 138 int slen; 139 140 slen = ip->ip_len; 141 ip->ip_len = fin->fin_hlen + sizeof(*tcp); 142 bzero((char *)tcp2, sizeof(*tcp2)); 143 tcp2->th_win = htons(8192); 144 tcp2->th_sport = htons(sp); 145 tcp2->th_dport = 0; /* XXX - don't specify remote port */ 146 tcp2->th_off = 5; 147 tcp2->th_flags = TH_SYN; 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; 153 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; 158 (void) fr_addstate(ip, &fi, NULL, 159 FI_W_DPORT|FI_IGNOREPKT); 160 } 161 ip->ip_len = slen; 162 ip->ip_src = swip; 163 } 164 return 0; 165} 166 167 168int ippr_rcmd_out(fin, ip, aps, nat) 169fr_info_t *fin; 170ip_t *ip; 171ap_session_t *aps; 172nat_t *nat; 173{ 174 return ippr_rcmd_portmsg(fin, ip, aps, nat); 175} 176