17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (C) 2000-2003 Darren Reed
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate *
6ab25eeb5Syz * $Id: ip_irc_pxy.c,v 2.39.2.4 2005/02/04 10:22:55 darrenr Exp $
77c478bd9Sstevel@tonic-gate *
8*33f2fefdSDarren Reed * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
97c478bd9Sstevel@tonic-gate * Use is subject to license terms.
107c478bd9Sstevel@tonic-gate */
117c478bd9Sstevel@tonic-gate
127c478bd9Sstevel@tonic-gate #define IPF_IRC_PROXY
137c478bd9Sstevel@tonic-gate
147c478bd9Sstevel@tonic-gate #define IPF_IRCBUFSZ 96 /* This *MUST* be >= 64! */
157c478bd9Sstevel@tonic-gate
16f4b3ec61Sdh typedef struct ifs_ircpxy {
17f4b3ec61Sdh frentry_t ircnatfr;
18f4b3ec61Sdh int irc_proxy_init;
19f4b3ec61Sdh } ifs_ircpxy_t;
207c478bd9Sstevel@tonic-gate
21f4b3ec61Sdh
22f4b3ec61Sdh int ippr_irc_init __P((void **, ipf_stack_t *));
23f4b3ec61Sdh void ippr_irc_fini __P((void **, ipf_stack_t *));
24f4b3ec61Sdh int ippr_irc_new __P((fr_info_t *, ap_session_t *, nat_t *, void *));
25f4b3ec61Sdh int ippr_irc_out __P((fr_info_t *, ap_session_t *, nat_t *, void *));
26f4b3ec61Sdh int ippr_irc_send __P((fr_info_t *, nat_t *, ifs_ircpxy_t *));
277c478bd9Sstevel@tonic-gate int ippr_irc_complete __P((ircinfo_t *, char *, size_t));
287c478bd9Sstevel@tonic-gate u_short ipf_irc_atoi __P((char **));
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate * Initialize local structures.
327c478bd9Sstevel@tonic-gate */
33f4b3ec61Sdh /*ARGSUSED*/
ippr_irc_init(private,ifs)34f4b3ec61Sdh int ippr_irc_init(private, ifs)
35f4b3ec61Sdh void **private;
36f4b3ec61Sdh ipf_stack_t *ifs;
377c478bd9Sstevel@tonic-gate {
38f4b3ec61Sdh ifs_ircpxy_t *ifsirc;
39f4b3ec61Sdh
40f4b3ec61Sdh KMALLOC(ifsirc, ifs_ircpxy_t *);
41f4b3ec61Sdh if (ifsirc == NULL)
42f4b3ec61Sdh return -1;
43f4b3ec61Sdh
44f4b3ec61Sdh bzero((char *)&ifsirc->ircnatfr, sizeof(ifsirc->ircnatfr));
45f4b3ec61Sdh ifsirc->ircnatfr.fr_ref = 1;
46f4b3ec61Sdh ifsirc->ircnatfr.fr_flags = FR_INQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
47f4b3ec61Sdh MUTEX_INIT(&ifsirc->ircnatfr.fr_lock, "IRC proxy rule lock");
48f4b3ec61Sdh ifsirc->irc_proxy_init = 1;
49f4b3ec61Sdh
50f4b3ec61Sdh *private = (void *)ifsirc;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate return 0;
537c478bd9Sstevel@tonic-gate }
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate
56f4b3ec61Sdh /*ARGSUSED*/
ippr_irc_fini(private,ifs)57f4b3ec61Sdh void ippr_irc_fini(private, ifs)
58f4b3ec61Sdh void **private;
59f4b3ec61Sdh ipf_stack_t *ifs;
607c478bd9Sstevel@tonic-gate {
61f4b3ec61Sdh ifs_ircpxy_t *ifsirc = *((ifs_ircpxy_t **)private);
62f4b3ec61Sdh
63f4b3ec61Sdh if (ifsirc->irc_proxy_init == 1) {
64f4b3ec61Sdh MUTEX_DESTROY(&ifsirc->ircnatfr.fr_lock);
65f4b3ec61Sdh ifsirc->irc_proxy_init = 0;
667c478bd9Sstevel@tonic-gate }
67f4b3ec61Sdh
68f4b3ec61Sdh KFREE(ifsirc);
69f4b3ec61Sdh *private = NULL;
707c478bd9Sstevel@tonic-gate }
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate
73f4b3ec61Sdh static char *ippr_irc_dcctypes[] = {
747c478bd9Sstevel@tonic-gate "CHAT ", /* CHAT chat ipnumber portnumber */
757c478bd9Sstevel@tonic-gate "SEND ", /* SEND filename ipnumber portnumber */
767c478bd9Sstevel@tonic-gate "MOVE ",
777c478bd9Sstevel@tonic-gate "TSEND ",
787c478bd9Sstevel@tonic-gate "SCHAT ",
797c478bd9Sstevel@tonic-gate NULL,
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate * :A PRIVMSG B :^ADCC CHAT chat 0 0^A\r\n
857c478bd9Sstevel@tonic-gate * PRIVMSG B ^ADCC CHAT chat 0 0^A\r\n
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate
ippr_irc_complete(ircp,buf,len)897c478bd9Sstevel@tonic-gate int ippr_irc_complete(ircp, buf, len)
907c478bd9Sstevel@tonic-gate ircinfo_t *ircp;
917c478bd9Sstevel@tonic-gate char *buf;
927c478bd9Sstevel@tonic-gate size_t len;
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate register char *s, c;
957c478bd9Sstevel@tonic-gate register size_t i;
967c478bd9Sstevel@tonic-gate u_32_t l;
977c478bd9Sstevel@tonic-gate int j, k;
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate ircp->irc_ipnum = 0;
1007c478bd9Sstevel@tonic-gate ircp->irc_port = 0;
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate if (len < 31)
1037c478bd9Sstevel@tonic-gate return 0;
1047c478bd9Sstevel@tonic-gate s = buf;
1057c478bd9Sstevel@tonic-gate c = *s++;
1067c478bd9Sstevel@tonic-gate i = len - 1;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate if ((c != ':') && (c != 'P'))
1097c478bd9Sstevel@tonic-gate return 0;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate if (c == ':') {
1127c478bd9Sstevel@tonic-gate /*
1137c478bd9Sstevel@tonic-gate * Loosely check that the source is a nickname of some sort
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate s++;
1167c478bd9Sstevel@tonic-gate c = *s;
1177c478bd9Sstevel@tonic-gate ircp->irc_snick = s;
118ab25eeb5Syz if (!ISALPHA(c))
1197c478bd9Sstevel@tonic-gate return 0;
1207c478bd9Sstevel@tonic-gate i--;
121ab25eeb5Syz for (c = *s; !ISSPACE(c) && (i > 0); i--)
1227c478bd9Sstevel@tonic-gate c = *s++;
1237c478bd9Sstevel@tonic-gate if (i < 31)
1247c478bd9Sstevel@tonic-gate return 0;
1257c478bd9Sstevel@tonic-gate if (c != 'P')
1267c478bd9Sstevel@tonic-gate return 0;
1277c478bd9Sstevel@tonic-gate } else
1287c478bd9Sstevel@tonic-gate ircp->irc_snick = NULL;
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate * Check command string
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate if (strncmp(s, "PRIVMSG ", 8))
1347c478bd9Sstevel@tonic-gate return 0;
1357c478bd9Sstevel@tonic-gate i -= 8;
1367c478bd9Sstevel@tonic-gate s += 8;
1377c478bd9Sstevel@tonic-gate c = *s;
1387c478bd9Sstevel@tonic-gate ircp->irc_dnick = s;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * Loosely check that the destination is a nickname of some sort
1427c478bd9Sstevel@tonic-gate */
143ab25eeb5Syz if (!ISALPHA(c))
1447c478bd9Sstevel@tonic-gate return 0;
145ab25eeb5Syz for (; !ISSPACE(c) && (i > 0); i--)
1467c478bd9Sstevel@tonic-gate c = *s++;
1477c478bd9Sstevel@tonic-gate if (i < 20)
1487c478bd9Sstevel@tonic-gate return 0;
1497c478bd9Sstevel@tonic-gate s++,
1507c478bd9Sstevel@tonic-gate i--;
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * Look for a ^A to start the DCC
1547c478bd9Sstevel@tonic-gate */
1557c478bd9Sstevel@tonic-gate c = *s;
1567c478bd9Sstevel@tonic-gate if (c == ':') {
1577c478bd9Sstevel@tonic-gate s++;
1587c478bd9Sstevel@tonic-gate c = *s;
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate if (strncmp(s, "\001DCC ", 4))
1627c478bd9Sstevel@tonic-gate return 0;
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate i -= 4;
1657c478bd9Sstevel@tonic-gate s += 4;
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate /*
1687c478bd9Sstevel@tonic-gate * Check for a recognised DCC command
1697c478bd9Sstevel@tonic-gate */
1707c478bd9Sstevel@tonic-gate for (j = 0, k = 0; ippr_irc_dcctypes[j]; j++) {
1717c478bd9Sstevel@tonic-gate k = MIN(strlen(ippr_irc_dcctypes[j]), i);
1727c478bd9Sstevel@tonic-gate if (!strncmp(ippr_irc_dcctypes[j], s, k))
1737c478bd9Sstevel@tonic-gate break;
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate if (!ippr_irc_dcctypes[j])
1767c478bd9Sstevel@tonic-gate return 0;
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate ircp->irc_type = s;
1797c478bd9Sstevel@tonic-gate i -= k;
1807c478bd9Sstevel@tonic-gate s += k;
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate if (i < 11)
1837c478bd9Sstevel@tonic-gate return 0;
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * Check for the arg
1877c478bd9Sstevel@tonic-gate */
1887c478bd9Sstevel@tonic-gate c = *s;
189ab25eeb5Syz if (ISSPACE(c))
1907c478bd9Sstevel@tonic-gate return 0;
1917c478bd9Sstevel@tonic-gate ircp->irc_arg = s;
1927c478bd9Sstevel@tonic-gate for (; (c != ' ') && (c != '\001') && (i > 0); i--)
1937c478bd9Sstevel@tonic-gate c = *s++;
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate if (c == '\001') /* In reality a ^A can quote another ^A...*/
1967c478bd9Sstevel@tonic-gate return 0;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate if (i < 5)
1997c478bd9Sstevel@tonic-gate return 0;
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate s++;
2027c478bd9Sstevel@tonic-gate i--;
2037c478bd9Sstevel@tonic-gate c = *s;
204ab25eeb5Syz if (!ISDIGIT(c))
2057c478bd9Sstevel@tonic-gate return 0;
2067c478bd9Sstevel@tonic-gate ircp->irc_addr = s;
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate * Get the IP#
2097c478bd9Sstevel@tonic-gate */
210ab25eeb5Syz for (l = 0; ISDIGIT(c) && (i > 0); i--) {
2117c478bd9Sstevel@tonic-gate l *= 10;
2127c478bd9Sstevel@tonic-gate l += c - '0';
2137c478bd9Sstevel@tonic-gate c = *s++;
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate if (i < 4)
2177c478bd9Sstevel@tonic-gate return 0;
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if (c != ' ')
2207c478bd9Sstevel@tonic-gate return 0;
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate ircp->irc_ipnum = l;
2237c478bd9Sstevel@tonic-gate s++;
2247c478bd9Sstevel@tonic-gate i--;
2257c478bd9Sstevel@tonic-gate c = *s;
226ab25eeb5Syz if (!ISDIGIT(c))
2277c478bd9Sstevel@tonic-gate return 0;
2287c478bd9Sstevel@tonic-gate /*
2297c478bd9Sstevel@tonic-gate * Get the port#
2307c478bd9Sstevel@tonic-gate */
231ab25eeb5Syz for (l = 0; ISDIGIT(c) && (i > 0); i--) {
2327c478bd9Sstevel@tonic-gate l *= 10;
2337c478bd9Sstevel@tonic-gate l += c - '0';
2347c478bd9Sstevel@tonic-gate c = *s++;
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate if (i < 3)
2377c478bd9Sstevel@tonic-gate return 0;
2387c478bd9Sstevel@tonic-gate if (strncmp(s, "\001\r\n", 3))
2397c478bd9Sstevel@tonic-gate return 0;
2407c478bd9Sstevel@tonic-gate s += 3;
2417c478bd9Sstevel@tonic-gate ircp->irc_len = s - buf;
2427c478bd9Sstevel@tonic-gate ircp->irc_port = l;
2437c478bd9Sstevel@tonic-gate return 1;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate
247f4b3ec61Sdh /*ARGSUSED*/
ippr_irc_new(fin,aps,nat,private)248f4b3ec61Sdh int ippr_irc_new(fin, aps, nat, private)
2497c478bd9Sstevel@tonic-gate fr_info_t *fin;
2507c478bd9Sstevel@tonic-gate ap_session_t *aps;
2517c478bd9Sstevel@tonic-gate nat_t *nat;
252f4b3ec61Sdh void *private;
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate ircinfo_t *irc;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate KMALLOC(irc, ircinfo_t *);
2577c478bd9Sstevel@tonic-gate if (irc == NULL)
2587c478bd9Sstevel@tonic-gate return -1;
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate fin = fin; /* LINT */
2617c478bd9Sstevel@tonic-gate nat = nat; /* LINT */
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate aps->aps_data = irc;
2647c478bd9Sstevel@tonic-gate aps->aps_psiz = sizeof(ircinfo_t);
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate bzero((char *)irc, sizeof(*irc));
2677c478bd9Sstevel@tonic-gate return 0;
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate
2707c478bd9Sstevel@tonic-gate
ippr_irc_send(fin,nat,ifsirc)271f4b3ec61Sdh int ippr_irc_send(fin, nat, ifsirc)
2727c478bd9Sstevel@tonic-gate fr_info_t *fin;
2737c478bd9Sstevel@tonic-gate nat_t *nat;
274f4b3ec61Sdh ifs_ircpxy_t *ifsirc;
2757c478bd9Sstevel@tonic-gate {
2767c478bd9Sstevel@tonic-gate char ctcpbuf[IPF_IRCBUFSZ], newbuf[IPF_IRCBUFSZ];
2777c478bd9Sstevel@tonic-gate tcphdr_t *tcp, tcph, *tcp2 = &tcph;
2787c478bd9Sstevel@tonic-gate int off, inc = 0, i, dlen;
2797c478bd9Sstevel@tonic-gate size_t nlen = 0, olen;
2807c478bd9Sstevel@tonic-gate struct in_addr swip;
2817c478bd9Sstevel@tonic-gate u_short a5, sp;
2827c478bd9Sstevel@tonic-gate ircinfo_t *irc;
2837c478bd9Sstevel@tonic-gate fr_info_t fi;
2847c478bd9Sstevel@tonic-gate nat_t *nat2;
2857c478bd9Sstevel@tonic-gate u_int a1;
2867c478bd9Sstevel@tonic-gate ip_t *ip;
2877c478bd9Sstevel@tonic-gate mb_t *m;
2887c478bd9Sstevel@tonic-gate #ifdef MENTAT
2897c478bd9Sstevel@tonic-gate mb_t *m1;
2907c478bd9Sstevel@tonic-gate #endif
2917c478bd9Sstevel@tonic-gate
292ab25eeb5Syz m = fin->fin_m;
2937c478bd9Sstevel@tonic-gate ip = fin->fin_ip;
2947c478bd9Sstevel@tonic-gate tcp = (tcphdr_t *)fin->fin_dp;
2957c478bd9Sstevel@tonic-gate bzero(ctcpbuf, sizeof(ctcpbuf));
296ab25eeb5Syz off = (char *)tcp - (char *)ip + (TCP_OFF(tcp) << 2) + fin->fin_ipoff;
2977c478bd9Sstevel@tonic-gate
298ab25eeb5Syz #ifdef __sgi
299ab25eeb5Syz dlen = fin->fin_plen - off;
300ab25eeb5Syz #else
3017c478bd9Sstevel@tonic-gate dlen = MSGDSIZE(m) - off;
302ab25eeb5Syz #endif
3037c478bd9Sstevel@tonic-gate if (dlen <= 0)
3047c478bd9Sstevel@tonic-gate return 0;
3057c478bd9Sstevel@tonic-gate COPYDATA(m, off, MIN(sizeof(ctcpbuf), dlen), ctcpbuf);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate if (dlen <= 0)
3087c478bd9Sstevel@tonic-gate return 0;
3097c478bd9Sstevel@tonic-gate ctcpbuf[sizeof(ctcpbuf) - 1] = '\0';
3107c478bd9Sstevel@tonic-gate *newbuf = '\0';
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate irc = nat->nat_aps->aps_data;
3137c478bd9Sstevel@tonic-gate if (ippr_irc_complete(irc, ctcpbuf, dlen) == 0)
3147c478bd9Sstevel@tonic-gate return 0;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate * check that IP address in the PORT/PASV reply is the same as the
3187c478bd9Sstevel@tonic-gate * sender of the command - prevents using PORT for port scanning.
3197c478bd9Sstevel@tonic-gate */
3207c478bd9Sstevel@tonic-gate if (irc->irc_ipnum != ntohl(nat->nat_inip.s_addr))
3217c478bd9Sstevel@tonic-gate return 0;
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate a5 = irc->irc_port;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * Calculate new address parts for the DCC command
3277c478bd9Sstevel@tonic-gate */
3287c478bd9Sstevel@tonic-gate a1 = ntohl(ip->ip_src.s_addr);
3297c478bd9Sstevel@tonic-gate olen = irc->irc_len;
3307c478bd9Sstevel@tonic-gate i = irc->irc_addr - ctcpbuf;
3317c478bd9Sstevel@tonic-gate i++;
3327c478bd9Sstevel@tonic-gate (void) strncpy(newbuf, ctcpbuf, i);
3337c478bd9Sstevel@tonic-gate /* DO NOT change these! */
334ab25eeb5Syz #if defined(SNPRINTF) && defined(KERNEL)
335ab25eeb5Syz (void) SNPRINTF(newbuf, sizeof(newbuf) - i, "%u %u\001\r\n", a1, a5);
3367c478bd9Sstevel@tonic-gate #else
3377c478bd9Sstevel@tonic-gate (void) sprintf(newbuf, "%u %u\001\r\n", a1, a5);
3387c478bd9Sstevel@tonic-gate #endif
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate nlen = strlen(newbuf);
3417c478bd9Sstevel@tonic-gate inc = nlen - olen;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate if ((inc + ip->ip_len) > 65535)
3447c478bd9Sstevel@tonic-gate return 0;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate #ifdef MENTAT
3477c478bd9Sstevel@tonic-gate for (m1 = m; m1->b_cont; m1 = m1->b_cont)
3487c478bd9Sstevel@tonic-gate ;
3497c478bd9Sstevel@tonic-gate if ((inc > 0) && (m1->b_datap->db_lim - m1->b_wptr < inc)) {
3507c478bd9Sstevel@tonic-gate mblk_t *nm;
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /* alloc enough to keep same trailer space for lower driver */
3537c478bd9Sstevel@tonic-gate nm = allocb(nlen, BPRI_MED);
3547c478bd9Sstevel@tonic-gate PANIC((!nm),("ippr_irc_out: allocb failed"));
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate nm->b_band = m1->b_band;
3577c478bd9Sstevel@tonic-gate nm->b_wptr += nlen;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate m1->b_wptr -= olen;
3607c478bd9Sstevel@tonic-gate PANIC((m1->b_wptr < m1->b_rptr),
3617c478bd9Sstevel@tonic-gate ("ippr_irc_out: cannot handle fragmented data block"));
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate linkb(m1, nm);
3647c478bd9Sstevel@tonic-gate } else {
3657c478bd9Sstevel@tonic-gate # if SOLARIS && defined(ICK_VALID)
3667c478bd9Sstevel@tonic-gate if (m1->b_datap->db_struiolim == m1->b_wptr)
3677c478bd9Sstevel@tonic-gate m1->b_datap->db_struiolim += inc;
3687c478bd9Sstevel@tonic-gate m1->b_datap->db_struioflag &= ~STRUIO_IP;
3697c478bd9Sstevel@tonic-gate # endif
3707c478bd9Sstevel@tonic-gate m1->b_wptr += inc;
3717c478bd9Sstevel@tonic-gate }
3727c478bd9Sstevel@tonic-gate #else
3737c478bd9Sstevel@tonic-gate if (inc < 0)
3747c478bd9Sstevel@tonic-gate m_adj(m, inc);
3757c478bd9Sstevel@tonic-gate /* the mbuf chain will be extended if necessary by m_copyback() */
3767c478bd9Sstevel@tonic-gate #endif
3777c478bd9Sstevel@tonic-gate COPYBACK(m, off, nlen, newbuf);
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate if (inc != 0) {
3807c478bd9Sstevel@tonic-gate #if defined(MENTAT) || defined(__sgi)
3817c478bd9Sstevel@tonic-gate register u_32_t sum1, sum2;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate sum1 = ip->ip_len;
3847c478bd9Sstevel@tonic-gate sum2 = ip->ip_len + inc;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate /* Because ~1 == -2, We really need ~1 == -1 */
3877c478bd9Sstevel@tonic-gate if (sum1 > sum2)
3887c478bd9Sstevel@tonic-gate sum2--;
3897c478bd9Sstevel@tonic-gate sum2 -= sum1;
3907c478bd9Sstevel@tonic-gate sum2 = (sum2 & 0xffff) + (sum2 >> 16);
3917c478bd9Sstevel@tonic-gate
392381a2a9aSdr fix_outcksum(&ip->ip_sum, sum2);
3937c478bd9Sstevel@tonic-gate #endif
3947c478bd9Sstevel@tonic-gate ip->ip_len += inc;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate * Add skeleton NAT entry for connection which will come back the
3997c478bd9Sstevel@tonic-gate * other way.
4007c478bd9Sstevel@tonic-gate */
4017c478bd9Sstevel@tonic-gate sp = htons(a5);
4027c478bd9Sstevel@tonic-gate /*
4037c478bd9Sstevel@tonic-gate * Don't allow the PORT command to specify a port < 1024 due to
4047c478bd9Sstevel@tonic-gate * security crap.
4057c478bd9Sstevel@tonic-gate */
4067c478bd9Sstevel@tonic-gate if (ntohs(sp) < 1024)
4077c478bd9Sstevel@tonic-gate return 0;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * The server may not make the connection back from port 20, but
4117c478bd9Sstevel@tonic-gate * it is the most likely so use it here to check for a conflicting
4127c478bd9Sstevel@tonic-gate * mapping.
4137c478bd9Sstevel@tonic-gate */
4147c478bd9Sstevel@tonic-gate bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
4157c478bd9Sstevel@tonic-gate fi.fin_data[0] = sp;
4167c478bd9Sstevel@tonic-gate fi.fin_data[1] = fin->fin_data[1];
4177c478bd9Sstevel@tonic-gate nat2 = nat_outlookup(fin, IPN_TCP, nat->nat_p, nat->nat_inip,
4187c478bd9Sstevel@tonic-gate ip->ip_dst);
4197c478bd9Sstevel@tonic-gate if (nat2 == NULL) {
4207c478bd9Sstevel@tonic-gate bcopy((caddr_t)fin, (caddr_t)&fi, sizeof(fi));
4217c478bd9Sstevel@tonic-gate bzero((char *)tcp2, sizeof(*tcp2));
4227c478bd9Sstevel@tonic-gate tcp2->th_win = htons(8192);
4237c478bd9Sstevel@tonic-gate tcp2->th_sport = sp;
4247c478bd9Sstevel@tonic-gate tcp2->th_dport = 0; /* XXX - don't specify remote port */
4257c478bd9Sstevel@tonic-gate fi.fin_data[0] = ntohs(sp);
4267c478bd9Sstevel@tonic-gate fi.fin_data[1] = 0;
4277c478bd9Sstevel@tonic-gate fi.fin_dp = (char *)tcp2;
428f4b3ec61Sdh fi.fin_fr = &ifsirc->ircnatfr;
4297c478bd9Sstevel@tonic-gate fi.fin_dlen = sizeof(*tcp2);
4307c478bd9Sstevel@tonic-gate fi.fin_plen = fi.fin_hlen + sizeof(*tcp2);
4317c478bd9Sstevel@tonic-gate swip = ip->ip_src;
4327c478bd9Sstevel@tonic-gate ip->ip_src = nat->nat_inip;
4337c478bd9Sstevel@tonic-gate nat2 = nat_new(&fi, nat->nat_ptr, NULL,
4347c478bd9Sstevel@tonic-gate NAT_SLAVE|IPN_TCP|SI_W_DPORT, NAT_OUTBOUND);
4357c478bd9Sstevel@tonic-gate if (nat2 != NULL) {
4367c478bd9Sstevel@tonic-gate (void) nat_proto(&fi, nat2, 0);
4377c478bd9Sstevel@tonic-gate nat_update(&fi, nat2, nat2->nat_ptr);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate (void) fr_addstate(&fi, NULL, SI_W_DPORT);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate ip->ip_src = swip;
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate return inc;
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate
ippr_irc_out(fin,aps,nat,private)447f4b3ec61Sdh int ippr_irc_out(fin, aps, nat, private)
4487c478bd9Sstevel@tonic-gate fr_info_t *fin;
4497c478bd9Sstevel@tonic-gate ap_session_t *aps;
4507c478bd9Sstevel@tonic-gate nat_t *nat;
451f4b3ec61Sdh void *private;
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate aps = aps; /* LINT */
454f4b3ec61Sdh return ippr_irc_send(fin, nat, (ifs_ircpxy_t *)private);
4557c478bd9Sstevel@tonic-gate }
456