|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (C) 1997 by Darren Reed. ! 24: * ! 25: * Redistribution and use in source and binary forms are permitted ! 26: * provided that this notice is preserved and due credit is given ! 27: * to the original author and the contributors. ! 28: */ ! 29: #if !defined(lint) ! 30: #endif ! 31: ! 32: #if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) ! 33: # define _KERNEL ! 34: #endif ! 35: ! 36: #if !defined(_KERNEL) && !defined(KERNEL) ! 37: # include <stdio.h> ! 38: # include <string.h> ! 39: # include <stdlib.h> ! 40: #endif ! 41: #include <sys/errno.h> ! 42: #include <sys/types.h> ! 43: #include <sys/param.h> ! 44: #include <sys/time.h> ! 45: #include <sys/file.h> ! 46: #if !defined(__FreeBSD__) ! 47: # include <sys/ioctl.h> ! 48: #endif ! 49: #include <sys/fcntl.h> ! 50: #include <sys/uio.h> ! 51: #ifndef linux ! 52: # include <sys/protosw.h> ! 53: #endif ! 54: #include <sys/socket.h> ! 55: #if defined(_KERNEL) ! 56: # if !defined(linux) ! 57: # include <sys/systm.h> ! 58: # else ! 59: # include <linux/string.h> ! 60: # endif ! 61: #endif ! 62: #if !defined(__SVR4) && !defined(__svr4__) ! 63: # ifndef linux ! 64: # include <sys/mbuf.h> ! 65: # endif ! 66: #else ! 67: # include <sys/byteorder.h> ! 68: # include <sys/dditypes.h> ! 69: # include <sys/stream.h> ! 70: # include <sys/kmem.h> ! 71: #endif ! 72: #if __FreeBSD__ > 2 ! 73: # include <sys/queue.h> ! 74: # include <sys/malloc.h> ! 75: #endif ! 76: #include <net/if.h> ! 77: #ifdef sun ! 78: # include <net/af.h> ! 79: #endif ! 80: #include <net/route.h> ! 81: #include <netinet/in.h> ! 82: #include <netinet/in_systm.h> ! 83: #include <netinet/ip.h> ! 84: #ifndef linux ! 85: # include <netinet/ip_var.h> ! 86: #endif ! 87: #include <netinet/tcp.h> ! 88: #include <netinet/udp.h> ! 89: #include <netinet/ip_icmp.h> ! 90: #include "netinet/ip_compat.h" ! 91: #include <netinet/tcpip.h> ! 92: #include "netinet/ip_fil.h" ! 93: #include "netinet/ip_proxy.h" ! 94: #include "netinet/ip_nat.h" ! 95: #include "netinet/ip_state.h" ! 96: ! 97: #ifndef MIN ! 98: #define MIN(a,b) (((a)<(b))?(a):(b)) ! 99: #endif ! 100: ! 101: static ap_session_t *ap_find __P((ip_t *, tcphdr_t *)); ! 102: static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *, ! 103: fr_info_t *, nat_t *)); ! 104: ! 105: static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src, ! 106: struct in_addr dst, void *tcp, u_short sport, ! 107: u_short dport)); ! 108: ! 109: #define AP_SESS_SIZE 53 ! 110: ! 111: #if defined(_KERNEL) && !defined(linux) ! 112: #include "netinet/ip_ftp_pxy.c" ! 113: #endif ! 114: ! 115: ap_session_t *ap_sess_tab[AP_SESS_SIZE]; ! 116: aproxy_t ap_proxies[] = { ! 117: #if IPF_FTP_PROXY ! 118: { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out }, ! 119: #endif ! 120: { "", '\0', 0, 0, NULL, NULL } ! 121: }; ! 122: ! 123: ! 124: int ap_ok(ip, tcp, nat) ! 125: ip_t *ip; ! 126: tcphdr_t *tcp; ! 127: ipnat_t *nat; ! 128: { ! 129: aproxy_t *apr = nat->in_apr; ! 130: u_short dport = nat->in_dport; ! 131: ! 132: if (!apr || (apr && (apr->apr_flags & APR_DELETE)) || ! 133: (ip->ip_p != apr->apr_p)) ! 134: return 0; ! 135: if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) ! 136: return 0; ! 137: return 1; ! 138: } ! 139: ! 140: ! 141: static int ! 142: ap_matchsrcdst(aps, src, dst, tcp, sport, dport) ! 143: ap_session_t *aps; ! 144: struct in_addr src, dst; ! 145: void *tcp; ! 146: u_short sport, dport; ! 147: { ! 148: if (aps->aps_dst.s_addr == dst.s_addr) { ! 149: if ((aps->aps_src.s_addr == src.s_addr) && ! 150: (!tcp || (sport == aps->aps_sport) && ! 151: (dport == aps->aps_dport))) ! 152: return 1; ! 153: } else if (aps->aps_dst.s_addr == src.s_addr) { ! 154: if ((aps->aps_src.s_addr == dst.s_addr) && ! 155: (!tcp || (sport == aps->aps_dport) && ! 156: (dport == aps->aps_sport))) ! 157: return 1; ! 158: } ! 159: return 0; ! 160: } ! 161: ! 162: ! 163: static ap_session_t *ap_find(ip, tcp) ! 164: ip_t *ip; ! 165: tcphdr_t *tcp; ! 166: { ! 167: register u_char p = ip->ip_p; ! 168: register ap_session_t *aps; ! 169: register u_short sp, dp; ! 170: register u_long hv; ! 171: struct in_addr src, dst; ! 172: ! 173: src = ip->ip_src, dst = ip->ip_dst; ! 174: sp = dp = 0; /* XXX gcc -Wunitialized */ ! 175: ! 176: hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr; ! 177: hv *= 651733; ! 178: if (tcp) { ! 179: sp = tcp->th_sport; ! 180: dp = tcp->th_dport; ! 181: hv ^= (sp + dp); ! 182: hv *= 5; ! 183: } ! 184: hv %= AP_SESS_SIZE; ! 185: ! 186: for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next) ! 187: if ((aps->aps_p == p) && ! 188: ap_matchsrcdst(aps, src, dst, tcp, sp, dp)) ! 189: break; ! 190: return aps; ! 191: } ! 192: ! 193: ! 194: /* ! 195: * Allocate a new application proxy structure and fill it in with the ! 196: * relevant details. call the init function once complete, prior to ! 197: * returning. ! 198: */ ! 199: static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat) ! 200: aproxy_t *apr; ! 201: ip_t *ip; ! 202: tcphdr_t *tcp; ! 203: fr_info_t *fin; ! 204: nat_t *nat; ! 205: { ! 206: register ap_session_t *aps; ! 207: u_short dport; ! 208: u_long hv; ! 209: ! 210: if (!apr || (apr && (apr->apr_flags & APR_DELETE)) || ! 211: (ip->ip_p != apr->apr_p)) ! 212: return NULL; ! 213: dport = nat->nat_ptr->in_dport; ! 214: if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) ! 215: return NULL; ! 216: ! 217: hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr; ! 218: hv *= 651733; ! 219: if (tcp) { ! 220: hv ^= (tcp->th_sport + tcp->th_dport); ! 221: hv *= 5; ! 222: } ! 223: hv %= AP_SESS_SIZE; ! 224: ! 225: KMALLOC(aps, ap_session_t *, sizeof(*aps)); ! 226: if (!aps) ! 227: return NULL; ! 228: bzero((char *)aps, sizeof(*aps)); ! 229: aps->aps_apr = apr; ! 230: aps->aps_src = ip->ip_src; ! 231: aps->aps_dst = ip->ip_dst; ! 232: aps->aps_p = ip->ip_p; ! 233: aps->aps_tout = 1200; /* XXX */ ! 234: if (tcp) { ! 235: aps->aps_sport = tcp->th_sport; ! 236: aps->aps_dport = tcp->th_dport; ! 237: } ! 238: aps->aps_data = NULL; ! 239: aps->aps_psiz = 0; ! 240: aps->aps_next = ap_sess_tab[hv]; ! 241: ap_sess_tab[hv] = aps; ! 242: (void) (*apr->apr_init)(fin, ip, tcp, aps, nat); ! 243: return aps; ! 244: } ! 245: ! 246: ! 247: /* ! 248: * check to see if a packet should be passed through an active proxy routine ! 249: * if one has been setup for it. ! 250: */ ! 251: int ap_check(ip, tcp, fin, nat) ! 252: ip_t *ip; ! 253: tcphdr_t *tcp; ! 254: fr_info_t *fin; ! 255: nat_t *nat; ! 256: { ! 257: ap_session_t *aps; ! 258: aproxy_t *apr; ! 259: int err; ! 260: ! 261: if (!(fin->fin_fi.fi_fl & FI_TCPUDP)) ! 262: tcp = NULL; ! 263: ! 264: if ((aps = ap_find(ip, tcp)) || ! 265: (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) { ! 266: if (ip->ip_p == IPPROTO_TCP) { ! 267: /* ! 268: * verify that the checksum is correct. If not, then ! 269: * don't do anything with this packet. ! 270: */ ! 271: if (tcp->th_sum != fr_tcpsum(*(mb_t **)fin->fin_mp, ! 272: ip, tcp, ip->ip_len)) { ! 273: frstats[fin->fin_out].fr_tcpbad++; ! 274: return -1; ! 275: } ! 276: fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin, ! 277: tcp->th_sport == aps->aps_sport); ! 278: } ! 279: ! 280: apr = aps->aps_apr; ! 281: err = 0; ! 282: if (fin->fin_out) { ! 283: if (apr->apr_outpkt) ! 284: err = (*apr->apr_outpkt)(fin, ip, tcp, ! 285: aps, nat); ! 286: } else { ! 287: if (apr->apr_inpkt) ! 288: err = (*apr->apr_inpkt)(fin, ip, tcp, ! 289: aps, nat); ! 290: } ! 291: if (err == 2) { ! 292: tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, ! 293: tcp, ip->ip_len); ! 294: err = 0; ! 295: } ! 296: return err; ! 297: } ! 298: return -1; ! 299: } ! 300: ! 301: ! 302: aproxy_t *ap_match(pr, name) ! 303: u_char pr; ! 304: char *name; ! 305: { ! 306: aproxy_t *ap; ! 307: ! 308: for (ap = ap_proxies; ap->apr_p; ap++) ! 309: if ((ap->apr_p == pr) && ! 310: !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { ! 311: ap->apr_ref++; ! 312: return ap; ! 313: } ! 314: return NULL; ! 315: } ! 316: ! 317: ! 318: void ap_free(ap) ! 319: aproxy_t *ap; ! 320: { ! 321: ap->apr_ref--; ! 322: } ! 323: ! 324: ! 325: void aps_free(aps) ! 326: ap_session_t *aps; ! 327: { ! 328: if (aps->aps_data && aps->aps_psiz) ! 329: KFREES(aps->aps_data, aps->aps_psiz); ! 330: KFREE(aps); ! 331: } ! 332: ! 333: ! 334: void ap_unload() ! 335: { ! 336: ap_session_t *aps; ! 337: int i; ! 338: ! 339: for (i = 0; i < AP_SESS_SIZE; i++) ! 340: while ((aps = ap_sess_tab[i])) { ! 341: ap_sess_tab[i] = aps->aps_next; ! 342: aps_free(aps); ! 343: } ! 344: } ! 345: ! 346: ! 347: void ap_expire() ! 348: { ! 349: ap_session_t *aps, **apsp; ! 350: int i; ! 351: ! 352: for (i = 0; i < AP_SESS_SIZE; i++) ! 353: for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) { ! 354: aps->aps_tout--; ! 355: if (!aps->aps_tout) { ! 356: ap_sess_tab[i] = aps->aps_next; ! 357: aps_free(aps); ! 358: *apsp = aps->aps_next; ! 359: } else ! 360: apsp = &aps->aps_next; ! 361: } ! 362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.