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_irc_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_irc_pxy.c,v 1.1.1.1.2.1 2004/08/13 03:55:28 jmc Exp $       */
    2 
    3 /*
    4  * Copyright (C) 2000-2003 Darren Reed
    5  *
    6  * See the IPFILTER.LICENCE file for details on licencing.
    7  *
    8  * Id: ip_irc_pxy.c,v 2.39.2.2 2004/05/24 14:01:48 darrenr Exp
    9  */
   10 
   11 #define IPF_IRC_PROXY
   12 
   13 #define IPF_IRCBUFSZ    96      /* This *MUST* be >= 64! */
   14 
   15 
   16 int ippr_irc_init __P((void));
   17 void ippr_irc_fini __P((void));
   18 int ippr_irc_new __P((fr_info_t *, ap_session_t *, nat_t *));
   19 int ippr_irc_out __P((fr_info_t *, ap_session_t *, nat_t *));
   20 int ippr_irc_send __P((fr_info_t *, nat_t *));
   21 int ippr_irc_complete __P((ircinfo_t *, char *, size_t));
   22 u_short ipf_irc_atoi __P((char **));
   23 
   24 static  frentry_t       ircnatfr;
   25 
   26 int     irc_proxy_init = 0;
   27 
   28 
   29 /*
   30  * Initialize local structures.
   31  */
   32 int ippr_irc_init()
   33 {
   34         bzero((char *)&ircnatfr, sizeof(ircnatfr));
   35         ircnatfr.fr_ref = 1;
   36         ircnatfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
   37         MUTEX_INIT(&ircnatfr.fr_lock, "IRC proxy rule lock");
   38         irc_proxy_init = 1;
   39 
   40         return 0;
   41 }
   42 
   43 
   44 void ippr_irc_fini()
   45 {
   46         if (irc_proxy_init == 1) {
   47                 MUTEX_DESTROY(&ircnatfr.fr_lock);
   48                 irc_proxy_init = 0;
   49         }
   50 }
   51 
   52 
   53 char *ippr_irc_dcctypes[] = {
   54         "CHAT ",        /* CHAT chat ipnumber portnumber */
   55         "SEND ",        /* SEND filename ipnumber portnumber */
   56         "MOVE ",
   57         "TSEND ",
   58         "SCHAT ",
   59         NULL,
   60 };
   61 
   62 
   63 /*
   64  * :A PRIVMSG B :^ADCC CHAT chat 0 0^A\r\n
   65  * PRIVMSG B ^ADCC CHAT chat 0 0^A\r\n
   66  */
   67 
   68 
   69 int ippr_irc_complete(ircp, buf, len)
   70 ircinfo_t *ircp;
   71 char *buf;
   72 size_t len;
   73 {
   74         register char *s, c;
   75         register size_t i;
   76         u_32_t l;
   77         int j, k;
   78 
   79         ircp->irc_ipnum = 0;
   80         ircp->irc_port = 0;
   81 
   82         if (len < 31)
   83                 return 0;
   84         s = buf;
   85         c = *s++;
   86         i = len - 1;
   87 
   88         if ((c != ':') && (c != 'P'))
   89                 return 0;
   90 
   91         if (c == ':') {
   92                 /*
   93                  * Loosely check that the source is a nickname of some sort
   94                  */
   95                 s++;
   96                 c = *s;
   97                 ircp->irc_snick = s;
   98                 if (!isalpha(c))
   99                         return 0;
  100                 i--;
  101                 for (c = *s; !isspace(c) && (i > 0); i--)
  102                         c = *s++;
  103                 if (i < 31)
  104                         return 0;
  105                 if (c != 'P')
  106                         return 0;
  107         } else
  108                 ircp->irc_snick = NULL;
  109 
  110         /*
  111          * Check command string
  112          */
  113         if (strncmp(s, "PRIVMSG ", 8))
  114                 return 0;
  115         i -= 8;
  116         s += 8;
  117         c = *s;
  118         ircp->irc_dnick = s;
  119 
  120         /*
  121          * Loosely check that the destination is a nickname of some sort
  122          */
  123         if (!isalpha(c))
  124                 return 0;
  125         for (; !isspace(c) && (i > 0); i--)
  126                 c = *s++;
  127         if (i < 20)
  128                 return 0;
  129         s++,
  130         i--;
  131 
  132         /*
  133          * Look for a ^A to start the DCC
  134          */
  135         c = *s;
  136         if (c == ':') {
  137                 s++;
  138                 c = *s;
  139         }
  140 
  141         if (strncmp(s, "\001DCC ", 4))
  142                 return 0;
  143 
  144         i -= 4;
  145         s += 4;
  146 
  147         /*
  148          * Check for a recognised DCC command
  149          */
  150         for (j = 0, k = 0; ippr_irc_dcctypes[j]; j++) {
  151                 k = MIN(strlen(ippr_irc_dcctypes[j]), i);
  152                 if (!strncmp(ippr_irc_dcctypes[j], s, k))
  153                         break;
  154         }
  155         if (!ippr_irc_dcctypes[j])
  156                 return 0;
  157 
  158         ircp->irc_type = s;
  159         i -= k;
  160         s += k;
  161 
  162         if (i < 11)
  163                 return 0;
  164 
  165         /*
  166          * Check for the arg
  167          */
  168         c = *s;
  169         if (isspace(c))
  170                 return 0;
  171         ircp->irc_arg = s;
  172         for (; (c != ' ') && (c != '\001') && (i > 0); i--)
  173                 c = *s++;
  174 
  175         if (c == '\001')        /* In reality a ^A can quote another ^A...*/
  176                 return 0;
  177 
  178         if (i < 5)
  179                 return 0;
  180 
  181         s++;
  182         i--;
  183         c = *s;
  184         if (!isdigit(c))
  185                 return 0;
  186         ircp->irc_addr = s;
  187         /*
  188          * Get the IP#
  189          */
  190         for (l = 0; isdigit(c) && (i > 0); i--) {
  191                 l *= 10;
  192                 l += c - '';
  193                 c = *s++;
  194         }
  195 
  196         if (i < 4)
  197                 return 0;
  198 
  199         if (c != ' ')
  200                 return 0;
  201 
  202         ircp->irc_ipnum = l;
  203         s++;
  204         i--;
  205         c = *s;
  206         if (!isdigit(c))
  207                 return 0;
  208         /*
  209          * Get the port#
  210          */
  211         for (l = 0; isdigit(c) && (i > 0); i--) {
  212                 l *= 10;
  213                 l += c - '';
  214                 c = *s++;
  215         }
  216         if (i < 3)
  217                 return 0;
  218         if (strncmp(s, "\001\r\n", 3))
  219                 return 0;
  220         s += 3;
  221         ircp->irc_len = s - buf;
  222         ircp->irc_port = l;
  223         return 1;
  224 }
  225 
  226 
  227 int ippr_irc_new(fin, aps, nat)
  228 fr_info_t *fin;
  229 ap_session_t *aps;
  230 nat_t *nat;
  231 {
  232         ircinfo_t *irc;
  233 
  234         KMALLOC(irc, ircinfo_t *);
  235         if (irc == NULL)
  236                 return -1;
  237 
  238         fin = fin;      /* LINT */
  239         nat = nat;      /* LINT */
  240 
  241         aps->aps_data = irc;
  242         aps->aps_psiz = sizeof(ircinfo_t);
  243 
  244         bzero((char *)irc, sizeof(*irc));
  245         return 0;
  246 }
  247 
  248 
  249 int ippr_irc_send(fin, nat)
  250 fr_info_t *fin;
  251 nat_t *nat;
  252 {
  253         char ctcpbuf[IPF_IRCBUFSZ], newbuf[IPF_IRCBUFSZ];
  254         tcphdr_t *tcp, tcph, *tcp2 = &tcph;
  255         int off, inc = 0, i, dlen;
  256         size_t nlen = 0, olen;
  257         struct in_addr swip;
  258         u_short a5, sp;
  259         ircinfo_t *irc;
  260         fr_info_t fi;
  261         nat_t *nat2;
  262         u_int a1;
  263         ip_t *ip;
  264         mb_t *m;
  265 #ifdef  MENTAT
  266         mb_t *m1;
  267 #endif
  268 
  269         m = fin->fin_m;
  270         ip = fin->fin_ip;
  271         tcp = (tcphdr_t *)fin->fin_dp;
  272         bzero(ctcpbuf, sizeof(ctcpbuf));
  273         off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
  274 
  275 #ifdef __sgi
  276         dlen = fin->fin_plen - off;
  277 #else
  278         dlen = MSGDSIZE(m) - off;
  279 #endif
  280         if (dlen <= 0)
  281                 return 0;
  282         COPYDATA(m, off, MIN(sizeof(ctcpbuf), dlen), ctcpbuf);
  283 
  284         if (dlen <= 0)
  285                 return 0;
  286         ctcpbuf[sizeof(ctcpbuf) - 1] = '\0';
  287         *newbuf = '\0';
  288 
  289         irc = nat->nat_aps->aps_data;
  290         if (ippr_irc_complete(irc, ctcpbuf, dlen) == 0)
  291                 return 0;
  292 
  293         /*
  294          * check that IP address in the PORT/PASV reply is the same as the
  295          * sender of the command - prevents using PORT for port scanning.
  296          */
  297         if (irc->irc_ipnum != ntohl(nat->nat_inip.s_addr))
  298                 return 0;
  299 
  300         a5 = irc->irc_port;
  301 
  302         /*
  303          * Calculate new address parts for the DCC command
  304          */
  305         a1 = ntohl(ip->ip_src.s_addr);
  306         olen = irc->irc_len;
  307         i = irc->irc_addr - ctcpbuf;
  308         i++;
  309         (void) strncpy(newbuf, ctcpbuf, i);
  310         /* DO NOT change these! */
  311 #if defined(SNPRINTF) && defined(KERNEL)
  312         SNPRINTF(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5);
  313 #else
  314         (void) sprintf(newbuf, "%u %u\001\r\n", a1, a5);
  315 #endif
  316 
  317         nlen = strlen(newbuf);
  318         inc = nlen - olen;
  319 
  320         if ((inc + ip->ip_len) > 65535)
  321                 return 0;
  322 
  323 #ifdef  MENTAT
  324         for (m1 = m; m1->b_cont; m1 = m1->b_cont)
  325                 ;
  326         if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
  327                 mblk_t *nm;
  328 
  329                 /* alloc enough to keep same trailer space for lower driver */
  330                 nm = allocb(nlen, BPRI_MED);
  331                 PANIC((!nm),("ippr_irc_out: allocb failed"));
  332 
  333                 nm->b_band = m1->b_band;
  334                 nm->b_wptr += nlen;
  335 
  336                 m1->b_wptr -= olen;
  337                 PANIC((m1->b_wptr < m1->b_rptr),
  338                       ("ippr_irc_out: cannot handle fragmented data block"));
  339 
  340                 linkb(m1, nm);
  341         } else {
  342 # if SOLARIS && defined(ICK_VALID)
  343                 if (m1->b_datap->db_struiolim == m1->b_wptr)
  344                         m1->b_datap->db_struiolim += inc;
  345                 m1->b_datap->db_struioflag &= ~STRUIO_IP;
  346 # endif
  347                 m1->b_wptr += inc;
  348         }
  349 #else
  350         if (inc < 0)
  351                 m_adj(m, inc);
  352         /* the mbuf chain will be extended if necessary by m_copyback() */
  353 #endif
  354         COPYBACK(m, off, nlen, newbuf);
  355 
  356         if (inc != 0) {
  357 #if defined(MENTAT) || defined(__sgi)
  358                 register u_32_t sum1, sum2;
  359 
  360                 sum1 = ip->ip_len;
  361                 sum2 = ip->ip_len + inc;
  362 
  363                 /* Because ~1 == -2, We really need ~1 == -1 */
  364                 if (sum1 > sum2)
  365                         sum2--;
  366                 sum2 -= sum1;
  367                 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
  368 
  369                 fix_outcksum(fin, &ip->ip_sum, sum2);
  370 #endif
  371                 ip->ip_len += inc;
  372         }
  373 
  374         /*
  375          * Add skeleton NAT entry for connection which will come back the
  376          * other way.
  377          */
  378         sp = htons(a5);
  379         /*
  380          * Don't allow the PORT command to specify a port < 1024 due to
  381          * security crap.
  382          */
  383         if (ntohs(sp) < 1024)
  384                 return 0;
  385 
  386         /*
  387          * The server may not make the connection back from port 20, but
  388          * it is the most likely so use it here to check for a conflicting
  389          * mapping.
  390          */
  391         bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
  392         fi.fin_data[0] = sp;
  393         fi.fin_data[1] = fin->fin_data[1];
  394         nat2 = nat_outlookup(fin, IPN_TCP, nat->nat_p, nat->nat_inip,
  395                              ip->ip_dst);
  396         if (nat2 == NULL) {
  397                 bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
  398                 bzero((char *)tcp2, sizeof(*tcp2));
  399                 tcp2->th_win = htons(8192);
  400                 tcp2->th_sport = sp;
  401                 tcp2->th_dport = 0; /* XXX - don't specify remote port */
  402                 fi.fin_data[0] = ntohs(sp);
  403                 fi.fin_data[1] = 0;
  404                 fi.fin_dp = (char *)tcp2;
  405                 fi.fin_fr = &ircnatfr;
  406                 fi.fin_dlen = sizeof(*tcp2);
  407                 fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
  408                 swip = ip->ip_src;
  409                 ip->ip_src = nat->nat_inip;
  410                 nat2 = nat_new(&fi, nat->nat_ptr, NULL,
  411                                NAT_SLAVE|IPN_TCP|SI_W_DPORT, NAT_OUTBOUND);
  412                 if (nat2 != NULL) {
  413                         (void) nat_proto(&fi, nat2, 0);
  414                         nat_update(&fi, nat2, nat2->nat_ptr);
  415 
  416                         (void) fr_addstate(&fi, NULL, SI_W_DPORT);
  417                 }
  418                 ip->ip_src = swip;
  419         }
  420         return inc;
  421 }
  422 
  423 
  424 int ippr_irc_out(fin, aps, nat)
  425 fr_info_t *fin;
  426 ap_session_t *aps;
  427 nat_t *nat;
  428 {
  429         aps = aps;      /* LINT */
  430         return ippr_irc_send(fin, nat);
  431 }

Cache object: ce90e1ac21aba0cf08ae9f99a61a33ca


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