The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_h323_pxy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ip_h323_pxy.c,v 1.9.2.1 2004/08/13 03:55:22 jmc Exp $  */
    2 
    3 /*
    4  * Copyright 2001, QNX Software Systems Ltd. All Rights Reserved
    5  *
    6  * This source code has been published by QNX Software Systems Ltd. (QSSL).
    7  * However, any use, reproduction, modification, distribution or transfer of
    8  * this software, or any software which includes or is based upon any of this
    9  * code, is only permitted under the terms of the QNX Open Community License
   10  * version 1.0 (see licensing.qnx.com for details) or as otherwise expressly
   11  * authorized by a written license agreement from QSSL. For more information,
   12  * please email licensing@qnx.com.
   13  *
   14  * For more details, see QNX_OCL.txt provided with this distribution.
   15  */
   16 
   17 /*
   18  * Simple H.323 proxy
   19  *
   20  *      by xtang@canada.com
   21  *      ported to ipfilter 3.4.20 by Michael Grant mg-ipf@grant.org
   22  */
   23 
   24 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
   25 # include <sys/fcntl.h>
   26 # include <sys/filio.h>
   27 #else
   28 # ifndef linux
   29 #  include <sys/ioctl.h>
   30 # endif
   31 #endif
   32 
   33 #ifdef _KERNEL_OPT
   34 #include "opt_ipfilter_log.h"
   35 #endif
   36 
   37 __KERNEL_RCSID(1, "$NetBSD: ip_h323_pxy.c,v 1.9.2.1 2004/08/13 03:55:22 jmc Exp $");
   38 
   39 #define IPF_H323_PROXY
   40 
   41 int  ippr_h323_init __P((void));
   42 void  ippr_h323_fini __P((void));
   43 int  ippr_h323_new __P((fr_info_t *, ap_session_t *, nat_t *));
   44 void ippr_h323_del __P((ap_session_t *));
   45 int  ippr_h323_out __P((fr_info_t *, ap_session_t *, nat_t *));
   46 int  ippr_h323_in __P((fr_info_t *, ap_session_t *, nat_t *));
   47 
   48 int  ippr_h245_new __P((fr_info_t *, ap_session_t *, nat_t *));
   49 int  ippr_h245_out __P((fr_info_t *, ap_session_t *, nat_t *));
   50 int  ippr_h245_in __P((fr_info_t *, ap_session_t *, nat_t *));
   51 
   52 static  frentry_t       h323_fr;
   53 
   54 int     h323_proxy_init = 0;
   55 
   56 static int find_port __P((int, caddr_t, int datlen, int *, u_short *));
   57 
   58 
   59 static int find_port(ipaddr, data, datlen, off, port)
   60 int ipaddr;
   61 caddr_t data;
   62 int datlen, *off;
   63 unsigned short *port;
   64 {
   65         u_32_t addr, netaddr;
   66         u_char *dp;
   67         int offset;
   68 
   69         if (datlen < 6)
   70                 return -1;
   71         
   72         *port = 0;
   73         offset = *off;
   74         dp = (u_char *)data;
   75         netaddr = ntohl(ipaddr);
   76 
   77         for (offset = 0; offset <= datlen - 6; offset++, dp++) {
   78                 addr = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3];
   79                 if (netaddr == addr)
   80                 {
   81                         *port = (*(dp + 4) << 8) | *(dp + 5);
   82                         break;
   83                 }
   84         }
   85         *off = offset;
   86         return (offset > datlen - 6) ? -1 : 0;
   87 }
   88 
   89 /*
   90  * Initialize local structures.
   91  */
   92 int ippr_h323_init()
   93 {
   94         bzero((char *)&h323_fr, sizeof(h323_fr));
   95         h323_fr.fr_ref = 1;
   96         h323_fr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
   97         MUTEX_INIT(&h323_fr.fr_lock, "H323 proxy rule lock");
   98         h323_proxy_init = 1;
   99 
  100         return 0;
  101 }
  102 
  103 
  104 void ippr_h323_fini()
  105 {
  106         if (h323_proxy_init == 1) {
  107                 MUTEX_DESTROY(&h323_fr.fr_lock);
  108                 h323_proxy_init = 0;
  109         }
  110 }
  111 
  112 
  113 int ippr_h323_new(fin, aps, nat)
  114 fr_info_t *fin;
  115 ap_session_t *aps;
  116 nat_t *nat;
  117 {
  118         fin = fin;      /* LINT */
  119         nat = nat;      /* LINT */
  120 
  121         aps->aps_data = NULL;
  122         aps->aps_psiz = 0;
  123 
  124         return 0;
  125 }
  126 
  127 
  128 void ippr_h323_del(aps)
  129 ap_session_t *aps;
  130 {
  131         int i;
  132         ipnat_t *ipn;
  133         
  134         if (aps->aps_data) {
  135                 for (i = 0, ipn = aps->aps_data;
  136                      i < (aps->aps_psiz / sizeof(ipnat_t));
  137                      i++, ipn = (ipnat_t *)((char *)ipn + sizeof(*ipn)))
  138                 {
  139                         /*
  140                          * Check the comment in ippr_h323_in() function,
  141                          * just above fr_nat_ioctl() call.
  142                          * We are lucky here because this function is not
  143                          * called with ipf_nat locked.
  144                          */
  145                         if (fr_nat_ioctl((caddr_t)ipn, SIOCRMNAT, NAT_SYSSPACE|
  146                                          NAT_LOCKHELD|FWRITE) == -1) {
  147                                 /*EMPTY*/;
  148                                 /* log the error */
  149                         }
  150                 }
  151                 KFREES(aps->aps_data, aps->aps_psiz);
  152                 /* avoid double free */
  153                 aps->aps_data = NULL;
  154                 aps->aps_psiz = 0;
  155         }
  156         return;
  157 }
  158 
  159 
  160 int ippr_h323_in(fin, aps, nat)
  161 fr_info_t *fin;
  162 ap_session_t *aps;
  163 nat_t *nat;
  164 {
  165         int ipaddr, off, datlen;
  166         unsigned short port;
  167         caddr_t data;
  168         tcphdr_t *tcp;
  169         ip_t *ip;
  170 
  171         ip = fin->fin_ip;
  172         tcp = (tcphdr_t *)fin->fin_dp;
  173         ipaddr = ip->ip_src.s_addr;
  174         
  175         data = (caddr_t)tcp + (TCP_OFF(tcp) << 2);
  176         datlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
  177         if (find_port(ipaddr, data, datlen, &off, &port) == 0) {
  178                 ipnat_t *ipn;
  179                 char *newarray;
  180 
  181                 /* setup a nat rule to set a h245 proxy on tcp-port "port"
  182                  * it's like:
  183                  *   map <if> <inter_ip>/<mask> -> <gate_ip>/<mask> proxy port <port> <port>/tcp
  184                  */
  185                 KMALLOCS(newarray, char *, aps->aps_psiz + sizeof(*ipn));
  186                 if (newarray == NULL) {
  187                         return -1;
  188                 }
  189                 ipn = (ipnat_t *)&newarray[aps->aps_psiz];
  190                 bcopy((caddr_t)nat->nat_ptr, (caddr_t)ipn, sizeof(ipnat_t));
  191                 (void) strncpy(ipn->in_plabel, "h245", APR_LABELLEN);
  192                 
  193                 ipn->in_inip = nat->nat_inip.s_addr;
  194                 ipn->in_inmsk = 0xffffffff;
  195                 ipn->in_dport = htons(port);
  196                 /*
  197                  * we got a problem here. we need to call fr_nat_ioctl() to add
  198                  * the h245 proxy rule, but since we already hold (READ locked)
  199                  * the nat table rwlock (ipf_nat), if we go into fr_nat_ioctl(),
  200                  * it will try to WRITE lock it. This will causing dead lock
  201                  * on RTP.
  202                  *
  203                  * The quick & dirty solution here is release the read lock,
  204                  * call fr_nat_ioctl() and re-lock it.
  205                  * A (maybe better) solution is do a UPGRADE(), and instead
  206                  * of calling fr_nat_ioctl(), we add the nat rule ourself.
  207                  */
  208                 RWLOCK_EXIT(&ipf_nat);
  209                 if (fr_nat_ioctl((caddr_t)ipn, SIOCADNAT,
  210                                  NAT_SYSSPACE|FWRITE) == -1) {
  211                         READ_ENTER(&ipf_nat);
  212                         return -1;
  213                 }
  214                 READ_ENTER(&ipf_nat);
  215                 if (aps->aps_data != NULL && aps->aps_psiz > 0) {
  216                         bcopy(aps->aps_data, newarray, aps->aps_psiz);
  217                         KFREES(aps->aps_data, aps->aps_psiz);
  218                 }
  219                 aps->aps_data = newarray;
  220                 aps->aps_psiz += sizeof(*ipn);
  221         }
  222         return 0;
  223 }
  224 
  225 
  226 int ippr_h245_new(fin, aps, nat)
  227 fr_info_t *fin;
  228 ap_session_t *aps;
  229 nat_t *nat;
  230 {
  231         fin = fin;      /* LINT */
  232         nat = nat;      /* LINT */
  233 
  234         aps->aps_data = NULL;
  235         aps->aps_psiz = 0;
  236         return 0;
  237 }
  238 
  239 
  240 int ippr_h245_out(fin, aps, nat)
  241 fr_info_t *fin;
  242 ap_session_t *aps;
  243 nat_t *nat;
  244 {
  245         int ipaddr, off, datlen;
  246         tcphdr_t *tcp;
  247         caddr_t data;
  248         u_short port;
  249         ip_t *ip;
  250 
  251         aps = aps;      /* LINT */
  252 
  253         ip = fin->fin_ip;
  254         tcp = (tcphdr_t *)fin->fin_dp;
  255         ipaddr = nat->nat_inip.s_addr;
  256         data = (caddr_t)tcp + (TCP_OFF(tcp) << 2);
  257         datlen = ip->ip_len - fin->fin_hlen - (TCP_OFF(tcp) << 2);
  258         if (find_port(ipaddr, data, datlen, &off, &port) == 0) {
  259                 fr_info_t fi;
  260                 nat_t     *nat2;
  261 
  262 /*              port = htons(port); */
  263                 nat2 = nat_outlookup(fin->fin_ifp, IPN_UDP, IPPROTO_UDP,
  264                                     ip->ip_src, ip->ip_dst);
  265                 if (nat2 == NULL) {
  266                         struct ip newip;
  267                         struct udphdr udp;
  268                         
  269                         bcopy((caddr_t)ip, (caddr_t)&newip, sizeof(newip));
  270                         newip.ip_len = fin->fin_hlen + sizeof(udp);
  271                         newip.ip_p = IPPROTO_UDP;
  272                         newip.ip_src = nat->nat_inip;
  273                         
  274                         bzero((char *)&udp, sizeof(udp));
  275                         udp.uh_sport = port;
  276                         
  277                         bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
  278                         fi.fin_fi.fi_p = IPPROTO_UDP;
  279                         fi.fin_data[0] = port;
  280                         fi.fin_data[1] = 0;
  281                         fi.fin_dp = (char *)&udp;
  282 
  283                         nat2 = nat_new(&fi, nat->nat_ptr, NULL,
  284                                        NAT_SLAVE|IPN_UDP|SI_W_DPORT,
  285                                        NAT_OUTBOUND);
  286                         if (nat2 != NULL) {
  287                                 (void) nat_proto(&fi, nat2, IPN_UDP);
  288                                 nat_update(&fi, nat2, nat2->nat_ptr);
  289 
  290                                 nat2->nat_ptr->in_hits++;
  291 #ifdef  IPFILTER_LOG
  292                                 nat_log(nat2, (u_int)(nat->nat_ptr->in_redir));
  293 #endif
  294                                 bcopy((caddr_t)&ip->ip_src.s_addr,
  295                                       data + off, 4);
  296                                 bcopy((caddr_t)&nat2->nat_outport,
  297                                       data + off + 4, 2);
  298                         }
  299                 }
  300         }
  301         return 0;
  302 }

Cache object: 2c3680a99829d727040e79732241255b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.