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

Cache object: 2d1748819cb53e4d1ff5e40e597b0ced


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