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/netpfil/ipfilter/netinet/ip_raudio_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 /*      $FreeBSD$       */
    2 
    3 /*
    4  * Copyright (C) 2012 by Darren Reed.
    5  *
    6  * See the IPFILTER.LICENCE file for details on licencing.
    7  *
    8  * $Id: ip_raudio_pxy.c,v 1.40.2.4 2006/07/14 06:12:17 darrenr Exp $
    9  */
   10 
   11 #define IPF_RAUDIO_PROXY
   12 
   13 
   14 void ipf_p_raudio_main_load(void);
   15 void ipf_p_raudio_main_unload(void);
   16 int ipf_p_raudio_new(void *, fr_info_t *, ap_session_t *, nat_t *);
   17 int ipf_p_raudio_in(void *, fr_info_t *, ap_session_t *, nat_t *);
   18 int ipf_p_raudio_out(void *, fr_info_t *, ap_session_t *, nat_t *);
   19 
   20 static  frentry_t       raudiofr;
   21 
   22 int     raudio_proxy_init = 0;
   23 
   24 
   25 /*
   26  * Real Audio application proxy initialization.
   27  */
   28 void
   29 ipf_p_raudio_main_load(void)
   30 {
   31         bzero((char *)&raudiofr, sizeof(raudiofr));
   32         raudiofr.fr_ref = 1;
   33         raudiofr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
   34         MUTEX_INIT(&raudiofr.fr_lock, "Real Audio proxy rule lock");
   35         raudio_proxy_init = 1;
   36 }
   37 
   38 
   39 void
   40 ipf_p_raudio_main_unload(void)
   41 {
   42         if (raudio_proxy_init == 1) {
   43                 MUTEX_DESTROY(&raudiofr.fr_lock);
   44                 raudio_proxy_init = 0;
   45         }
   46 }
   47 
   48 
   49 /*
   50  * Setup for a new proxy to handle Real Audio.
   51  */
   52 int
   53 ipf_p_raudio_new(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat)
   54 {
   55         raudio_t *rap;
   56 
   57         nat = nat;      /* LINT */
   58 
   59         if (fin->fin_v != 4)
   60                 return (-1);
   61 
   62         KMALLOCS(aps->aps_data, void *, sizeof(raudio_t));
   63         if (aps->aps_data == NULL)
   64                 return (-1);
   65 
   66         bzero(aps->aps_data, sizeof(raudio_t));
   67         rap = aps->aps_data;
   68         aps->aps_psiz = sizeof(raudio_t);
   69         rap->rap_mode = RAP_M_TCP;      /* default is for TCP */
   70         return (0);
   71 }
   72 
   73 
   74 
   75 int
   76 ipf_p_raudio_out(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat)
   77 {
   78         raudio_t *rap = aps->aps_data;
   79         unsigned char membuf[512 + 1], *s;
   80         u_short id = 0;
   81         tcphdr_t *tcp;
   82         int off, dlen;
   83         int len = 0;
   84         mb_t *m;
   85 
   86         nat = nat;      /* LINT */
   87 
   88         /*
   89          * If we've already processed the start messages, then nothing left
   90          * for the proxy to do.
   91          */
   92         if (rap->rap_eos == 1)
   93                 return (0);
   94 
   95         m = fin->fin_m;
   96         tcp = (tcphdr_t *)fin->fin_dp;
   97         off = (char *)tcp - (char *)fin->fin_ip;
   98         off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
   99 
  100         dlen = MSGDSIZE(m) - off;
  101         if (dlen <= 0)
  102                 return (0);
  103 
  104         if (dlen > sizeof(membuf))
  105                 dlen = sizeof(membuf);
  106 
  107         bzero((char *)membuf, sizeof(membuf));
  108         COPYDATA(m, off, dlen, (char *)membuf);
  109         /*
  110          * In all the startup parsing, ensure that we don't go outside
  111          * the packet buffer boundary.
  112          */
  113         /*
  114          * Look for the start of connection "PNA" string if not seen yet.
  115          */
  116         if (rap->rap_seenpna == 0) {
  117                 s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen);
  118                 if (s == NULL)
  119                         return (0);
  120                 s += 3;
  121                 rap->rap_seenpna = 1;
  122         } else
  123                 s = membuf;
  124 
  125         /*
  126          * Directly after the PNA will be the version number of this
  127          * connection.
  128          */
  129         if (rap->rap_seenpna == 1 && rap->rap_seenver == 0) {
  130                 if ((s + 1) - membuf < dlen) {
  131                         rap->rap_version = (*s << 8) | *(s + 1);
  132                         s += 2;
  133                         rap->rap_seenver = 1;
  134                 } else
  135                         return (0);
  136         }
  137 
  138         /*
  139          * Now that we've been past the PNA and version number, we're into the
  140          * startup messages block.  This ends when a message with an ID of 0.
  141          */
  142         while ((rap->rap_eos == 0) && ((s + 1) - membuf < dlen)) {
  143                 if (rap->rap_gotid == 0) {
  144                         id = (*s << 8) | *(s + 1);
  145                         s += 2;
  146                         rap->rap_gotid = 1;
  147                         if (id == RA_ID_END) {
  148                                 rap->rap_eos = 1;
  149                                 break;
  150                         }
  151                 } else if (rap->rap_gotlen == 0) {
  152                         len = (*s << 8) | *(s + 1);
  153                         s += 2;
  154                         rap->rap_gotlen = 1;
  155                 }
  156 
  157                 if (rap->rap_gotid == 1 && rap->rap_gotlen == 1) {
  158                         if (id == RA_ID_UDP) {
  159                                 rap->rap_mode &= ~RAP_M_TCP;
  160                                 rap->rap_mode |= RAP_M_UDP;
  161                                 rap->rap_plport = (*s << 8) | *(s + 1);
  162                         } else if (id == RA_ID_ROBUST) {
  163                                 rap->rap_mode |= RAP_M_ROBUST;
  164                                 rap->rap_prport = (*s << 8) | *(s + 1);
  165                         }
  166                         s += len;
  167                         rap->rap_gotlen = 0;
  168                         rap->rap_gotid = 0;
  169                 }
  170         }
  171         return (0);
  172 }
  173 
  174 
  175 int
  176 ipf_p_raudio_in(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat)
  177 {
  178         unsigned char membuf[IPF_MAXPORTLEN + 1], *s;
  179         tcphdr_t *tcp, tcph, *tcp2 = &tcph;
  180         raudio_t *rap = aps->aps_data;
  181         ipf_main_softc_t *softc;
  182         ipf_nat_softc_t *softn;
  183         struct in_addr swa, swb;
  184         int off, dlen, slen;
  185         int a1, a2, a3, a4;
  186         u_short sp, dp;
  187         fr_info_t fi;
  188         tcp_seq seq;
  189         nat_t *nat2;
  190         u_char swp;
  191         ip_t *ip;
  192         mb_t *m;
  193 
  194         softc = fin->fin_main_soft;
  195         softn = softc->ipf_nat_soft;
  196         /*
  197          * Wait until we've seen the end of the start messages and even then
  198          * only proceed further if we're using UDP.  If they want to use TCP
  199          * then data is sent back on the same channel that is already open.
  200          */
  201         if (rap->rap_sdone != 0)
  202                 return (0);
  203 
  204         m = fin->fin_m;
  205         tcp = (tcphdr_t *)fin->fin_dp;
  206         off = (char *)tcp - (char *)fin->fin_ip;
  207         off += (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
  208 
  209         dlen = MSGDSIZE(m) - off;
  210         if (dlen <= 0)
  211                 return (0);
  212 
  213         if (dlen > sizeof(membuf))
  214                 dlen = sizeof(membuf);
  215 
  216         bzero((char *)membuf, sizeof(membuf));
  217         COPYDATA(m, off, dlen, (char *)membuf);
  218 
  219         seq = ntohl(tcp->th_seq);
  220         /*
  221          * Check to see if the data in this packet is of interest to us.
  222          * We only care for the first 19 bytes coming back from the server.
  223          */
  224         if (rap->rap_sseq == 0) {
  225                 s = (u_char *)memstr("PNA", (char *)membuf, 3, dlen);
  226                 if (s == NULL)
  227                         return (0);
  228                 a1 = s - membuf;
  229                 dlen -= a1;
  230                 a1 = 0;
  231                 rap->rap_sseq = seq;
  232                 a2 = MIN(dlen, sizeof(rap->rap_svr));
  233         } else if (seq <= rap->rap_sseq + sizeof(rap->rap_svr)) {
  234                 /*
  235                  * seq # which is the start of data and from that the offset
  236                  * into the buffer array.
  237                  */
  238                 a1 = seq - rap->rap_sseq;
  239                 a2 = MIN(dlen, sizeof(rap->rap_svr));
  240                 a2 -= a1;
  241                 s = membuf;
  242         } else
  243                 return (0);
  244 
  245         for (a3 = a1, a4 = a2; (a4 > 0) && (a3 < 19) && (a3 >= 0); a4--,a3++) {
  246                 rap->rap_sbf |= (1 << a3);
  247                 rap->rap_svr[a3] = *s++;
  248         }
  249 
  250         if ((rap->rap_sbf != 0x7ffff) || (!rap->rap_eos))       /* 19 bits */
  251                 return (0);
  252         rap->rap_sdone = 1;
  253 
  254         s = (u_char *)rap->rap_svr + 11;
  255         if (((*s << 8) | *(s + 1)) == RA_ID_ROBUST) {
  256                 s += 2;
  257                 rap->rap_srport = (*s << 8) | *(s + 1);
  258         }
  259 
  260         ip = fin->fin_ip;
  261         swp = ip->ip_p;
  262         swa = ip->ip_src;
  263         swb = ip->ip_dst;
  264 
  265         ip->ip_p = IPPROTO_UDP;
  266         ip->ip_src = nat->nat_ndstip;
  267         ip->ip_dst = nat->nat_odstip;
  268 
  269         bcopy((char *)fin, (char *)&fi, sizeof(fi));
  270         bzero((char *)tcp2, sizeof(*tcp2));
  271         TCP_OFF_A(tcp2, 5);
  272         fi.fin_flx |= FI_IGNORE;
  273         fi.fin_dp = (char *)tcp2;
  274         fi.fin_fr = &raudiofr;
  275         fi.fin_dlen = sizeof(*tcp2);
  276         fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
  277         tcp2->th_win = htons(8192);
  278         slen = ip->ip_len;
  279         ip->ip_len = htons(fin->fin_hlen + sizeof(*tcp));
  280 
  281         if (((rap->rap_mode & RAP_M_UDP_ROBUST) == RAP_M_UDP_ROBUST) &&
  282             (rap->rap_srport != 0)) {
  283                 dp = rap->rap_srport;
  284                 sp = rap->rap_prport;
  285                 tcp2->th_sport = htons(sp);
  286                 tcp2->th_dport = htons(dp);
  287                 fi.fin_data[0] = dp;
  288                 fi.fin_data[1] = sp;
  289                 fi.fin_out = 0;
  290                 MUTEX_ENTER(&softn->ipf_nat_new);
  291                 nat2 = ipf_nat_add(&fi, nat->nat_ptr, NULL,
  292                                NAT_SLAVE|IPN_UDP | (sp ? 0 : SI_W_SPORT),
  293                                NAT_OUTBOUND);
  294                 MUTEX_EXIT(&softn->ipf_nat_new);
  295                 if (nat2 != NULL) {
  296                         (void) ipf_nat_proto(&fi, nat2, IPN_UDP);
  297                         MUTEX_ENTER(&nat2->nat_lock);
  298                         ipf_nat_update(&fi, nat2);
  299                         MUTEX_EXIT(&nat2->nat_lock);
  300 
  301                         (void) ipf_state_add(softc, &fi, NULL,
  302                                              (sp ? 0 : SI_W_SPORT));
  303                 }
  304         }
  305 
  306         if ((rap->rap_mode & RAP_M_UDP) == RAP_M_UDP) {
  307                 sp = rap->rap_plport;
  308                 tcp2->th_sport = htons(sp);
  309                 tcp2->th_dport = 0; /* XXX - don't specify remote port */
  310                 fi.fin_data[0] = sp;
  311                 fi.fin_data[1] = 0;
  312                 fi.fin_out = 1;
  313                 MUTEX_ENTER(&softn->ipf_nat_new);
  314                 nat2 = ipf_nat_add(&fi, nat->nat_ptr, NULL,
  315                                NAT_SLAVE|IPN_UDP|SI_W_DPORT,
  316                                NAT_OUTBOUND);
  317                 MUTEX_EXIT(&softn->ipf_nat_new);
  318                 if (nat2 != NULL) {
  319                         (void) ipf_nat_proto(&fi, nat2, IPN_UDP);
  320                         MUTEX_ENTER(&nat2->nat_lock);
  321                         ipf_nat_update(&fi, nat2);
  322                         MUTEX_EXIT(&nat2->nat_lock);
  323 
  324                         (void) ipf_state_add(softc, &fi, NULL, SI_W_DPORT);
  325                 }
  326         }
  327 
  328         ip->ip_p = swp;
  329         ip->ip_len = slen;
  330         ip->ip_src = swa;
  331         ip->ip_dst = swb;
  332         return (0);
  333 }

Cache object: 4f4a82aa266ccb0b1ce66bf8f9e249b7


[ 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.