Commit f0cbd3ec9f4a3de1a9ef94deda09704543889f44

Authored by bellard
1 parent 7c1f25b4

initial user mode network support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 22 of 37 files are displayed.

slirp/bootp.c 0 → 100644
  1 +/*
  2 + * QEMU BOOTP/DHCP server
  3 + *
  4 + * Copyright (c) 2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include <slirp.h>
  25 +
  26 +/* XXX: only DHCP is supported */
  27 +
  28 +#define NB_ADDR 16
  29 +
  30 +#define START_ADDR 15
  31 +
  32 +#define LEASE_TIME (24 * 3600)
  33 +
  34 +typedef struct {
  35 + uint8_t allocated;
  36 +} BOOTPClient;
  37 +
  38 +BOOTPClient bootp_clients[NB_ADDR];
  39 +
  40 +static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
  41 +
  42 +#ifdef DEBUG
  43 +#define dprintf(fmt, args...) \
  44 +if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
  45 +#else
  46 +#define dprintf(fmt, args...)
  47 +#endif
  48 +
  49 +static BOOTPClient *get_new_addr(struct in_addr *paddr)
  50 +{
  51 + BOOTPClient *bc;
  52 + int i;
  53 +
  54 + for(i = 0; i < NB_ADDR; i++) {
  55 + if (!bootp_clients[i].allocated)
  56 + goto found;
  57 + }
  58 + return NULL;
  59 + found:
  60 + bc = &bootp_clients[i];
  61 + bc->allocated = 1;
  62 + paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
  63 + return bc;
  64 +}
  65 +
  66 +static void dhcp_decode(const uint8_t *buf, int size,
  67 + int *pmsg_type)
  68 +{
  69 + const uint8_t *p, *p_end;
  70 + int len, tag;
  71 +
  72 + *pmsg_type = 0;
  73 +
  74 + p = buf;
  75 + p_end = buf + size;
  76 + if (size < 5)
  77 + return;
  78 + if (memcmp(p, rfc1533_cookie, 4) != 0)
  79 + return;
  80 + p += 4;
  81 + while (p < p_end) {
  82 + tag = p[0];
  83 + if (tag == RFC1533_PAD) {
  84 + p++;
  85 + } else if (tag == RFC1533_END) {
  86 + break;
  87 + } else {
  88 + p++;
  89 + if (p >= p_end)
  90 + break;
  91 + len = *p++;
  92 + dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
  93 +
  94 + switch(tag) {
  95 + case RFC2132_MSG_TYPE:
  96 + if (len >= 1)
  97 + *pmsg_type = p[0];
  98 + break;
  99 + default:
  100 + break;
  101 + }
  102 + p += len;
  103 + }
  104 + }
  105 +}
  106 +
  107 +static void bootp_reply(struct bootp_t *bp)
  108 +{
  109 + BOOTPClient *bc;
  110 + struct mbuf *m;
  111 + struct bootp_t *rbp;
  112 + struct sockaddr_in saddr, daddr;
  113 + struct in_addr dns_addr;
  114 + int dhcp_msg_type, val;
  115 + uint8_t *q;
  116 +
  117 + /* extract exact DHCP msg type */
  118 + dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
  119 + dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
  120 +
  121 + if (dhcp_msg_type != DHCPDISCOVER &&
  122 + dhcp_msg_type != DHCPREQUEST)
  123 + return;
  124 + /* XXX: this is a hack to get the client mac address */
  125 + memcpy(client_ethaddr, bp->bp_hwaddr, 6);
  126 +
  127 + if ((m = m_get()) == NULL)
  128 + return;
  129 + m->m_data += if_maxlinkhdr;
  130 + rbp = (struct bootp_t *)m->m_data;
  131 + m->m_data += sizeof(struct udpiphdr);
  132 + memset(rbp, 0, sizeof(struct bootp_t));
  133 +
  134 + bc = get_new_addr(&daddr.sin_addr);
  135 + if (!bc) {
  136 + dprintf("no address left\n");
  137 + return;
  138 + }
  139 + dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
  140 +
  141 + saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
  142 + saddr.sin_port = htons(BOOTP_SERVER);
  143 +
  144 + daddr.sin_port = htons(BOOTP_CLIENT);
  145 +
  146 + rbp->bp_op = BOOTP_REPLY;
  147 + rbp->bp_xid = bp->bp_xid;
  148 + rbp->bp_htype = 1;
  149 + rbp->bp_hlen = 6;
  150 + memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
  151 +
  152 + rbp->bp_yiaddr = daddr.sin_addr; /* IP address */
  153 +
  154 + q = rbp->bp_vend;
  155 + memcpy(q, rfc1533_cookie, 4);
  156 + q += 4;
  157 +
  158 + if (dhcp_msg_type == DHCPDISCOVER) {
  159 + *q++ = RFC2132_MSG_TYPE;
  160 + *q++ = 1;
  161 + *q++ = DHCPOFFER;
  162 + } else if (dhcp_msg_type == DHCPREQUEST) {
  163 + *q++ = RFC2132_MSG_TYPE;
  164 + *q++ = 1;
  165 + *q++ = DHCPACK;
  166 + }
  167 +
  168 + if (dhcp_msg_type == DHCPDISCOVER ||
  169 + dhcp_msg_type == DHCPREQUEST) {
  170 + *q++ = RFC2132_SRV_ID;
  171 + *q++ = 4;
  172 + memcpy(q, &saddr.sin_addr, 4);
  173 + q += 4;
  174 +
  175 + *q++ = RFC1533_NETMASK;
  176 + *q++ = 4;
  177 + *q++ = 0xff;
  178 + *q++ = 0xff;
  179 + *q++ = 0xff;
  180 + *q++ = 0x00;
  181 +
  182 + *q++ = RFC1533_GATEWAY;
  183 + *q++ = 4;
  184 + memcpy(q, &saddr.sin_addr, 4);
  185 + q += 4;
  186 +
  187 + *q++ = RFC1533_DNS;
  188 + *q++ = 4;
  189 + dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
  190 + memcpy(q, &dns_addr, 4);
  191 + q += 4;
  192 +
  193 + *q++ = RFC2132_LEASE_TIME;
  194 + *q++ = 4;
  195 + val = htonl(LEASE_TIME);
  196 + memcpy(q, &val, 4);
  197 + q += 4;
  198 + }
  199 + *q++ = RFC1533_END;
  200 +
  201 + m->m_len = sizeof(struct bootp_t);
  202 + udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
  203 +}
  204 +
  205 +void bootp_input(struct mbuf *m)
  206 +{
  207 + struct bootp_t *bp = (struct bootp_t *)m->m_data;
  208 +
  209 + if (bp->bp_op == BOOTP_REQUEST) {
  210 + bootp_reply(bp);
  211 + }
  212 +}
... ...
slirp/bootp.h 0 → 100644
  1 +/* bootp/dhcp defines */
  2 +
  3 +#define BOOTP_SERVER 67
  4 +#define BOOTP_CLIENT 68
  5 +
  6 +#define BOOTP_REQUEST 1
  7 +#define BOOTP_REPLY 2
  8 +
  9 +#define RFC1533_COOKIE 99, 130, 83, 99
  10 +#define RFC1533_PAD 0
  11 +#define RFC1533_NETMASK 1
  12 +#define RFC1533_TIMEOFFSET 2
  13 +#define RFC1533_GATEWAY 3
  14 +#define RFC1533_TIMESERVER 4
  15 +#define RFC1533_IEN116NS 5
  16 +#define RFC1533_DNS 6
  17 +#define RFC1533_LOGSERVER 7
  18 +#define RFC1533_COOKIESERVER 8
  19 +#define RFC1533_LPRSERVER 9
  20 +#define RFC1533_IMPRESSSERVER 10
  21 +#define RFC1533_RESOURCESERVER 11
  22 +#define RFC1533_HOSTNAME 12
  23 +#define RFC1533_BOOTFILESIZE 13
  24 +#define RFC1533_MERITDUMPFILE 14
  25 +#define RFC1533_DOMAINNAME 15
  26 +#define RFC1533_SWAPSERVER 16
  27 +#define RFC1533_ROOTPATH 17
  28 +#define RFC1533_EXTENSIONPATH 18
  29 +#define RFC1533_IPFORWARDING 19
  30 +#define RFC1533_IPSOURCEROUTING 20
  31 +#define RFC1533_IPPOLICYFILTER 21
  32 +#define RFC1533_IPMAXREASSEMBLY 22
  33 +#define RFC1533_IPTTL 23
  34 +#define RFC1533_IPMTU 24
  35 +#define RFC1533_IPMTUPLATEAU 25
  36 +#define RFC1533_INTMTU 26
  37 +#define RFC1533_INTLOCALSUBNETS 27
  38 +#define RFC1533_INTBROADCAST 28
  39 +#define RFC1533_INTICMPDISCOVER 29
  40 +#define RFC1533_INTICMPRESPOND 30
  41 +#define RFC1533_INTROUTEDISCOVER 31
  42 +#define RFC1533_INTROUTESOLICIT 32
  43 +#define RFC1533_INTSTATICROUTES 33
  44 +#define RFC1533_LLTRAILERENCAP 34
  45 +#define RFC1533_LLARPCACHETMO 35
  46 +#define RFC1533_LLETHERNETENCAP 36
  47 +#define RFC1533_TCPTTL 37
  48 +#define RFC1533_TCPKEEPALIVETMO 38
  49 +#define RFC1533_TCPKEEPALIVEGB 39
  50 +#define RFC1533_NISDOMAIN 40
  51 +#define RFC1533_NISSERVER 41
  52 +#define RFC1533_NTPSERVER 42
  53 +#define RFC1533_VENDOR 43
  54 +#define RFC1533_NBNS 44
  55 +#define RFC1533_NBDD 45
  56 +#define RFC1533_NBNT 46
  57 +#define RFC1533_NBSCOPE 47
  58 +#define RFC1533_XFS 48
  59 +#define RFC1533_XDM 49
  60 +
  61 +#define RFC2132_REQ_ADDR 50
  62 +#define RFC2132_LEASE_TIME 51
  63 +#define RFC2132_MSG_TYPE 53
  64 +#define RFC2132_SRV_ID 54
  65 +#define RFC2132_PARAM_LIST 55
  66 +#define RFC2132_MAX_SIZE 57
  67 +#define RFC2132_RENEWAL_TIME 58
  68 +#define RFC2132_REBIND_TIME 59
  69 +
  70 +#define DHCPDISCOVER 1
  71 +#define DHCPOFFER 2
  72 +#define DHCPREQUEST 3
  73 +#define DHCPACK 5
  74 +
  75 +#define RFC1533_VENDOR_MAJOR 0
  76 +#define RFC1533_VENDOR_MINOR 0
  77 +
  78 +#define RFC1533_VENDOR_MAGIC 128
  79 +#define RFC1533_VENDOR_ADDPARM 129
  80 +#define RFC1533_VENDOR_ETHDEV 130
  81 +#define RFC1533_VENDOR_HOWTO 132
  82 +#define RFC1533_VENDOR_MNUOPTS 160
  83 +#define RFC1533_VENDOR_SELECTION 176
  84 +#define RFC1533_VENDOR_MOTD 184
  85 +#define RFC1533_VENDOR_NUMOFMOTD 8
  86 +#define RFC1533_VENDOR_IMG 192
  87 +#define RFC1533_VENDOR_NUMOFIMG 16
  88 +
  89 +#define RFC1533_END 255
  90 +#define BOOTP_VENDOR_LEN 64
  91 +#define DHCP_OPT_LEN 312
  92 +
  93 +struct bootp_t {
  94 + struct ip ip;
  95 + struct udphdr udp;
  96 + uint8_t bp_op;
  97 + uint8_t bp_htype;
  98 + uint8_t bp_hlen;
  99 + uint8_t bp_hops;
  100 + unsigned long bp_xid;
  101 + unsigned short bp_secs;
  102 + unsigned short unused;
  103 + struct in_addr bp_ciaddr;
  104 + struct in_addr bp_yiaddr;
  105 + struct in_addr bp_siaddr;
  106 + struct in_addr bp_giaddr;
  107 + uint8_t bp_hwaddr[16];
  108 + uint8_t bp_sname[64];
  109 + uint8_t bp_file[128];
  110 + uint8_t bp_vend[DHCP_OPT_LEN];
  111 +};
  112 +
  113 +void bootp_input(struct mbuf *m);
... ...
slirp/cksum.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1988, 1992, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
  34 + * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp
  35 + */
  36 +
  37 +#include <slirp.h>
  38 +
  39 +/*
  40 + * Checksum routine for Internet Protocol family headers (Portable Version).
  41 + *
  42 + * This routine is very heavily used in the network
  43 + * code and should be modified for each CPU to be as fast as possible.
  44 + *
  45 + * XXX Since we will never span more than 1 mbuf, we can optimise this
  46 + */
  47 +
  48 +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
  49 +#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
  50 +
  51 +int cksum(struct mbuf *m, int len)
  52 +{
  53 + register u_int16_t *w;
  54 + register int sum = 0;
  55 + register int mlen = 0;
  56 + int byte_swapped = 0;
  57 +
  58 + union {
  59 + u_int8_t c[2];
  60 + u_int16_t s;
  61 + } s_util;
  62 + union {
  63 + u_int16_t s[2];
  64 + u_int32_t l;
  65 + } l_util;
  66 +
  67 + if (m->m_len == 0)
  68 + goto cont;
  69 + w = mtod(m, u_int16_t *);
  70 +
  71 + mlen = m->m_len;
  72 +
  73 + if (len < mlen)
  74 + mlen = len;
  75 + len -= mlen;
  76 + /*
  77 + * Force to even boundary.
  78 + */
  79 + if ((1 & (long) w) && (mlen > 0)) {
  80 + REDUCE;
  81 + sum <<= 8;
  82 + s_util.c[0] = *(u_int8_t *)w;
  83 + w = (u_int16_t *)((int8_t *)w + 1);
  84 + mlen--;
  85 + byte_swapped = 1;
  86 + }
  87 + /*
  88 + * Unroll the loop to make overhead from
  89 + * branches &c small.
  90 + */
  91 + while ((mlen -= 32) >= 0) {
  92 + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
  93 + sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
  94 + sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
  95 + sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
  96 + w += 16;
  97 + }
  98 + mlen += 32;
  99 + while ((mlen -= 8) >= 0) {
  100 + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
  101 + w += 4;
  102 + }
  103 + mlen += 8;
  104 + if (mlen == 0 && byte_swapped == 0)
  105 + goto cont;
  106 + REDUCE;
  107 + while ((mlen -= 2) >= 0) {
  108 + sum += *w++;
  109 + }
  110 +
  111 + if (byte_swapped) {
  112 + REDUCE;
  113 + sum <<= 8;
  114 + byte_swapped = 0;
  115 + if (mlen == -1) {
  116 + s_util.c[1] = *(u_int8_t *)w;
  117 + sum += s_util.s;
  118 + mlen = 0;
  119 + } else
  120 +
  121 + mlen = -1;
  122 + } else if (mlen == -1)
  123 + s_util.c[0] = *(u_int8_t *)w;
  124 +
  125 +cont:
  126 +#ifdef DEBUG
  127 + if (len) {
  128 + DEBUG_ERROR((dfd, "cksum: out of data\n"));
  129 + DEBUG_ERROR((dfd, " len = %d\n", len));
  130 + }
  131 +#endif
  132 + if (mlen == -1) {
  133 + /* The last mbuf has odd # of bytes. Follow the
  134 + standard (the odd byte may be shifted left by 8 bits
  135 + or not as determined by endian-ness of the machine) */
  136 + s_util.c[1] = 0;
  137 + sum += s_util.s;
  138 + }
  139 + REDUCE;
  140 + return (~sum & 0xffff);
  141 +}
... ...
slirp/ctl.h 0 → 100644
  1 +#define CTL_CMD 0
  2 +#define CTL_EXEC 1
  3 +#define CTL_ALIAS 2
  4 +#define CTL_DNS 3
  5 +
  6 +#define CTL_SPECIAL "10.0.2.0"
  7 +#define CTL_LOCAL "10.0.2.15"
... ...
slirp/debug.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + * Portions copyright (c) 2000 Kelly Price.
  4 + *
  5 + * Please read the file COPYRIGHT for the
  6 + * terms and conditions of the copyright.
  7 + */
  8 +
  9 +#include <slirp.h>
  10 +
  11 +FILE *dfd = NULL;
  12 +#ifdef DEBUG
  13 +int dostats = 1;
  14 +#else
  15 +int dostats = 0;
  16 +#endif
  17 +int slirp_debug = 0;
  18 +
  19 +extern char *strerror _P((int));
  20 +
  21 +/* Carry over one item from main.c so that the tty's restored.
  22 + * Only done when the tty being used is /dev/tty --RedWolf */
  23 +extern struct termios slirp_tty_settings;
  24 +extern int slirp_tty_restore;
  25 +
  26 +
  27 +void
  28 +debug_init(file, dbg)
  29 + char *file;
  30 + int dbg;
  31 +{
  32 + /* Close the old debugging file */
  33 + if (dfd)
  34 + fclose(dfd);
  35 +
  36 + dfd = fopen(file,"w");
  37 + if (dfd != NULL) {
  38 +#if 0
  39 + fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION);
  40 +#endif
  41 + fprintf(dfd,"Debugging Started level %i.\r\n",dbg);
  42 + fflush(dfd);
  43 + slirp_debug = dbg;
  44 + } else {
  45 + lprint("Error: Debugging file \"%s\" could not be opened: %s\r\n",
  46 + file, strerror(errno));
  47 + }
  48 +}
  49 +
  50 +/*
  51 + * Dump a packet in the same format as tcpdump -x
  52 + */
  53 +#ifdef DEBUG
  54 +void
  55 +dump_packet(dat, n)
  56 + void *dat;
  57 + int n;
  58 +{
  59 + u_char *pptr = (u_char *)dat;
  60 + int j,k;
  61 +
  62 + n /= 16;
  63 + n++;
  64 + DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
  65 + for(j = 0; j < n; j++) {
  66 + for(k = 0; k < 6; k++)
  67 + DEBUG_MISC((dfd, "%02x ", *pptr++));
  68 + DEBUG_MISC((dfd, "\n"));
  69 + fflush(dfd);
  70 + }
  71 +}
  72 +#endif
  73 +
  74 +#if 0
  75 +/*
  76 + * Statistic routines
  77 + *
  78 + * These will print statistics to the screen, the debug file (dfd), or
  79 + * a buffer, depending on "type", so that the stats can be sent over
  80 + * the link as well.
  81 + */
  82 +
  83 +void
  84 +ttystats(ttyp)
  85 + struct ttys *ttyp;
  86 +{
  87 + struct slirp_ifstats *is = &ttyp->ifstats;
  88 + char buff[512];
  89 +
  90 + lprint(" \r\n");
  91 +
  92 + if (if_comp & IF_COMPRESS)
  93 + strcpy(buff, "on");
  94 + else if (if_comp & IF_NOCOMPRESS)
  95 + strcpy(buff, "off");
  96 + else
  97 + strcpy(buff, "off (for now)");
  98 + lprint("Unit %d:\r\n", ttyp->unit);
  99 + lprint(" using %s encapsulation (VJ compression is %s)\r\n", (
  100 +#ifdef USE_PPP
  101 + ttyp->proto==PROTO_PPP?"PPP":
  102 +#endif
  103 + "SLIP"), buff);
  104 + lprint(" %d baudrate\r\n", ttyp->baud);
  105 + lprint(" interface is %s\r\n", ttyp->up?"up":"down");
  106 + lprint(" using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid);
  107 +#ifndef FULL_BOLT
  108 + lprint(" towrite is %d bytes\r\n", ttyp->towrite);
  109 +#endif
  110 + if (ttyp->zeros)
  111 + lprint(" %d zeros have been typed\r\n", ttyp->zeros);
  112 + else if (ttyp->ones)
  113 + lprint(" %d ones have been typed\r\n", ttyp->ones);
  114 + lprint("Interface stats:\r\n");
  115 + lprint(" %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes);
  116 + lprint(" %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes);
  117 + lprint(" %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes);
  118 + lprint(" %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes);
  119 + lprint(" %6d bad input packets\r\n", is->in_mbad);
  120 +}
  121 +
  122 +void
  123 +allttystats()
  124 +{
  125 + struct ttys *ttyp;
  126 +
  127 + for (ttyp = ttys; ttyp; ttyp = ttyp->next)
  128 + ttystats(ttyp);
  129 +}
  130 +#endif
  131 +
  132 +void
  133 +ipstats()
  134 +{
  135 + lprint(" \r\n");
  136 +
  137 + lprint("IP stats:\r\n");
  138 + lprint(" %6d total packets received (%d were unaligned)\r\n",
  139 + ipstat.ips_total, ipstat.ips_unaligned);
  140 + lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers);
  141 + lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum);
  142 + lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort);
  143 + lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall);
  144 + lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen);
  145 + lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen);
  146 + lprint(" %6d fragments received\r\n", ipstat.ips_fragments);
  147 + lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped);
  148 + lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout);
  149 + lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled);
  150 + lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented);
  151 + lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments);
  152 + lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto);
  153 + lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
  154 +}
  155 +
  156 +#if 0
  157 +void
  158 +vjstats()
  159 +{
  160 + lprint(" \r\n");
  161 +
  162 + lprint("VJ compression stats:\r\n");
  163 +
  164 + lprint(" %6d outbound packets (%d compressed)\r\n",
  165 + comp_s.sls_packets, comp_s.sls_compressed);
  166 + lprint(" %6d searches for connection stats (%d misses)\r\n",
  167 + comp_s.sls_searches, comp_s.sls_misses);
  168 + lprint(" %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin);
  169 + lprint(" %6d inbound compressed packets\r\n", comp_s.sls_compressedin);
  170 + lprint(" %6d inbound unknown type packets\r\n", comp_s.sls_errorin);
  171 + lprint(" %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed);
  172 +}
  173 +#endif
  174 +
  175 +void
  176 +tcpstats()
  177 +{
  178 + lprint(" \r\n");
  179 +
  180 + lprint("TCP stats:\r\n");
  181 +
  182 + lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
  183 + lprint(" %6d data packets (%d bytes)\r\n",
  184 + tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
  185 + lprint(" %6d data packets retransmitted (%d bytes)\r\n",
  186 + tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte);
  187 + lprint(" %6d ack-only packets (%d delayed)\r\n",
  188 + tcpstat.tcps_sndacks, tcpstat.tcps_delack);
  189 + lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg);
  190 + lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe);
  191 + lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
  192 + lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
  193 + lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
  194 +
  195 + lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
  196 + lprint(" %6d acks (for %d bytes)\r\n",
  197 + tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
  198 + lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
  199 + lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch);
  200 + lprint(" %6d packets received in sequence (%d bytes)\r\n",
  201 + tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
  202 + lprint(" %6d completely duplicate packets (%d bytes)\r\n",
  203 + tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
  204 +
  205 + lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
  206 + tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
  207 + lprint(" %6d out-of-order packets (%d bytes)\r\n",
  208 + tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte);
  209 + lprint(" %6d packets of data after window (%d bytes)\r\n",
  210 + tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin);
  211 + lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe);
  212 + lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd);
  213 + lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose);
  214 + lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
  215 + lprint(" %6d discarded for bad header offset fields\r\n",
  216 + tcpstat.tcps_rcvbadoff);
  217 +
  218 + lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
  219 + lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
  220 + lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
  221 + lprint(" %6d connections closed (including %d drop)\r\n",
  222 + tcpstat.tcps_closed, tcpstat.tcps_drops);
  223 + lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops);
  224 + lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n",
  225 + tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated);
  226 + lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo);
  227 + lprint(" %6d connections dropped by rxmt timeout\r\n",
  228 + tcpstat.tcps_timeoutdrop);
  229 + lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo);
  230 + lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo);
  231 + lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe);
  232 + lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops);
  233 + lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
  234 + lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
  235 + lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
  236 +
  237 +
  238 +/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
  239 +/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
  240 +
  241 +}
  242 +
  243 +void
  244 +udpstats()
  245 +{
  246 + lprint(" \r\n");
  247 +
  248 + lprint("UDP stats:\r\n");
  249 + lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets);
  250 + lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops);
  251 + lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum);
  252 + lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen);
  253 + lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss);
  254 + lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
  255 +}
  256 +
  257 +void
  258 +icmpstats()
  259 +{
  260 + lprint(" \r\n");
  261 + lprint("ICMP stats:\r\n");
  262 + lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received);
  263 + lprint(" %6d were too short\r\n", icmpstat.icps_tooshort);
  264 + lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum);
  265 + lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp);
  266 + lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype);
  267 + lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
  268 +}
  269 +
  270 +void
  271 +mbufstats()
  272 +{
  273 + struct mbuf *m;
  274 + int i;
  275 +
  276 + lprint(" \r\n");
  277 +
  278 + lprint("Mbuf stats:\r\n");
  279 +
  280 + lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
  281 +
  282 + i = 0;
  283 + for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
  284 + i++;
  285 + lprint(" %6d mbufs on free list\r\n", i);
  286 +
  287 + i = 0;
  288 + for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
  289 + i++;
  290 + lprint(" %6d mbufs on used list\r\n", i);
  291 + lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
  292 +}
  293 +
  294 +void
  295 +sockstats()
  296 +{
  297 + char buff[256];
  298 + int n;
  299 + struct socket *so;
  300 +
  301 + lprint(" \r\n");
  302 +
  303 + lprint(
  304 + "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n");
  305 +
  306 + for (so = tcb.so_next; so != &tcb; so = so->so_next) {
  307 +
  308 + n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
  309 + while (n < 17)
  310 + buff[n++] = ' ';
  311 + buff[17] = 0;
  312 + lprint("%s %3d %15s %5d ",
  313 + buff, so->s,
  314 + inet_ntoa(so->so_laddr), ntohs(so->so_lport));
  315 + lprint("%15s %5d %5d %5d\r\n",
  316 + inet_ntoa(so->so_faddr), ntohs(so->so_fport),
  317 + so->so_rcv.sb_cc, so->so_snd.sb_cc);
  318 + }
  319 +
  320 + for (so = udb.so_next; so != &udb; so = so->so_next) {
  321 +
  322 + n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
  323 + while (n < 17)
  324 + buff[n++] = ' ';
  325 + buff[17] = 0;
  326 + lprint("%s %3d %15s %5d ",
  327 + buff, so->s,
  328 + inet_ntoa(so->so_laddr), ntohs(so->so_lport));
  329 + lprint("%15s %5d %5d %5d\r\n",
  330 + inet_ntoa(so->so_faddr), ntohs(so->so_fport),
  331 + so->so_rcv.sb_cc, so->so_snd.sb_cc);
  332 + }
  333 +}
  334 +
  335 +#if 0
  336 +void
  337 +slirp_exit(exit_status)
  338 + int exit_status;
  339 +{
  340 + struct ttys *ttyp;
  341 +
  342 + DEBUG_CALL("slirp_exit");
  343 + DEBUG_ARG("exit_status = %d", exit_status);
  344 +
  345 + if (dostats) {
  346 + lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf;
  347 + if (!dfd)
  348 + debug_init("slirp_stats", 0xf);
  349 + lprint_arg = (char **)&dfd;
  350 +
  351 + ipstats();
  352 + tcpstats();
  353 + udpstats();
  354 + icmpstats();
  355 + mbufstats();
  356 + sockstats();
  357 + allttystats();
  358 + vjstats();
  359 + }
  360 +
  361 + for (ttyp = ttys; ttyp; ttyp = ttyp->next)
  362 + tty_detached(ttyp, 1);
  363 +
  364 + if (slirp_forked) {
  365 + /* Menendez time */
  366 + if (kill(getppid(), SIGQUIT) < 0)
  367 + lprint("Couldn't kill parent process %ld!\n",
  368 + (long) getppid());
  369 + }
  370 +
  371 + /* Restore the terminal if we gotta */
  372 + if(slirp_tty_restore)
  373 + tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
  374 + exit(exit_status);
  375 +}
  376 +#endif
... ...
slirp/debug.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#define PRN_STDERR 1
  9 +#define PRN_SPRINTF 2
  10 +
  11 +extern FILE *dfd;
  12 +extern FILE *lfd;
  13 +extern int dostats;
  14 +extern int slirp_debug;
  15 +
  16 +#define DBG_CALL 0x1
  17 +#define DBG_MISC 0x2
  18 +#define DBG_ERROR 0x4
  19 +#define DEBUG_DEFAULT DBG_CALL|DBG_MISC|DBG_ERROR
  20 +
  21 +#ifdef DEBUG
  22 +#define DEBUG_CALL(x) if (slirp_debug & DBG_CALL) { fprintf(dfd, "%s...\n", x); fflush(dfd); }
  23 +#define DEBUG_ARG(x, y) if (slirp_debug & DBG_CALL) { fputc(' ', dfd); fprintf(dfd, x, y); fputc('\n', dfd); fflush(dfd); }
  24 +#define DEBUG_ARGS(x) if (slirp_debug & DBG_CALL) { fprintf x ; fflush(dfd); }
  25 +#define DEBUG_MISC(x) if (slirp_debug & DBG_MISC) { fprintf x ; fflush(dfd); }
  26 +#define DEBUG_ERROR(x) if (slirp_debug & DBG_ERROR) {fprintf x ; fflush(dfd); }
  27 +
  28 +
  29 +#else
  30 +
  31 +#define DEBUG_CALL(x)
  32 +#define DEBUG_ARG(x, y)
  33 +#define DEBUG_ARGS(x)
  34 +#define DEBUG_MISC(x)
  35 +#define DEBUG_ERROR(x)
  36 +
  37 +#endif
  38 +
  39 +void debug_init _P((char *, int));
  40 +//void ttystats _P((struct ttys *));
  41 +void allttystats _P((void));
  42 +void ipstats _P((void));
  43 +void vjstats _P((void));
  44 +void tcpstats _P((void));
  45 +void udpstats _P((void));
  46 +void icmpstats _P((void));
  47 +void mbufstats _P((void));
  48 +void sockstats _P((void));
  49 +void slirp_exit _P((int));
  50 +
... ...
slirp/icmp_var.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93
  34 + * icmp_var.h,v 1.4 1995/02/16 00:27:40 wollman Exp
  35 + */
  36 +
  37 +#ifndef _NETINET_ICMP_VAR_H_
  38 +#define _NETINET_ICMP_VAR_H_
  39 +
  40 +/*
  41 + * Variables related to this implementation
  42 + * of the internet control message protocol.
  43 + */
  44 +struct icmpstat {
  45 +/* statistics related to input messages processed */
  46 + u_long icps_received; /* #ICMP packets received */
  47 + u_long icps_tooshort; /* packet < ICMP_MINLEN */
  48 + u_long icps_checksum; /* bad checksum */
  49 + u_long icps_notsupp; /* #ICMP packets not supported */
  50 + u_long icps_badtype; /* #with bad type feild */
  51 + u_long icps_reflect; /* number of responses */
  52 +};
  53 +
  54 +/*
  55 + * Names for ICMP sysctl objects
  56 + */
  57 +#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
  58 +#define ICMPCTL_STATS 2 /* statistics (read-only) */
  59 +#define ICMPCTL_MAXID 3
  60 +
  61 +#define ICMPCTL_NAMES { \
  62 + { 0, 0 }, \
  63 + { "maskrepl", CTLTYPE_INT }, \
  64 + { "stats", CTLTYPE_STRUCT }, \
  65 +}
  66 +
  67 +extern struct icmpstat icmpstat;
  68 +
  69 +#endif
... ...
slirp/if.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#include <slirp.h>
  9 +
  10 +int if_mtu, if_mru;
  11 +int if_comp;
  12 +int if_maxlinkhdr;
  13 +int if_queued = 0; /* Number of packets queued so far */
  14 +int if_thresh = 10; /* Number of packets queued before we start sending
  15 + * (to prevent allocing too many mbufs) */
  16 +
  17 +struct mbuf if_fastq; /* fast queue (for interactive data) */
  18 +struct mbuf if_batchq; /* queue for non-interactive data */
  19 +struct mbuf *next_m; /* Pointer to next mbuf to output */
  20 +
  21 +#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
  22 +
  23 +void
  24 +ifs_insque(ifm, ifmhead)
  25 + struct mbuf *ifm, *ifmhead;
  26 +{
  27 + ifm->ifs_next = ifmhead->ifs_next;
  28 + ifmhead->ifs_next = ifm;
  29 + ifm->ifs_prev = ifmhead;
  30 + ifm->ifs_next->ifs_prev = ifm;
  31 +}
  32 +
  33 +void
  34 +ifs_remque(ifm)
  35 + struct mbuf *ifm;
  36 +{
  37 + ifm->ifs_prev->ifs_next = ifm->ifs_next;
  38 + ifm->ifs_next->ifs_prev = ifm->ifs_prev;
  39 +}
  40 +
  41 +void
  42 +if_init()
  43 +{
  44 +#if 0
  45 + /*
  46 + * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
  47 + * and 8 bytes for PPP, but need to have it on an 8byte boundary
  48 + */
  49 +#ifdef USE_PPP
  50 + if_maxlinkhdr = 48;
  51 +#else
  52 + if_maxlinkhdr = 40;
  53 +#endif
  54 +#else
  55 + /* 14 for ethernet + 40 */
  56 + if_maxlinkhdr = 14 + 40;
  57 +#endif
  58 + if_mtu = 1500;
  59 + if_mru = 1500;
  60 + if_comp = IF_AUTOCOMP;
  61 + if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
  62 + if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
  63 + // sl_compress_init(&comp_s);
  64 + next_m = &if_batchq;
  65 +}
  66 +
  67 +#if 0
  68 +/*
  69 + * This shouldn't be needed since the modem is blocking and
  70 + * we don't expect any signals, but what the hell..
  71 + */
  72 +inline int
  73 +writen(fd, bptr, n)
  74 + int fd;
  75 + char *bptr;
  76 + int n;
  77 +{
  78 + int ret;
  79 + int total;
  80 +
  81 + /* This should succeed most of the time */
  82 + ret = write(fd, bptr, n);
  83 + if (ret == n || ret <= 0)
  84 + return ret;
  85 +
  86 + /* Didn't write everything, go into the loop */
  87 + total = ret;
  88 + while (n > total) {
  89 + ret = write(fd, bptr+total, n-total);
  90 + if (ret <= 0)
  91 + return ret;
  92 + total += ret;
  93 + }
  94 + return total;
  95 +}
  96 +
  97 +/*
  98 + * if_input - read() the tty, do "top level" processing (ie: check for any escapes),
  99 + * and pass onto (*ttyp->if_input)
  100 + *
  101 + * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
  102 + */
  103 +#define INBUFF_SIZE 2048 /* XXX */
  104 +void
  105 +if_input(ttyp)
  106 + struct ttys *ttyp;
  107 +{
  108 + u_char if_inbuff[INBUFF_SIZE];
  109 + int if_n;
  110 +
  111 + DEBUG_CALL("if_input");
  112 + DEBUG_ARG("ttyp = %lx", (long)ttyp);
  113 +
  114 + if_n = read(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE);
  115 +
  116 + DEBUG_MISC((dfd, " read %d bytes\n", if_n));
  117 +
  118 + if (if_n <= 0) {
  119 + if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
  120 + if (ttyp->up)
  121 + link_up--;
  122 + tty_detached(ttyp, 0);
  123 + }
  124 + return;
  125 + }
  126 + if (if_n == 1) {
  127 + if (*if_inbuff == '0') {
  128 + ttyp->ones = 0;
  129 + if (++ttyp->zeros >= 5)
  130 + slirp_exit(0);
  131 + return;
  132 + }
  133 + if (*if_inbuff == '1') {
  134 + ttyp->zeros = 0;
  135 + if (++ttyp->ones >= 5)
  136 + tty_detached(ttyp, 0);
  137 + return;
  138 + }
  139 + }
  140 + ttyp->ones = ttyp->zeros = 0;
  141 +
  142 + (*ttyp->if_input)(ttyp, if_inbuff, if_n);
  143 +}
  144 +#endif
  145 +
  146 +/*
  147 + * if_output: Queue packet into an output queue.
  148 + * There are 2 output queue's, if_fastq and if_batchq.
  149 + * Each output queue is a doubly linked list of double linked lists
  150 + * of mbufs, each list belonging to one "session" (socket). This
  151 + * way, we can output packets fairly by sending one packet from each
  152 + * session, instead of all the packets from one session, then all packets
  153 + * from the next session, etc. Packets on the if_fastq get absolute
  154 + * priority, but if one session hogs the link, it gets "downgraded"
  155 + * to the batchq until it runs out of packets, then it'll return
  156 + * to the fastq (eg. if the user does an ls -alR in a telnet session,
  157 + * it'll temporarily get downgraded to the batchq)
  158 + */
  159 +void
  160 +if_output(so, ifm)
  161 + struct socket *so;
  162 + struct mbuf *ifm;
  163 +{
  164 + struct mbuf *ifq;
  165 + int on_fastq = 1;
  166 +
  167 + DEBUG_CALL("if_output");
  168 + DEBUG_ARG("so = %lx", (long)so);
  169 + DEBUG_ARG("ifm = %lx", (long)ifm);
  170 +
  171 + /*
  172 + * First remove the mbuf from m_usedlist,
  173 + * since we're gonna use m_next and m_prev ourselves
  174 + * XXX Shouldn't need this, gotta change dtom() etc.
  175 + */
  176 + if (ifm->m_flags & M_USEDLIST) {
  177 + remque(ifm);
  178 + ifm->m_flags &= ~M_USEDLIST;
  179 + }
  180 +
  181 + /*
  182 + * See if there's already a batchq list for this session.
  183 + * This can include an interactive session, which should go on fastq,
  184 + * but gets too greedy... hence it'll be downgraded from fastq to batchq.
  185 + * We mustn't put this packet back on the fastq (or we'll send it out of order)
  186 + * XXX add cache here?
  187 + */
  188 + for (ifq = if_batchq.ifq_prev; ifq != &if_batchq; ifq = ifq->ifq_prev) {
  189 + if (so == ifq->ifq_so) {
  190 + /* A match! */
  191 + ifm->ifq_so = so;
  192 + ifs_insque(ifm, ifq->ifs_prev);
  193 + goto diddit;
  194 + }
  195 + }
  196 +
  197 + /* No match, check which queue to put it on */
  198 + if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
  199 + ifq = if_fastq.ifq_prev;
  200 + on_fastq = 1;
  201 + /*
  202 + * Check if this packet is a part of the last
  203 + * packet's session
  204 + */
  205 + if (ifq->ifq_so == so) {
  206 + ifm->ifq_so = so;
  207 + ifs_insque(ifm, ifq->ifs_prev);
  208 + goto diddit;
  209 + }
  210 + } else
  211 + ifq = if_batchq.ifq_prev;
  212 +
  213 + /* Create a new doubly linked list for this session */
  214 + ifm->ifq_so = so;
  215 + ifs_init(ifm);
  216 + insque(ifm, ifq);
  217 +
  218 +diddit:
  219 + ++if_queued;
  220 +
  221 + if (so) {
  222 + /* Update *_queued */
  223 + so->so_queued++;
  224 + so->so_nqueued++;
  225 + /*
  226 + * Check if the interactive session should be downgraded to
  227 + * the batchq. A session is downgraded if it has queued 6
  228 + * packets without pausing, and at least 3 of those packets
  229 + * have been sent over the link
  230 + * (XXX These are arbitrary numbers, probably not optimal..)
  231 + */
  232 + if (on_fastq && ((so->so_nqueued >= 6) &&
  233 + (so->so_nqueued - so->so_queued) >= 3)) {
  234 +
  235 + /* Remove from current queue... */
  236 + remque(ifm->ifs_next);
  237 +
  238 + /* ...And insert in the new. That'll teach ya! */
  239 + insque(ifm->ifs_next, &if_batchq);
  240 + }
  241 + }
  242 +
  243 +#ifndef FULL_BOLT
  244 + /*
  245 + * This prevents us from malloc()ing too many mbufs
  246 + */
  247 + if (link_up) {
  248 + /* if_start will check towrite */
  249 + if_start();
  250 + }
  251 +#endif
  252 +}
  253 +
  254 +/*
  255 + * Send a packet
  256 + * We choose a packet based on it's position in the output queues;
  257 + * If there are packets on the fastq, they are sent FIFO, before
  258 + * everything else. Otherwise we choose the first packet from the
  259 + * batchq and send it. the next packet chosen will be from the session
  260 + * after this one, then the session after that one, and so on.. So,
  261 + * for example, if there are 3 ftp session's fighting for bandwidth,
  262 + * one packet will be sent from the first session, then one packet
  263 + * from the second session, then one packet from the third, then back
  264 + * to the first, etc. etc.
  265 + */
  266 +void
  267 +if_start(void)
  268 +{
  269 + struct mbuf *ifm, *ifqt;
  270 +
  271 + DEBUG_CALL("if_start");
  272 +
  273 + if (if_queued == 0)
  274 + return; /* Nothing to do */
  275 +
  276 + again:
  277 + /* check if we can really output */
  278 + if (!slirp_can_output())
  279 + return;
  280 +
  281 + /*
  282 + * See which queue to get next packet from
  283 + * If there's something in the fastq, select it immediately
  284 + */
  285 + if (if_fastq.ifq_next != &if_fastq) {
  286 + ifm = if_fastq.ifq_next;
  287 + } else {
  288 + /* Nothing on fastq, see if next_m is valid */
  289 + if (next_m != &if_batchq)
  290 + ifm = next_m;
  291 + else
  292 + ifm = if_batchq.ifq_next;
  293 +
  294 + /* Set which packet to send on next iteration */
  295 + next_m = ifm->ifq_next;
  296 + }
  297 + /* Remove it from the queue */
  298 + ifqt = ifm->ifq_prev;
  299 + remque(ifm);
  300 + --if_queued;
  301 +
  302 + /* If there are more packets for this session, re-queue them */
  303 + if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
  304 + insque(ifm->ifs_next, ifqt);
  305 + ifs_remque(ifm);
  306 + }
  307 +
  308 + /* Update so_queued */
  309 + if (ifm->ifq_so) {
  310 + if (--ifm->ifq_so->so_queued == 0)
  311 + /* If there's no more queued, reset nqueued */
  312 + ifm->ifq_so->so_nqueued = 0;
  313 + }
  314 +
  315 + /* Encapsulate the packet for sending */
  316 + if_encap(ifm->m_data, ifm->m_len);
  317 +
  318 + if (if_queued)
  319 + goto again;
  320 +}
... ...
slirp/if.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#ifndef _IF_H_
  9 +#define _IF_H_
  10 +
  11 +#define IF_COMPRESS 0x01 /* We want compression */
  12 +#define IF_NOCOMPRESS 0x02 /* Do not do compression */
  13 +#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
  14 +#define IF_NOCIDCOMP 0x08 /* CID compression */
  15 +
  16 +/* Needed for FreeBSD */
  17 +#undef if_mtu
  18 +extern int if_mtu;
  19 +extern int if_mru; /* MTU and MRU */
  20 +extern int if_comp; /* Flags for compression */
  21 +extern int if_maxlinkhdr;
  22 +extern int if_queued; /* Number of packets queued so far */
  23 +extern int if_thresh; /* Number of packets queued before we start sending
  24 + * (to prevent allocing too many mbufs) */
  25 +
  26 +extern struct mbuf if_fastq; /* fast queue (for interactive data) */
  27 +extern struct mbuf if_batchq; /* queue for non-interactive data */
  28 +extern struct mbuf *next_m;
  29 +
  30 +#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
  31 +
  32 +/* Interface statistics */
  33 +struct slirp_ifstats {
  34 + u_int out_pkts; /* Output packets */
  35 + u_int out_bytes; /* Output bytes */
  36 + u_int out_errpkts; /* Output Error Packets */
  37 + u_int out_errbytes; /* Output Error Bytes */
  38 + u_int in_pkts; /* Input packets */
  39 + u_int in_bytes; /* Input bytes */
  40 + u_int in_errpkts; /* Input Error Packets */
  41 + u_int in_errbytes; /* Input Error Bytes */
  42 +
  43 + u_int bytes_saved; /* Number of bytes that compression "saved" */
  44 + /* ie: number of bytes that didn't need to be sent over the link
  45 + * because of compression */
  46 +
  47 + u_int in_mbad; /* Bad incoming packets */
  48 +};
  49 +
  50 +#endif
... ...
slirp/ip.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)ip.h 8.1 (Berkeley) 6/10/93
  34 + * ip.h,v 1.3 1994/08/21 05:27:30 paul Exp
  35 + */
  36 +
  37 +#ifndef _IP_H_
  38 +#define _IP_H_
  39 +
  40 +#ifdef WORDS_BIGENDIAN
  41 +# ifndef NTOHL
  42 +# define NTOHL(d)
  43 +# endif
  44 +# ifndef NTOHS
  45 +# define NTOHS(d)
  46 +# endif
  47 +# ifndef HTONL
  48 +# define HTONL(d)
  49 +# endif
  50 +# ifndef HTONS
  51 +# define HTONS(d)
  52 +# endif
  53 +#else
  54 +# ifndef NTOHL
  55 +# define NTOHL(d) ((d) = ntohl((d)))
  56 +# endif
  57 +# ifndef NTOHS
  58 +# define NTOHS(d) ((d) = ntohs((u_int16_t)(d)))
  59 +# endif
  60 +# ifndef HTONL
  61 +# define HTONL(d) ((d) = htonl((d)))
  62 +# endif
  63 +# ifndef HTONS
  64 +# define HTONS(d) ((d) = htons((u_int16_t)(d)))
  65 +# endif
  66 +#endif
  67 +
  68 +typedef u_int32_t n_long; /* long as received from the net */
  69 +
  70 +/*
  71 + * Definitions for internet protocol version 4.
  72 + * Per RFC 791, September 1981.
  73 + */
  74 +#define IPVERSION 4
  75 +
  76 +/*
  77 + * Structure of an internet header, naked of options.
  78 + *
  79 + * We declare ip_len and ip_off to be short, rather than u_short
  80 + * pragmatically since otherwise unsigned comparisons can result
  81 + * against negative integers quite easily, and fail in subtle ways.
  82 + */
  83 +struct ip {
  84 +#ifdef WORDS_BIGENDIAN
  85 + u_int ip_v:4, /* version */
  86 + ip_hl:4; /* header length */
  87 +#else
  88 + u_int ip_hl:4, /* header length */
  89 + ip_v:4; /* version */
  90 +#endif
  91 + u_int8_t ip_tos; /* type of service */
  92 + int16_t ip_len; /* total length */
  93 + u_int16_t ip_id; /* identification */
  94 + int16_t ip_off; /* fragment offset field */
  95 +#define IP_DF 0x4000 /* don't fragment flag */
  96 +#define IP_MF 0x2000 /* more fragments flag */
  97 +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
  98 + u_int8_t ip_ttl; /* time to live */
  99 + u_int8_t ip_p; /* protocol */
  100 + u_int16_t ip_sum; /* checksum */
  101 + struct in_addr ip_src,ip_dst; /* source and dest address */
  102 +};
  103 +
  104 +#define IP_MAXPACKET 65535 /* maximum packet size */
  105 +
  106 +/*
  107 + * Definitions for IP type of service (ip_tos)
  108 + */
  109 +#define IPTOS_LOWDELAY 0x10
  110 +#define IPTOS_THROUGHPUT 0x08
  111 +#define IPTOS_RELIABILITY 0x04
  112 +
  113 +/*
  114 + * Definitions for options.
  115 + */
  116 +#define IPOPT_COPIED(o) ((o)&0x80)
  117 +#define IPOPT_CLASS(o) ((o)&0x60)
  118 +#define IPOPT_NUMBER(o) ((o)&0x1f)
  119 +
  120 +#define IPOPT_CONTROL 0x00
  121 +#define IPOPT_RESERVED1 0x20
  122 +#define IPOPT_DEBMEAS 0x40
  123 +#define IPOPT_RESERVED2 0x60
  124 +
  125 +#define IPOPT_EOL 0 /* end of option list */
  126 +#define IPOPT_NOP 1 /* no operation */
  127 +
  128 +#define IPOPT_RR 7 /* record packet route */
  129 +#define IPOPT_TS 68 /* timestamp */
  130 +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
  131 +#define IPOPT_LSRR 131 /* loose source route */
  132 +#define IPOPT_SATID 136 /* satnet id */
  133 +#define IPOPT_SSRR 137 /* strict source route */
  134 +
  135 +/*
  136 + * Offsets to fields in options other than EOL and NOP.
  137 + */
  138 +#define IPOPT_OPTVAL 0 /* option ID */
  139 +#define IPOPT_OLEN 1 /* option length */
  140 +#define IPOPT_OFFSET 2 /* offset within option */
  141 +#define IPOPT_MINOFF 4 /* min value of above */
  142 +
  143 +/*
  144 + * Time stamp option structure.
  145 + */
  146 +struct ip_timestamp {
  147 + u_int8_t ipt_code; /* IPOPT_TS */
  148 + u_int8_t ipt_len; /* size of structure (variable) */
  149 + u_int8_t ipt_ptr; /* index of current entry */
  150 +#ifdef WORDS_BIGENDIAN
  151 + u_int ipt_oflw:4, /* overflow counter */
  152 + ipt_flg:4; /* flags, see below */
  153 +#else
  154 + u_int ipt_flg:4, /* flags, see below */
  155 + ipt_oflw:4; /* overflow counter */
  156 +#endif
  157 + union ipt_timestamp {
  158 + n_long ipt_time[1];
  159 + struct ipt_ta {
  160 + struct in_addr ipt_addr;
  161 + n_long ipt_time;
  162 + } ipt_ta[1];
  163 + } ipt_timestamp;
  164 +};
  165 +
  166 +/* flag bits for ipt_flg */
  167 +#define IPOPT_TS_TSONLY 0 /* timestamps only */
  168 +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
  169 +#define IPOPT_TS_PRESPEC 3 /* specified modules only */
  170 +
  171 +/* bits for security (not byte swapped) */
  172 +#define IPOPT_SECUR_UNCLASS 0x0000
  173 +#define IPOPT_SECUR_CONFID 0xf135
  174 +#define IPOPT_SECUR_EFTO 0x789a
  175 +#define IPOPT_SECUR_MMMM 0xbc4d
  176 +#define IPOPT_SECUR_RESTR 0xaf13
  177 +#define IPOPT_SECUR_SECRET 0xd788
  178 +#define IPOPT_SECUR_TOPSECRET 0x6bc5
  179 +
  180 +/*
  181 + * Internet implementation parameters.
  182 + */
  183 +#define MAXTTL 255 /* maximum time to live (seconds) */
  184 +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
  185 +#define IPFRAGTTL 60 /* time to live for frags, slowhz */
  186 +#define IPTTLDEC 1 /* subtracted when forwarding */
  187 +
  188 +#define IP_MSS 576 /* default maximum segment size */
  189 +
  190 +#ifdef HAVE_SYS_TYPES32_H /* Overcome some Solaris 2.x junk */
  191 +#include <sys/types32.h>
  192 +#else
  193 +#if SIZEOF_CHAR_P == 4
  194 +typedef caddr_t caddr32_t;
  195 +#else
  196 +typedef u_int32_t caddr32_t;
  197 +#endif
  198 +#endif
  199 +
  200 +#if SIZEOF_CHAR_P == 4
  201 +typedef struct ipq *ipqp_32;
  202 +typedef struct ipasfrag *ipasfragp_32;
  203 +#else
  204 +typedef caddr32_t ipqp_32;
  205 +typedef caddr32_t ipasfragp_32;
  206 +#endif
  207 +
  208 +/*
  209 + * Overlay for ip header used by other protocols (tcp, udp).
  210 + */
  211 +struct ipovly {
  212 + caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
  213 + u_int8_t ih_x1; /* (unused) */
  214 + u_int8_t ih_pr; /* protocol */
  215 + int16_t ih_len; /* protocol length */
  216 + struct in_addr ih_src; /* source internet address */
  217 + struct in_addr ih_dst; /* destination internet address */
  218 +};
  219 +
  220 +/*
  221 + * Ip reassembly queue structure. Each fragment
  222 + * being reassembled is attached to one of these structures.
  223 + * They are timed out after ipq_ttl drops to 0, and may also
  224 + * be reclaimed if memory becomes tight.
  225 + * size 28 bytes
  226 + */
  227 +struct ipq {
  228 + ipqp_32 next,prev; /* to other reass headers */
  229 + u_int8_t ipq_ttl; /* time for reass q to live */
  230 + u_int8_t ipq_p; /* protocol of this fragment */
  231 + u_int16_t ipq_id; /* sequence id for reassembly */
  232 + ipasfragp_32 ipq_next,ipq_prev;
  233 + /* to ip headers of fragments */
  234 + struct in_addr ipq_src,ipq_dst;
  235 +};
  236 +
  237 +/*
  238 + * Ip header, when holding a fragment.
  239 + *
  240 + * Note: ipf_next must be at same offset as ipq_next above
  241 + */
  242 +struct ipasfrag {
  243 +#ifdef WORDS_BIGENDIAN
  244 + u_int ip_v:4,
  245 + ip_hl:4;
  246 +#else
  247 + u_int ip_hl:4,
  248 + ip_v:4;
  249 +#endif
  250 + /* BUG : u_int changed to u_int8_t.
  251 + * sizeof(u_int)==4 on linux 2.0
  252 + */
  253 + u_int8_t ipf_mff; /* XXX overlays ip_tos: use low bit
  254 + * to avoid destroying tos (PPPDTRuu);
  255 + * copied from (ip_off&IP_MF) */
  256 + int16_t ip_len;
  257 + u_int16_t ip_id;
  258 + int16_t ip_off;
  259 + u_int8_t ip_ttl;
  260 + u_int8_t ip_p;
  261 + u_int16_t ip_sum;
  262 + ipasfragp_32 ipf_next; /* next fragment */
  263 + ipasfragp_32 ipf_prev; /* previous fragment */
  264 +};
  265 +
  266 +/*
  267 + * Structure stored in mbuf in inpcb.ip_options
  268 + * and passed to ip_output when ip options are in use.
  269 + * The actual length of the options (including ipopt_dst)
  270 + * is in m_len.
  271 + */
  272 +#define MAX_IPOPTLEN 40
  273 +
  274 +struct ipoption {
  275 + struct in_addr ipopt_dst; /* first-hop dst if source routed */
  276 + int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
  277 +};
  278 +
  279 +/*
  280 + * Structure attached to inpcb.ip_moptions and
  281 + * passed to ip_output when IP multicast options are in use.
  282 + */
  283 +
  284 +struct ipstat {
  285 + u_long ips_total; /* total packets received */
  286 + u_long ips_badsum; /* checksum bad */
  287 + u_long ips_tooshort; /* packet too short */
  288 + u_long ips_toosmall; /* not enough data */
  289 + u_long ips_badhlen; /* ip header length < data size */
  290 + u_long ips_badlen; /* ip length < ip header length */
  291 + u_long ips_fragments; /* fragments received */
  292 + u_long ips_fragdropped; /* frags dropped (dups, out of space) */
  293 + u_long ips_fragtimeout; /* fragments timed out */
  294 + u_long ips_forward; /* packets forwarded */
  295 + u_long ips_cantforward; /* packets rcvd for unreachable dest */
  296 + u_long ips_redirectsent; /* packets forwarded on same net */
  297 + u_long ips_noproto; /* unknown or unsupported protocol */
  298 + u_long ips_delivered; /* datagrams delivered to upper level*/
  299 + u_long ips_localout; /* total ip packets generated here */
  300 + u_long ips_odropped; /* lost packets due to nobufs, etc. */
  301 + u_long ips_reassembled; /* total packets reassembled ok */
  302 + u_long ips_fragmented; /* datagrams successfully fragmented */
  303 + u_long ips_ofragments; /* output fragments created */
  304 + u_long ips_cantfrag; /* don't fragment flag was set, etc. */
  305 + u_long ips_badoptions; /* error in option processing */
  306 + u_long ips_noroute; /* packets discarded due to no route */
  307 + u_long ips_badvers; /* ip version != 4 */
  308 + u_long ips_rawout; /* total raw ip packets generated */
  309 + u_long ips_unaligned; /* times the ip packet was not aligned */
  310 +};
  311 +
  312 +extern struct ipstat ipstat;
  313 +extern struct ipq ipq; /* ip reass. queue */
  314 +extern u_int16_t ip_id; /* ip packet ctr, for ids */
  315 +extern int ip_defttl; /* default IP ttl */
  316 +
  317 +#endif
... ...
slirp/ip_icmp.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1988, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
  34 + * ip_icmp.c,v 1.7 1995/05/30 08:09:42 rgrimes Exp
  35 + */
  36 +
  37 +#include "slirp.h"
  38 +#include "ip_icmp.h"
  39 +
  40 +struct icmpstat icmpstat;
  41 +
  42 +/* The message sent when emulating PING */
  43 +/* Be nice and tell them it's just a psuedo-ping packet */
  44 +char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
  45 +
  46 +/* list of actions for icmp_error() on RX of an icmp message */
  47 +static int icmp_flush[19] = {
  48 +/* ECHO REPLY (0) */ 0,
  49 + 1,
  50 + 1,
  51 +/* DEST UNREACH (3) */ 1,
  52 +/* SOURCE QUENCH (4)*/ 1,
  53 +/* REDIRECT (5) */ 1,
  54 + 1,
  55 + 1,
  56 +/* ECHO (8) */ 0,
  57 +/* ROUTERADVERT (9) */ 1,
  58 +/* ROUTERSOLICIT (10) */ 1,
  59 +/* TIME EXCEEDED (11) */ 1,
  60 +/* PARAMETER PROBLEM (12) */ 1,
  61 +/* TIMESTAMP (13) */ 0,
  62 +/* TIMESTAMP REPLY (14) */ 0,
  63 +/* INFO (15) */ 0,
  64 +/* INFO REPLY (16) */ 0,
  65 +/* ADDR MASK (17) */ 0,
  66 +/* ADDR MASK REPLY (18) */ 0
  67 +};
  68 +
  69 +/*
  70 + * Process a received ICMP message.
  71 + */
  72 +void
  73 +icmp_input(m, hlen)
  74 + struct mbuf *m;
  75 + int hlen;
  76 +{
  77 + register struct icmp *icp;
  78 + register struct ip *ip=mtod(m, struct ip *);
  79 + int icmplen=ip->ip_len;
  80 + /* int code; */
  81 +
  82 + DEBUG_CALL("icmp_input");
  83 + DEBUG_ARG("m = %lx", (long )m);
  84 + DEBUG_ARG("m_len = %d", m->m_len);
  85 +
  86 + icmpstat.icps_received++;
  87 +
  88 + /*
  89 + * Locate icmp structure in mbuf, and check
  90 + * that its not corrupted and of at least minimum length.
  91 + */
  92 + if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
  93 + icmpstat.icps_tooshort++;
  94 + freeit:
  95 + m_freem(m);
  96 + goto end_error;
  97 + }
  98 +
  99 + m->m_len -= hlen;
  100 + m->m_data += hlen;
  101 + icp = mtod(m, struct icmp *);
  102 + if (cksum(m, icmplen)) {
  103 + icmpstat.icps_checksum++;
  104 + goto freeit;
  105 + }
  106 + m->m_len += hlen;
  107 + m->m_data -= hlen;
  108 +
  109 + /* icmpstat.icps_inhist[icp->icmp_type]++; */
  110 + /* code = icp->icmp_code; */
  111 +
  112 + DEBUG_ARG("icmp_type = %d", icp->icmp_type);
  113 + switch (icp->icmp_type) {
  114 + case ICMP_ECHO:
  115 + icp->icmp_type = ICMP_ECHOREPLY;
  116 + ip->ip_len += hlen; /* since ip_input subtracts this */
  117 + if (ip->ip_dst.s_addr == our_addr.s_addr ||
  118 + (ip->ip_dst.s_addr == (special_addr.s_addr|htonl(CTL_ALIAS))) ) {
  119 + icmp_reflect(m);
  120 + } else {
  121 + struct socket *so;
  122 + struct sockaddr_in addr;
  123 + if ((so = socreate()) == NULL) goto freeit;
  124 + if(udp_attach(so) == -1) {
  125 + DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
  126 + errno,strerror(errno)));
  127 + sofree(so);
  128 + m_free(m);
  129 + goto end_error;
  130 + }
  131 + so->so_m = m;
  132 + so->so_faddr = ip->ip_dst;
  133 + so->so_fport = htons(7);
  134 + so->so_laddr = ip->ip_src;
  135 + so->so_lport = htons(9);
  136 + so->so_iptos = ip->ip_tos;
  137 + so->so_type = IPPROTO_ICMP;
  138 + so->so_state = SS_ISFCONNECTED;
  139 +
  140 + /* Send the packet */
  141 + addr.sin_family = AF_INET;
  142 + if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
  143 + /* It's an alias */
  144 + switch(ntohl(so->so_faddr.s_addr) & 0xff) {
  145 + case CTL_DNS:
  146 + addr.sin_addr = dns_addr;
  147 + break;
  148 + case CTL_ALIAS:
  149 + default:
  150 + addr.sin_addr = loopback_addr;
  151 + break;
  152 + }
  153 + } else {
  154 + addr.sin_addr = so->so_faddr;
  155 + }
  156 + addr.sin_port = so->so_fport;
  157 + if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
  158 + (struct sockaddr *)&addr, sizeof(addr)) == -1) {
  159 + DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
  160 + errno,strerror(errno)));
  161 + icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
  162 + udp_detach(so);
  163 + }
  164 + } /* if ip->ip_dst.s_addr == our_addr.s_addr */
  165 + break;
  166 + case ICMP_UNREACH:
  167 + /* XXX? report error? close socket? */
  168 + case ICMP_TIMXCEED:
  169 + case ICMP_PARAMPROB:
  170 + case ICMP_SOURCEQUENCH:
  171 + case ICMP_TSTAMP:
  172 + case ICMP_MASKREQ:
  173 + case ICMP_REDIRECT:
  174 + icmpstat.icps_notsupp++;
  175 + m_freem(m);
  176 + break;
  177 +
  178 + default:
  179 + icmpstat.icps_badtype++;
  180 + m_freem(m);
  181 + } /* swith */
  182 +
  183 +end_error:
  184 + /* m is m_free()'d xor put in a socket xor or given to ip_send */
  185 + return;
  186 +}
  187 +
  188 +
  189 +/*
  190 + * Send an ICMP message in response to a situation
  191 + *
  192 + * RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
  193 + * MUST NOT change this header information.
  194 + * MUST NOT reply to a multicast/broadcast IP address.
  195 + * MUST NOT reply to a multicast/broadcast MAC address.
  196 + * MUST reply to only the first fragment.
  197 + */
  198 +/*
  199 + * Send ICMP_UNREACH back to the source regarding msrc.
  200 + * mbuf *msrc is used as a template, but is NOT m_free()'d.
  201 + * It is reported as the bad ip packet. The header should
  202 + * be fully correct and in host byte order.
  203 + * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
  204 + * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
  205 + */
  206 +
  207 +#define ICMP_MAXDATALEN (IP_MSS-28)
  208 +void
  209 +icmp_error(msrc, type, code, minsize, message)
  210 + struct mbuf *msrc;
  211 + u_char type;
  212 + u_char code;
  213 + int minsize;
  214 + char *message;
  215 +{
  216 + unsigned hlen, shlen, s_ip_len;
  217 + register struct ip *ip;
  218 + register struct icmp *icp;
  219 + register struct mbuf *m;
  220 +
  221 + DEBUG_CALL("icmp_error");
  222 + DEBUG_ARG("msrc = %lx", (long )msrc);
  223 + DEBUG_ARG("msrc_len = %d", msrc->m_len);
  224 +
  225 + if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
  226 +
  227 + /* check msrc */
  228 + if(!msrc) goto end_error;
  229 + ip = mtod(msrc, struct ip *);
  230 +#if DEBUG
  231 + { char bufa[20], bufb[20];
  232 + strcpy(bufa, inet_ntoa(ip->ip_src));
  233 + strcpy(bufb, inet_ntoa(ip->ip_dst));
  234 + DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
  235 + }
  236 +#endif
  237 + if(ip->ip_off & IP_OFFMASK) goto end_error; /* Only reply to fragment 0 */
  238 +
  239 + shlen=ip->ip_hl << 2;
  240 + s_ip_len=ip->ip_len;
  241 + if(ip->ip_p == IPPROTO_ICMP) {
  242 + icp = (struct icmp *)((char *)ip + shlen);
  243 + /*
  244 + * Assume any unknown ICMP type is an error. This isn't
  245 + * specified by the RFC, but think about it..
  246 + */
  247 + if(icp->icmp_type>18 || icmp_flush[icp->icmp_type]) goto end_error;
  248 + }
  249 +
  250 + /* make a copy */
  251 + if(!(m=m_get())) goto end_error; /* get mbuf */
  252 + { int new_m_size;
  253 + new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
  254 + if(new_m_size>m->m_size) m_inc(m, new_m_size);
  255 + }
  256 + memcpy(m->m_data, msrc->m_data, msrc->m_len);
  257 + m->m_len = msrc->m_len; /* copy msrc to m */
  258 +
  259 + /* make the header of the reply packet */
  260 + ip = mtod(m, struct ip *);
  261 + hlen= sizeof(struct ip ); /* no options in reply */
  262 +
  263 + /* fill in icmp */
  264 + m->m_data += hlen;
  265 + m->m_len -= hlen;
  266 +
  267 + icp = mtod(m, struct icmp *);
  268 +
  269 + if(minsize) s_ip_len=shlen+ICMP_MINLEN; /* return header+8b only */
  270 + else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
  271 + s_ip_len=ICMP_MAXDATALEN;
  272 +
  273 + m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
  274 +
  275 + /* min. size = 8+sizeof(struct ip)+8 */
  276 +
  277 + icp->icmp_type = type;
  278 + icp->icmp_code = code;
  279 + icp->icmp_id = 0;
  280 + icp->icmp_seq = 0;
  281 +
  282 + memcpy(&icp->icmp_ip, msrc->m_data, s_ip_len); /* report the ip packet */
  283 + HTONS(icp->icmp_ip.ip_len);
  284 + HTONS(icp->icmp_ip.ip_id);
  285 + HTONS(icp->icmp_ip.ip_off);
  286 +
  287 +#if DEBUG
  288 + if(message) { /* DEBUG : append message to ICMP packet */
  289 + int message_len;
  290 + char *cpnt;
  291 + message_len=strlen(message);
  292 + if(message_len>ICMP_MAXDATALEN) message_len=ICMP_MAXDATALEN;
  293 + cpnt=(char *)m->m_data+m->m_len;
  294 + memcpy(cpnt, message, message_len);
  295 + m->m_len+=message_len;
  296 + }
  297 +#endif
  298 +
  299 + icp->icmp_cksum = 0;
  300 + icp->icmp_cksum = cksum(m, m->m_len);
  301 +
  302 + m->m_data -= hlen;
  303 + m->m_len += hlen;
  304 +
  305 + /* fill in ip */
  306 + ip->ip_hl = hlen >> 2;
  307 + ip->ip_len = m->m_len;
  308 +
  309 + ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
  310 +
  311 + ip->ip_ttl = MAXTTL;
  312 + ip->ip_p = IPPROTO_ICMP;
  313 + ip->ip_dst = ip->ip_src; /* ip adresses */
  314 + ip->ip_src = our_addr;
  315 +
  316 + (void ) ip_output((struct socket *)NULL, m);
  317 +
  318 + icmpstat.icps_reflect++;
  319 +
  320 +end_error:
  321 + return;
  322 +}
  323 +#undef ICMP_MAXDATALEN
  324 +
  325 +/*
  326 + * Reflect the ip packet back to the source
  327 + */
  328 +void
  329 +icmp_reflect(m)
  330 + struct mbuf *m;
  331 +{
  332 + register struct ip *ip = mtod(m, struct ip *);
  333 + int hlen = ip->ip_hl << 2;
  334 + int optlen = hlen - sizeof(struct ip );
  335 + register struct icmp *icp;
  336 +
  337 + /*
  338 + * Send an icmp packet back to the ip level,
  339 + * after supplying a checksum.
  340 + */
  341 + m->m_data += hlen;
  342 + m->m_len -= hlen;
  343 + icp = mtod(m, struct icmp *);
  344 +
  345 + icp->icmp_cksum = 0;
  346 + icp->icmp_cksum = cksum(m, ip->ip_len - hlen);
  347 +
  348 + m->m_data -= hlen;
  349 + m->m_len += hlen;
  350 +
  351 + /* fill in ip */
  352 + if (optlen > 0) {
  353 + /*
  354 + * Strip out original options by copying rest of first
  355 + * mbuf's data back, and adjust the IP length.
  356 + */
  357 + memmove((caddr_t)(ip + 1), (caddr_t)ip + hlen,
  358 + (unsigned )(m->m_len - hlen));
  359 + hlen -= optlen;
  360 + ip->ip_hl = hlen >> 2;
  361 + ip->ip_len -= optlen;
  362 + m->m_len -= optlen;
  363 + }
  364 +
  365 + ip->ip_ttl = MAXTTL;
  366 + { /* swap */
  367 + struct in_addr icmp_dst;
  368 + icmp_dst = ip->ip_dst;
  369 + ip->ip_dst = ip->ip_src;
  370 + ip->ip_src = icmp_dst;
  371 + }
  372 +
  373 + (void ) ip_output((struct socket *)NULL, m);
  374 +
  375 + icmpstat.icps_reflect++;
  376 +}
... ...
slirp/ip_icmp.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
  34 + * ip_icmp.h,v 1.4 1995/05/30 08:09:43 rgrimes Exp
  35 + */
  36 +
  37 +#ifndef _NETINET_IP_ICMP_H_
  38 +#define _NETINET_IP_ICMP_H_
  39 +
  40 +/*
  41 + * Interface Control Message Protocol Definitions.
  42 + * Per RFC 792, September 1981.
  43 + */
  44 +
  45 +typedef u_int32_t n_time;
  46 +
  47 +/*
  48 + * Structure of an icmp header.
  49 + */
  50 +struct icmp {
  51 + u_char icmp_type; /* type of message, see below */
  52 + u_char icmp_code; /* type sub code */
  53 + u_short icmp_cksum; /* ones complement cksum of struct */
  54 + union {
  55 + u_char ih_pptr; /* ICMP_PARAMPROB */
  56 + struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
  57 + struct ih_idseq {
  58 + u_short icd_id;
  59 + u_short icd_seq;
  60 + } ih_idseq;
  61 + int ih_void;
  62 +
  63 + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
  64 + struct ih_pmtu {
  65 + u_short ipm_void;
  66 + u_short ipm_nextmtu;
  67 + } ih_pmtu;
  68 + } icmp_hun;
  69 +#define icmp_pptr icmp_hun.ih_pptr
  70 +#define icmp_gwaddr icmp_hun.ih_gwaddr
  71 +#define icmp_id icmp_hun.ih_idseq.icd_id
  72 +#define icmp_seq icmp_hun.ih_idseq.icd_seq
  73 +#define icmp_void icmp_hun.ih_void
  74 +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
  75 +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
  76 + union {
  77 + struct id_ts {
  78 + n_time its_otime;
  79 + n_time its_rtime;
  80 + n_time its_ttime;
  81 + } id_ts;
  82 + struct id_ip {
  83 + struct ip idi_ip;
  84 + /* options and then 64 bits of data */
  85 + } id_ip;
  86 + u_long id_mask;
  87 + char id_data[1];
  88 + } icmp_dun;
  89 +#define icmp_otime icmp_dun.id_ts.its_otime
  90 +#define icmp_rtime icmp_dun.id_ts.its_rtime
  91 +#define icmp_ttime icmp_dun.id_ts.its_ttime
  92 +#define icmp_ip icmp_dun.id_ip.idi_ip
  93 +#define icmp_mask icmp_dun.id_mask
  94 +#define icmp_data icmp_dun.id_data
  95 +};
  96 +
  97 +/*
  98 + * Lower bounds on packet lengths for various types.
  99 + * For the error advice packets must first insure that the
  100 + * packet is large enought to contain the returned ip header.
  101 + * Only then can we do the check to see if 64 bits of packet
  102 + * data have been returned, since we need to check the returned
  103 + * ip header length.
  104 + */
  105 +#define ICMP_MINLEN 8 /* abs minimum */
  106 +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
  107 +#define ICMP_MASKLEN 12 /* address mask */
  108 +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
  109 +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
  110 + /* N.B.: must separately check that ip_hl >= 5 */
  111 +
  112 +/*
  113 + * Definition of type and code field values.
  114 + */
  115 +#define ICMP_ECHOREPLY 0 /* echo reply */
  116 +#define ICMP_UNREACH 3 /* dest unreachable, codes: */
  117 +#define ICMP_UNREACH_NET 0 /* bad net */
  118 +#define ICMP_UNREACH_HOST 1 /* bad host */
  119 +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
  120 +#define ICMP_UNREACH_PORT 3 /* bad port */
  121 +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
  122 +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
  123 +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
  124 +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
  125 +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
  126 +#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
  127 +#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
  128 +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
  129 +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
  130 +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
  131 +#define ICMP_REDIRECT 5 /* shorter route, codes: */
  132 +#define ICMP_REDIRECT_NET 0 /* for network */
  133 +#define ICMP_REDIRECT_HOST 1 /* for host */
  134 +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
  135 +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
  136 +#define ICMP_ECHO 8 /* echo service */
  137 +#define ICMP_ROUTERADVERT 9 /* router advertisement */
  138 +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
  139 +#define ICMP_TIMXCEED 11 /* time exceeded, code: */
  140 +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
  141 +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
  142 +#define ICMP_PARAMPROB 12 /* ip header bad */
  143 +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
  144 +#define ICMP_TSTAMP 13 /* timestamp request */
  145 +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
  146 +#define ICMP_IREQ 15 /* information request */
  147 +#define ICMP_IREQREPLY 16 /* information reply */
  148 +#define ICMP_MASKREQ 17 /* address mask request */
  149 +#define ICMP_MASKREPLY 18 /* address mask reply */
  150 +
  151 +#define ICMP_MAXTYPE 18
  152 +
  153 +#define ICMP_INFOTYPE(type) \
  154 + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
  155 + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
  156 + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
  157 + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
  158 + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
  159 +
  160 +void icmp_input _P((struct mbuf *, int));
  161 +void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
  162 +void icmp_reflect _P((struct mbuf *));
  163 +
  164 +#endif
... ...
slirp/ip_input.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1988, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
  34 + * ip_input.c,v 1.11 1994/11/16 10:17:08 jkh Exp
  35 + */
  36 +
  37 +/*
  38 + * Changes and additions relating to SLiRP are
  39 + * Copyright (c) 1995 Danny Gasparovski.
  40 + *
  41 + * Please read the file COPYRIGHT for the
  42 + * terms and conditions of the copyright.
  43 + */
  44 +
  45 +#include <slirp.h>
  46 +#include "ip_icmp.h"
  47 +
  48 +int ip_defttl;
  49 +struct ipstat ipstat;
  50 +struct ipq ipq;
  51 +
  52 +/*
  53 + * IP initialization: fill in IP protocol switch table.
  54 + * All protocols not implemented in kernel go to raw IP protocol handler.
  55 + */
  56 +void
  57 +ip_init()
  58 +{
  59 + ipq.next = ipq.prev = (ipqp_32)&ipq;
  60 + ip_id = tt.tv_sec & 0xffff;
  61 + udp_init();
  62 + tcp_init();
  63 + ip_defttl = IPDEFTTL;
  64 +}
  65 +
  66 +/*
  67 + * Ip input routine. Checksum and byte swap header. If fragmented
  68 + * try to reassemble. Process options. Pass to next level.
  69 + */
  70 +void
  71 +ip_input(m)
  72 + struct mbuf *m;
  73 +{
  74 + register struct ip *ip;
  75 + int hlen;
  76 +
  77 + DEBUG_CALL("ip_input");
  78 + DEBUG_ARG("m = %lx", (long)m);
  79 + DEBUG_ARG("m_len = %d", m->m_len);
  80 +
  81 + ipstat.ips_total++;
  82 +
  83 + if (m->m_len < sizeof (struct ip)) {
  84 + ipstat.ips_toosmall++;
  85 + return;
  86 + }
  87 +
  88 + ip = mtod(m, struct ip *);
  89 +
  90 + if (ip->ip_v != IPVERSION) {
  91 + ipstat.ips_badvers++;
  92 + goto bad;
  93 + }
  94 +
  95 + hlen = ip->ip_hl << 2;
  96 + if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
  97 + ipstat.ips_badhlen++; /* or packet too short */
  98 + goto bad;
  99 + }
  100 +
  101 + /* keep ip header intact for ICMP reply
  102 + * ip->ip_sum = cksum(m, hlen);
  103 + * if (ip->ip_sum) {
  104 + */
  105 + if(cksum(m,hlen)) {
  106 + ipstat.ips_badsum++;
  107 + goto bad;
  108 + }
  109 +
  110 + /*
  111 + * Convert fields to host representation.
  112 + */
  113 + NTOHS(ip->ip_len);
  114 + if (ip->ip_len < hlen) {
  115 + ipstat.ips_badlen++;
  116 + goto bad;
  117 + }
  118 + NTOHS(ip->ip_id);
  119 + NTOHS(ip->ip_off);
  120 +
  121 + /*
  122 + * Check that the amount of data in the buffers
  123 + * is as at least much as the IP header would have us expect.
  124 + * Trim mbufs if longer than we expect.
  125 + * Drop packet if shorter than we expect.
  126 + */
  127 + if (m->m_len < ip->ip_len) {
  128 + ipstat.ips_tooshort++;
  129 + goto bad;
  130 + }
  131 + /* Should drop packet if mbuf too long? hmmm... */
  132 + if (m->m_len > ip->ip_len)
  133 + m_adj(m, ip->ip_len - m->m_len);
  134 +
  135 + /* check ip_ttl for a correct ICMP reply */
  136 + if(ip->ip_ttl==0 || ip->ip_ttl==1) {
  137 + icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
  138 + goto bad;
  139 + }
  140 +
  141 + /*
  142 + * Process options and, if not destined for us,
  143 + * ship it on. ip_dooptions returns 1 when an
  144 + * error was detected (causing an icmp message
  145 + * to be sent and the original packet to be freed).
  146 + */
  147 +/* We do no IP options */
  148 +/* if (hlen > sizeof (struct ip) && ip_dooptions(m))
  149 + * goto next;
  150 + */
  151 + /*
  152 + * If offset or IP_MF are set, must reassemble.
  153 + * Otherwise, nothing need be done.
  154 + * (We could look in the reassembly queue to see
  155 + * if the packet was previously fragmented,
  156 + * but it's not worth the time; just let them time out.)
  157 + *
  158 + * XXX This should fail, don't fragment yet
  159 + */
  160 + if (ip->ip_off &~ IP_DF) {
  161 + register struct ipq *fp;
  162 + /*
  163 + * Look for queue of fragments
  164 + * of this datagram.
  165 + */
  166 + for (fp = (struct ipq *) ipq.next; fp != &ipq;
  167 + fp = (struct ipq *) fp->next)
  168 + if (ip->ip_id == fp->ipq_id &&
  169 + ip->ip_src.s_addr == fp->ipq_src.s_addr &&
  170 + ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
  171 + ip->ip_p == fp->ipq_p)
  172 + goto found;
  173 + fp = 0;
  174 + found:
  175 +
  176 + /*
  177 + * Adjust ip_len to not reflect header,
  178 + * set ip_mff if more fragments are expected,
  179 + * convert offset of this to bytes.
  180 + */
  181 + ip->ip_len -= hlen;
  182 + if (ip->ip_off & IP_MF)
  183 + ((struct ipasfrag *)ip)->ipf_mff |= 1;
  184 + else
  185 + ((struct ipasfrag *)ip)->ipf_mff &= ~1;
  186 +
  187 + ip->ip_off <<= 3;
  188 +
  189 + /*
  190 + * If datagram marked as having more fragments
  191 + * or if this is not the first fragment,
  192 + * attempt reassembly; if it succeeds, proceed.
  193 + */
  194 + if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
  195 + ipstat.ips_fragments++;
  196 + ip = ip_reass((struct ipasfrag *)ip, fp);
  197 + if (ip == 0)
  198 + return;
  199 + ipstat.ips_reassembled++;
  200 + m = dtom(ip);
  201 + } else
  202 + if (fp)
  203 + ip_freef(fp);
  204 +
  205 + } else
  206 + ip->ip_len -= hlen;
  207 +
  208 + /*
  209 + * Switch out to protocol's input routine.
  210 + */
  211 + ipstat.ips_delivered++;
  212 + switch (ip->ip_p) {
  213 + case IPPROTO_TCP:
  214 + tcp_input(m, hlen, (struct socket *)NULL);
  215 + break;
  216 + case IPPROTO_UDP:
  217 + udp_input(m, hlen);
  218 + break;
  219 + case IPPROTO_ICMP:
  220 + icmp_input(m, hlen);
  221 + break;
  222 + default:
  223 + ipstat.ips_noproto++;
  224 + m_free(m);
  225 + }
  226 + return;
  227 +bad:
  228 + m_freem(m);
  229 + return;
  230 +}
  231 +
  232 +/*
  233 + * Take incoming datagram fragment and try to
  234 + * reassemble it into whole datagram. If a chain for
  235 + * reassembly of this datagram already exists, then it
  236 + * is given as fp; otherwise have to make a chain.
  237 + */
  238 +struct ip *
  239 +ip_reass(ip, fp)
  240 + register struct ipasfrag *ip;
  241 + register struct ipq *fp;
  242 +{
  243 + register struct mbuf *m = dtom(ip);
  244 + register struct ipasfrag *q;
  245 + int hlen = ip->ip_hl << 2;
  246 + int i, next;
  247 +
  248 + DEBUG_CALL("ip_reass");
  249 + DEBUG_ARG("ip = %lx", (long)ip);
  250 + DEBUG_ARG("fp = %lx", (long)fp);
  251 + DEBUG_ARG("m = %lx", (long)m);
  252 +
  253 + /*
  254 + * Presence of header sizes in mbufs
  255 + * would confuse code below.
  256 + * Fragment m_data is concatenated.
  257 + */
  258 + m->m_data += hlen;
  259 + m->m_len -= hlen;
  260 +
  261 + /*
  262 + * If first fragment to arrive, create a reassembly queue.
  263 + */
  264 + if (fp == 0) {
  265 + struct mbuf *t;
  266 + if ((t = m_get()) == NULL) goto dropfrag;
  267 + fp = mtod(t, struct ipq *);
  268 + insque_32(fp, &ipq);
  269 + fp->ipq_ttl = IPFRAGTTL;
  270 + fp->ipq_p = ip->ip_p;
  271 + fp->ipq_id = ip->ip_id;
  272 + fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
  273 + fp->ipq_src = ((struct ip *)ip)->ip_src;
  274 + fp->ipq_dst = ((struct ip *)ip)->ip_dst;
  275 + q = (struct ipasfrag *)fp;
  276 + goto insert;
  277 + }
  278 +
  279 + /*
  280 + * Find a segment which begins after this one does.
  281 + */
  282 + for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
  283 + q = (struct ipasfrag *)q->ipf_next)
  284 + if (q->ip_off > ip->ip_off)
  285 + break;
  286 +
  287 + /*
  288 + * If there is a preceding segment, it may provide some of
  289 + * our data already. If so, drop the data from the incoming
  290 + * segment. If it provides all of our data, drop us.
  291 + */
  292 + if (q->ipf_prev != (ipasfragp_32)fp) {
  293 + i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
  294 + ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
  295 + if (i > 0) {
  296 + if (i >= ip->ip_len)
  297 + goto dropfrag;
  298 + m_adj(dtom(ip), i);
  299 + ip->ip_off += i;
  300 + ip->ip_len -= i;
  301 + }
  302 + }
  303 +
  304 + /*
  305 + * While we overlap succeeding segments trim them or,
  306 + * if they are completely covered, dequeue them.
  307 + */
  308 + while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
  309 + i = (ip->ip_off + ip->ip_len) - q->ip_off;
  310 + if (i < q->ip_len) {
  311 + q->ip_len -= i;
  312 + q->ip_off += i;
  313 + m_adj(dtom(q), i);
  314 + break;
  315 + }
  316 + q = (struct ipasfrag *) q->ipf_next;
  317 + m_freem(dtom((struct ipasfrag *) q->ipf_prev));
  318 + ip_deq((struct ipasfrag *) q->ipf_prev);
  319 + }
  320 +
  321 +insert:
  322 + /*
  323 + * Stick new segment in its place;
  324 + * check for complete reassembly.
  325 + */
  326 + ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
  327 + next = 0;
  328 + for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
  329 + q = (struct ipasfrag *) q->ipf_next) {
  330 + if (q->ip_off != next)
  331 + return (0);
  332 + next += q->ip_len;
  333 + }
  334 + if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
  335 + return (0);
  336 +
  337 + /*
  338 + * Reassembly is complete; concatenate fragments.
  339 + */
  340 + q = (struct ipasfrag *) fp->ipq_next;
  341 + m = dtom(q);
  342 +
  343 + q = (struct ipasfrag *) q->ipf_next;
  344 + while (q != (struct ipasfrag *)fp) {
  345 + struct mbuf *t;
  346 + t = dtom(q);
  347 + m_cat(m, t);
  348 + q = (struct ipasfrag *) q->ipf_next;
  349 + }
  350 +
  351 + /*
  352 + * Create header for new ip packet by
  353 + * modifying header of first packet;
  354 + * dequeue and discard fragment reassembly header.
  355 + * Make header visible.
  356 + */
  357 + ip = (struct ipasfrag *) fp->ipq_next;
  358 +
  359 + /*
  360 + * If the fragments concatenated to an mbuf that's
  361 + * bigger than the total size of the fragment, then and
  362 + * m_ext buffer was alloced. But fp->ipq_next points to
  363 + * the old buffer (in the mbuf), so we must point ip
  364 + * into the new buffer.
  365 + */
  366 + if (m->m_flags & M_EXT) {
  367 + int delta;
  368 + delta = (char *)ip - m->m_dat;
  369 + ip = (struct ipasfrag *)(m->m_ext + delta);
  370 + }
  371 +
  372 + /* DEBUG_ARG("ip = %lx", (long)ip);
  373 + * ip=(struct ipasfrag *)m->m_data; */
  374 +
  375 + ip->ip_len = next;
  376 + ip->ipf_mff &= ~1;
  377 + ((struct ip *)ip)->ip_src = fp->ipq_src;
  378 + ((struct ip *)ip)->ip_dst = fp->ipq_dst;
  379 + remque_32(fp);
  380 + (void) m_free(dtom(fp));
  381 + m = dtom(ip);
  382 + m->m_len += (ip->ip_hl << 2);
  383 + m->m_data -= (ip->ip_hl << 2);
  384 +
  385 + return ((struct ip *)ip);
  386 +
  387 +dropfrag:
  388 + ipstat.ips_fragdropped++;
  389 + m_freem(m);
  390 + return (0);
  391 +}
  392 +
  393 +/*
  394 + * Free a fragment reassembly header and all
  395 + * associated datagrams.
  396 + */
  397 +void
  398 +ip_freef(fp)
  399 + struct ipq *fp;
  400 +{
  401 + register struct ipasfrag *q, *p;
  402 +
  403 + for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
  404 + q = p) {
  405 + p = (struct ipasfrag *) q->ipf_next;
  406 + ip_deq(q);
  407 + m_freem(dtom(q));
  408 + }
  409 + remque_32(fp);
  410 + (void) m_free(dtom(fp));
  411 +}
  412 +
  413 +/*
  414 + * Put an ip fragment on a reassembly chain.
  415 + * Like insque, but pointers in middle of structure.
  416 + */
  417 +void
  418 +ip_enq(p, prev)
  419 + register struct ipasfrag *p, *prev;
  420 +{
  421 + DEBUG_CALL("ip_enq");
  422 + DEBUG_ARG("prev = %lx", (long)prev);
  423 + p->ipf_prev = (ipasfragp_32) prev;
  424 + p->ipf_next = prev->ipf_next;
  425 + ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
  426 + prev->ipf_next = (ipasfragp_32) p;
  427 +}
  428 +
  429 +/*
  430 + * To ip_enq as remque is to insque.
  431 + */
  432 +void
  433 +ip_deq(p)
  434 + register struct ipasfrag *p;
  435 +{
  436 + ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
  437 + ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
  438 +}
  439 +
  440 +/*
  441 + * IP timer processing;
  442 + * if a timer expires on a reassembly
  443 + * queue, discard it.
  444 + */
  445 +void
  446 +ip_slowtimo()
  447 +{
  448 + register struct ipq *fp;
  449 +
  450 + DEBUG_CALL("ip_slowtimo");
  451 +
  452 + fp = (struct ipq *) ipq.next;
  453 + if (fp == 0)
  454 + return;
  455 +
  456 + while (fp != &ipq) {
  457 + --fp->ipq_ttl;
  458 + fp = (struct ipq *) fp->next;
  459 + if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
  460 + ipstat.ips_fragtimeout++;
  461 + ip_freef((struct ipq *) fp->prev);
  462 + }
  463 + }
  464 +}
  465 +
  466 +/*
  467 + * Do option processing on a datagram,
  468 + * possibly discarding it if bad options are encountered,
  469 + * or forwarding it if source-routed.
  470 + * Returns 1 if packet has been forwarded/freed,
  471 + * 0 if the packet should be processed further.
  472 + */
  473 +
  474 +#ifdef notdef
  475 +
  476 +int
  477 +ip_dooptions(m)
  478 + struct mbuf *m;
  479 +{
  480 + register struct ip *ip = mtod(m, struct ip *);
  481 + register u_char *cp;
  482 + register struct ip_timestamp *ipt;
  483 + register struct in_ifaddr *ia;
  484 +/* int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; */
  485 + int opt, optlen, cnt, off, code, type, forward = 0;
  486 + struct in_addr *sin, dst;
  487 +typedef u_int32_t n_time;
  488 + n_time ntime;
  489 +
  490 + dst = ip->ip_dst;
  491 + cp = (u_char *)(ip + 1);
  492 + cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  493 + for (; cnt > 0; cnt -= optlen, cp += optlen) {
  494 + opt = cp[IPOPT_OPTVAL];
  495 + if (opt == IPOPT_EOL)
  496 + break;
  497 + if (opt == IPOPT_NOP)
  498 + optlen = 1;
  499 + else {
  500 + optlen = cp[IPOPT_OLEN];
  501 + if (optlen <= 0 || optlen > cnt) {
  502 + code = &cp[IPOPT_OLEN] - (u_char *)ip;
  503 + goto bad;
  504 + }
  505 + }
  506 + switch (opt) {
  507 +
  508 + default:
  509 + break;
  510 +
  511 + /*
  512 + * Source routing with record.
  513 + * Find interface with current destination address.
  514 + * If none on this machine then drop if strictly routed,
  515 + * or do nothing if loosely routed.
  516 + * Record interface address and bring up next address
  517 + * component. If strictly routed make sure next
  518 + * address is on directly accessible net.
  519 + */
  520 + case IPOPT_LSRR:
  521 + case IPOPT_SSRR:
  522 + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  523 + code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  524 + goto bad;
  525 + }
  526 + ipaddr.sin_addr = ip->ip_dst;
  527 + ia = (struct in_ifaddr *)
  528 + ifa_ifwithaddr((struct sockaddr *)&ipaddr);
  529 + if (ia == 0) {
  530 + if (opt == IPOPT_SSRR) {
  531 + type = ICMP_UNREACH;
  532 + code = ICMP_UNREACH_SRCFAIL;
  533 + goto bad;
  534 + }
  535 + /*
  536 + * Loose routing, and not at next destination
  537 + * yet; nothing to do except forward.
  538 + */
  539 + break;
  540 + }
  541 + off--; / * 0 origin * /
  542 + if (off > optlen - sizeof(struct in_addr)) {
  543 + /*
  544 + * End of source route. Should be for us.
  545 + */
  546 + save_rte(cp, ip->ip_src);
  547 + break;
  548 + }
  549 + /*
  550 + * locate outgoing interface
  551 + */
  552 + bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
  553 + sizeof(ipaddr.sin_addr));
  554 + if (opt == IPOPT_SSRR) {
  555 +#define INA struct in_ifaddr *
  556 +#define SA struct sockaddr *
  557 + if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
  558 + ia = (INA)ifa_ifwithnet((SA)&ipaddr);
  559 + } else
  560 + ia = ip_rtaddr(ipaddr.sin_addr);
  561 + if (ia == 0) {
  562 + type = ICMP_UNREACH;
  563 + code = ICMP_UNREACH_SRCFAIL;
  564 + goto bad;
  565 + }
  566 + ip->ip_dst = ipaddr.sin_addr;
  567 + bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  568 + (caddr_t)(cp + off), sizeof(struct in_addr));
  569 + cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  570 + /*
  571 + * Let ip_intr's mcast routing check handle mcast pkts
  572 + */
  573 + forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
  574 + break;
  575 +
  576 + case IPOPT_RR:
  577 + if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
  578 + code = &cp[IPOPT_OFFSET] - (u_char *)ip;
  579 + goto bad;
  580 + }
  581 + /*
  582 + * If no space remains, ignore.
  583 + */
  584 + off--; * 0 origin *
  585 + if (off > optlen - sizeof(struct in_addr))
  586 + break;
  587 + bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
  588 + sizeof(ipaddr.sin_addr));
  589 + /*
  590 + * locate outgoing interface; if we're the destination,
  591 + * use the incoming interface (should be same).
  592 + */
  593 + if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
  594 + (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
  595 + type = ICMP_UNREACH;
  596 + code = ICMP_UNREACH_HOST;
  597 + goto bad;
  598 + }
  599 + bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
  600 + (caddr_t)(cp + off), sizeof(struct in_addr));
  601 + cp[IPOPT_OFFSET] += sizeof(struct in_addr);
  602 + break;
  603 +
  604 + case IPOPT_TS:
  605 + code = cp - (u_char *)ip;
  606 + ipt = (struct ip_timestamp *)cp;
  607 + if (ipt->ipt_len < 5)
  608 + goto bad;
  609 + if (ipt->ipt_ptr > ipt->ipt_len - sizeof (int32_t)) {
  610 + if (++ipt->ipt_oflw == 0)
  611 + goto bad;
  612 + break;
  613 + }
  614 + sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
  615 + switch (ipt->ipt_flg) {
  616 +
  617 + case IPOPT_TS_TSONLY:
  618 + break;
  619 +
  620 + case IPOPT_TS_TSANDADDR:
  621 + if (ipt->ipt_ptr + sizeof(n_time) +
  622 + sizeof(struct in_addr) > ipt->ipt_len)
  623 + goto bad;
  624 + ipaddr.sin_addr = dst;
  625 + ia = (INA)ifaof_ i f p foraddr((SA)&ipaddr,
  626 + m->m_pkthdr.rcvif);
  627 + if (ia == 0)
  628 + continue;
  629 + bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
  630 + (caddr_t)sin, sizeof(struct in_addr));
  631 + ipt->ipt_ptr += sizeof(struct in_addr);
  632 + break;
  633 +
  634 + case IPOPT_TS_PRESPEC:
  635 + if (ipt->ipt_ptr + sizeof(n_time) +
  636 + sizeof(struct in_addr) > ipt->ipt_len)
  637 + goto bad;
  638 + bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
  639 + sizeof(struct in_addr));
  640 + if (ifa_ifwithaddr((SA)&ipaddr) == 0)
  641 + continue;
  642 + ipt->ipt_ptr += sizeof(struct in_addr);
  643 + break;
  644 +
  645 + default:
  646 + goto bad;
  647 + }
  648 + ntime = iptime();
  649 + bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
  650 + sizeof(n_time));
  651 + ipt->ipt_ptr += sizeof(n_time);
  652 + }
  653 + }
  654 + if (forward) {
  655 + ip_forward(m, 1);
  656 + return (1);
  657 + }
  658 + }
  659 + }
  660 + return (0);
  661 +bad:
  662 + /* ip->ip_len -= ip->ip_hl << 2; XXX icmp_error adds in hdr length */
  663 +
  664 +/* Not yet */
  665 + icmp_error(m, type, code, 0, 0);
  666 +
  667 + ipstat.ips_badoptions++;
  668 + return (1);
  669 +}
  670 +
  671 +#endif /* notdef */
  672 +
  673 +/*
  674 + * Strip out IP options, at higher
  675 + * level protocol in the kernel.
  676 + * Second argument is buffer to which options
  677 + * will be moved, and return value is their length.
  678 + * (XXX) should be deleted; last arg currently ignored.
  679 + */
  680 +void
  681 +ip_stripoptions(m, mopt)
  682 + register struct mbuf *m;
  683 + struct mbuf *mopt;
  684 +{
  685 + register int i;
  686 + struct ip *ip = mtod(m, struct ip *);
  687 + register caddr_t opts;
  688 + int olen;
  689 +
  690 + olen = (ip->ip_hl<<2) - sizeof (struct ip);
  691 + opts = (caddr_t)(ip + 1);
  692 + i = m->m_len - (sizeof (struct ip) + olen);
  693 + memcpy(opts, opts + olen, (unsigned)i);
  694 + m->m_len -= olen;
  695 +
  696 + ip->ip_hl = sizeof(struct ip) >> 2;
  697 +}
... ...
slirp/ip_output.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1988, 1990, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
  34 + * ip_output.c,v 1.9 1994/11/16 10:17:10 jkh Exp
  35 + */
  36 +
  37 +/*
  38 + * Changes and additions relating to SLiRP are
  39 + * Copyright (c) 1995 Danny Gasparovski.
  40 + *
  41 + * Please read the file COPYRIGHT for the
  42 + * terms and conditions of the copyright.
  43 + */
  44 +
  45 +#include <slirp.h>
  46 +
  47 +u_int16_t ip_id;
  48 +
  49 +/*
  50 + * IP output. The packet in mbuf chain m contains a skeletal IP
  51 + * header (with len, off, ttl, proto, tos, src, dst).
  52 + * The mbuf chain containing the packet will be freed.
  53 + * The mbuf opt, if present, will not be freed.
  54 + */
  55 +int
  56 +ip_output(so, m0)
  57 + struct socket *so;
  58 + struct mbuf *m0;
  59 +{
  60 + register struct ip *ip;
  61 + register struct mbuf *m = m0;
  62 + register int hlen = sizeof(struct ip );
  63 + int len, off, error = 0;
  64 +
  65 + DEBUG_CALL("ip_output");
  66 + DEBUG_ARG("so = %lx", (long)so);
  67 + DEBUG_ARG("m0 = %lx", (long)m0);
  68 +
  69 + /* We do no options */
  70 +/* if (opt) {
  71 + * m = ip_insertoptions(m, opt, &len);
  72 + * hlen = len;
  73 + * }
  74 + */
  75 + ip = mtod(m, struct ip *);
  76 + /*
  77 + * Fill in IP header.
  78 + */
  79 + ip->ip_v = IPVERSION;
  80 + ip->ip_off &= IP_DF;
  81 + ip->ip_id = htons(ip_id++);
  82 + ip->ip_hl = hlen >> 2;
  83 + ipstat.ips_localout++;
  84 +
  85 + /*
  86 + * Verify that we have any chance at all of being able to queue
  87 + * the packet or packet fragments
  88 + */
  89 + /* XXX Hmmm... */
  90 +/* if (if_queued > if_thresh && towrite <= 0) {
  91 + * error = ENOBUFS;
  92 + * goto bad;
  93 + * }
  94 + */
  95 +
  96 + /*
  97 + * If small enough for interface, can just send directly.
  98 + */
  99 + if ((u_int16_t)ip->ip_len <= if_mtu) {
  100 + ip->ip_len = htons((u_int16_t)ip->ip_len);
  101 + ip->ip_off = htons((u_int16_t)ip->ip_off);
  102 + ip->ip_sum = 0;
  103 + ip->ip_sum = cksum(m, hlen);
  104 +
  105 + if_output(so, m);
  106 + goto done;
  107 + }
  108 +
  109 + /*
  110 + * Too large for interface; fragment if possible.
  111 + * Must be able to put at least 8 bytes per fragment.
  112 + */
  113 + if (ip->ip_off & IP_DF) {
  114 + error = -1;
  115 + ipstat.ips_cantfrag++;
  116 + goto bad;
  117 + }
  118 +
  119 + len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
  120 + if (len < 8) {
  121 + error = -1;
  122 + goto bad;
  123 + }
  124 +
  125 + {
  126 + int mhlen, firstlen = len;
  127 + struct mbuf **mnext = &m->m_nextpkt;
  128 +
  129 + /*
  130 + * Loop through length of segment after first fragment,
  131 + * make new header and copy data of each part and link onto chain.
  132 + */
  133 + m0 = m;
  134 + mhlen = sizeof (struct ip);
  135 + for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
  136 + register struct ip *mhip;
  137 + m = m_get();
  138 + if (m == 0) {
  139 + error = -1;
  140 + ipstat.ips_odropped++;
  141 + goto sendorfree;
  142 + }
  143 + m->m_data += if_maxlinkhdr;
  144 + mhip = mtod(m, struct ip *);
  145 + *mhip = *ip;
  146 +
  147 + /* No options */
  148 +/* if (hlen > sizeof (struct ip)) {
  149 + * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
  150 + * mhip->ip_hl = mhlen >> 2;
  151 + * }
  152 + */
  153 + m->m_len = mhlen;
  154 + mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
  155 + if (ip->ip_off & IP_MF)
  156 + mhip->ip_off |= IP_MF;
  157 + if (off + len >= (u_int16_t)ip->ip_len)
  158 + len = (u_int16_t)ip->ip_len - off;
  159 + else
  160 + mhip->ip_off |= IP_MF;
  161 + mhip->ip_len = htons((u_int16_t)(len + mhlen));
  162 +
  163 + if (m_copy(m, m0, off, len) < 0) {
  164 + error = -1;
  165 + goto sendorfree;
  166 + }
  167 +
  168 + mhip->ip_off = htons((u_int16_t)mhip->ip_off);
  169 + mhip->ip_sum = 0;
  170 + mhip->ip_sum = cksum(m, mhlen);
  171 + *mnext = m;
  172 + mnext = &m->m_nextpkt;
  173 + ipstat.ips_ofragments++;
  174 + }
  175 + /*
  176 + * Update first fragment by trimming what's been copied out
  177 + * and updating header, then send each fragment (in order).
  178 + */
  179 + m = m0;
  180 + m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
  181 + ip->ip_len = htons((u_int16_t)m->m_len);
  182 + ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
  183 + ip->ip_sum = 0;
  184 + ip->ip_sum = cksum(m, hlen);
  185 +sendorfree:
  186 + for (m = m0; m; m = m0) {
  187 + m0 = m->m_nextpkt;
  188 + m->m_nextpkt = 0;
  189 + if (error == 0)
  190 + if_output(so, m);
  191 + else
  192 + m_freem(m);
  193 + }
  194 +
  195 + if (error == 0)
  196 + ipstat.ips_fragmented++;
  197 + }
  198 +
  199 +done:
  200 + return (error);
  201 +
  202 +bad:
  203 + m_freem(m0);
  204 + goto done;
  205 +}
... ...
slirp/libslirp.h 0 → 100644
  1 +#ifndef _LIBSLIRP_H
  2 +#define _LIBSLIRP_H
  3 +
  4 +#include <sys/select.h>
  5 +
  6 +void slirp_init(void);
  7 +
  8 +void slirp_select_fill(int *pnfds,
  9 + fd_set *readfds, fd_set *writefds, fd_set *xfds);
  10 +
  11 +void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
  12 +
  13 +void slirp_input(const uint8_t *pkt, int pkt_len);
  14 +
  15 +/* you must provide the following functions: */
  16 +int slirp_can_output(void);
  17 +void slirp_output(const uint8_t *pkt, int pkt_len);
  18 +
  19 +#endif
... ...
slirp/main.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#ifdef HAVE_SYS_SELECT_H
  9 +#include <sys/select.h>
  10 +#endif
  11 +
  12 +#define TOWRITEMAX 512
  13 +#define min(x,y) ((x) < (y) ? (x) : (y))
  14 +
  15 +extern struct timeval tt;
  16 +extern int link_up;
  17 +extern int slirp_socket;
  18 +extern int slirp_socket_unit;
  19 +extern int slirp_socket_port;
  20 +extern u_int32_t slirp_socket_addr;
  21 +extern char *slirp_socket_passwd;
  22 +extern int ctty_closed;
  23 +
  24 +/*
  25 + * Get the difference in 2 times from updtim()
  26 + * Allow for wraparound times, "just in case"
  27 + * x is the greater of the 2 (current time) and y is
  28 + * what it's being compared against.
  29 + */
  30 +#define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)
  31 +
  32 +extern char *slirp_tty;
  33 +extern char *exec_shell;
  34 +extern u_int curtime;
  35 +extern fd_set *global_readfds, *global_writefds, *global_xfds;
  36 +extern struct in_addr ctl_addr;
  37 +extern struct in_addr special_addr;
  38 +extern struct in_addr our_addr;
  39 +extern struct in_addr loopback_addr;
  40 +extern struct in_addr dns_addr;
  41 +extern char *username;
  42 +extern char *socket_path;
  43 +extern int towrite_max;
  44 +extern int ppp_exit;
  45 +extern int so_options;
  46 +extern int tcp_keepintvl;
  47 +extern uint8_t client_ethaddr[6];
  48 +
  49 +#define PROTO_SLIP 0x1
  50 +#ifdef USE_PPP
  51 +#define PROTO_PPP 0x2
  52 +#endif
  53 +
  54 +void if_encap(const uint8_t *ip_data, int ip_data_len);
... ...
slirp/mbuf.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +/*
  9 + * mbuf's in SLiRP are much simpler than the real mbufs in
  10 + * FreeBSD. They are fixed size, determined by the MTU,
  11 + * so that one whole packet can fit. Mbuf's cannot be
  12 + * chained together. If there's more data than the mbuf
  13 + * could hold, an external malloced buffer is pointed to
  14 + * by m_ext (and the data pointers) and M_EXT is set in
  15 + * the flags
  16 + */
  17 +
  18 +#include <slirp.h>
  19 +
  20 +struct mbuf *mbutl;
  21 +char *mclrefcnt;
  22 +int mbuf_alloced = 0;
  23 +struct mbuf m_freelist, m_usedlist;
  24 +int mbuf_thresh = 30;
  25 +int mbuf_max = 0;
  26 +int msize;
  27 +
  28 +void
  29 +m_init()
  30 +{
  31 + m_freelist.m_next = m_freelist.m_prev = &m_freelist;
  32 + m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
  33 + msize_init();
  34 +}
  35 +
  36 +void
  37 +msize_init()
  38 +{
  39 + /*
  40 + * Find a nice value for msize
  41 + * XXX if_maxlinkhdr already in mtu
  42 + */
  43 + msize = (if_mtu>if_mru?if_mtu:if_mru) +
  44 + if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
  45 +}
  46 +
  47 +/*
  48 + * Get an mbuf from the free list, if there are none
  49 + * malloc one
  50 + *
  51 + * Because fragmentation can occur if we alloc new mbufs and
  52 + * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
  53 + * which tells m_free to actually free() it
  54 + */
  55 +struct mbuf *
  56 +m_get()
  57 +{
  58 + register struct mbuf *m;
  59 + int flags = 0;
  60 +
  61 + DEBUG_CALL("m_get");
  62 +
  63 + if (m_freelist.m_next == &m_freelist) {
  64 + m = (struct mbuf *)malloc(msize);
  65 + if (m == NULL) goto end_error;
  66 + mbuf_alloced++;
  67 + if (mbuf_alloced > mbuf_thresh)
  68 + flags = M_DOFREE;
  69 + if (mbuf_alloced > mbuf_max)
  70 + mbuf_max = mbuf_alloced;
  71 + } else {
  72 + m = m_freelist.m_next;
  73 + remque(m);
  74 + }
  75 +
  76 + /* Insert it in the used list */
  77 + insque(m,&m_usedlist);
  78 + m->m_flags = (flags | M_USEDLIST);
  79 +
  80 + /* Initialise it */
  81 + m->m_size = msize - sizeof(struct m_hdr);
  82 + m->m_data = m->m_dat;
  83 + m->m_len = 0;
  84 + m->m_nextpkt = 0;
  85 + m->m_prevpkt = 0;
  86 +end_error:
  87 + DEBUG_ARG("m = %lx", (long )m);
  88 + return m;
  89 +}
  90 +
  91 +void
  92 +m_free(m)
  93 + struct mbuf *m;
  94 +{
  95 +
  96 + DEBUG_CALL("m_free");
  97 + DEBUG_ARG("m = %lx", (long )m);
  98 +
  99 + if(m) {
  100 + /* Remove from m_usedlist */
  101 + if (m->m_flags & M_USEDLIST)
  102 + remque(m);
  103 +
  104 + /* If it's M_EXT, free() it */
  105 + if (m->m_flags & M_EXT)
  106 + free(m->m_ext);
  107 +
  108 + /*
  109 + * Either free() it or put it on the free list
  110 + */
  111 + if (m->m_flags & M_DOFREE) {
  112 + free(m);
  113 + mbuf_alloced--;
  114 + } else if ((m->m_flags & M_FREELIST) == 0) {
  115 + insque(m,&m_freelist);
  116 + m->m_flags = M_FREELIST; /* Clobber other flags */
  117 + }
  118 + } /* if(m) */
  119 +}
  120 +
  121 +/*
  122 + * Copy data from one mbuf to the end of
  123 + * the other.. if result is too big for one mbuf, malloc()
  124 + * an M_EXT data segment
  125 + */
  126 +void
  127 +m_cat(m, n)
  128 + register struct mbuf *m, *n;
  129 +{
  130 + /*
  131 + * If there's no room, realloc
  132 + */
  133 + if (M_FREEROOM(m) < n->m_len)
  134 + m_inc(m,m->m_size+MINCSIZE);
  135 +
  136 + memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
  137 + m->m_len += n->m_len;
  138 +
  139 + m_free(n);
  140 +}
  141 +
  142 +
  143 +/* make m size bytes large */
  144 +void
  145 +m_inc(m, size)
  146 + struct mbuf *m;
  147 + int size;
  148 +{
  149 + /* some compiles throw up on gotos. This one we can fake. */
  150 + if(m->m_size>size) return;
  151 +
  152 + if (m->m_flags & M_EXT) {
  153 + /* datasize = m->m_data - m->m_ext; */
  154 + m->m_ext = (char *)realloc(m->m_ext,size);
  155 +/* if (m->m_ext == NULL)
  156 + * return (struct mbuf *)NULL;
  157 + */
  158 + /* m->m_data = m->m_ext + datasize; */
  159 + } else {
  160 + int datasize;
  161 + char *dat;
  162 + datasize = m->m_data - m->m_dat;
  163 + dat = (char *)malloc(size);
  164 +/* if (dat == NULL)
  165 + * return (struct mbuf *)NULL;
  166 + */
  167 + memcpy(dat, m->m_dat, m->m_size);
  168 +
  169 + m->m_ext = dat;
  170 + m->m_data = m->m_ext + datasize;
  171 + m->m_flags |= M_EXT;
  172 + }
  173 +
  174 + m->m_size = size;
  175 +
  176 +}
  177 +
  178 +
  179 +
  180 +void
  181 +m_adj(m, len)
  182 + struct mbuf *m;
  183 + int len;
  184 +{
  185 + if (m == NULL)
  186 + return;
  187 + if (len >= 0) {
  188 + /* Trim from head */
  189 + m->m_data += len;
  190 + m->m_len -= len;
  191 + } else {
  192 + /* Trim from tail */
  193 + len = -len;
  194 + m->m_len -= len;
  195 + }
  196 +}
  197 +
  198 +
  199 +/*
  200 + * Copy len bytes from m, starting off bytes into n
  201 + */
  202 +int
  203 +m_copy(n, m, off, len)
  204 + struct mbuf *n, *m;
  205 + int off, len;
  206 +{
  207 + if (len > M_FREEROOM(n))
  208 + return -1;
  209 +
  210 + memcpy((n->m_data + n->m_len), (m->m_data + off), len);
  211 + n->m_len += len;
  212 + return 0;
  213 +}
  214 +
  215 +
  216 +/*
  217 + * Given a pointer into an mbuf, return the mbuf
  218 + * XXX This is a kludge, I should eliminate the need for it
  219 + * Fortunately, it's not used often
  220 + */
  221 +struct mbuf *
  222 +dtom(dat)
  223 + void *dat;
  224 +{
  225 + struct mbuf *m;
  226 +
  227 + DEBUG_CALL("dtom");
  228 + DEBUG_ARG("dat = %lx", (long )dat);
  229 +
  230 + /* bug corrected for M_EXT buffers */
  231 + for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
  232 + if (m->m_flags & M_EXT) {
  233 + if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
  234 + return m;
  235 + } else {
  236 + if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
  237 + return m;
  238 + }
  239 + }
  240 +
  241 + DEBUG_ERROR((dfd, "dtom failed"));
  242 +
  243 + return (struct mbuf *)0;
  244 +}
  245 +
... ...
slirp/mbuf.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1982, 1986, 1988, 1993
  3 + * The Regents of the University of California. All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions
  7 + * are met:
  8 + * 1. Redistributions of source code must retain the above copyright
  9 + * notice, this list of conditions and the following disclaimer.
  10 + * 2. Redistributions in binary form must reproduce the above copyright
  11 + * notice, this list of conditions and the following disclaimer in the
  12 + * documentation and/or other materials provided with the distribution.
  13 + * 3. All advertising materials mentioning features or use of this software
  14 + * must display the following acknowledgement:
  15 + * This product includes software developed by the University of
  16 + * California, Berkeley and its contributors.
  17 + * 4. Neither the name of the University nor the names of its contributors
  18 + * may be used to endorse or promote products derived from this software
  19 + * without specific prior written permission.
  20 + *
  21 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24 + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31 + * SUCH DAMAGE.
  32 + *
  33 + * @(#)mbuf.h 8.3 (Berkeley) 1/21/94
  34 + * mbuf.h,v 1.9 1994/11/14 13:54:20 bde Exp
  35 + */
  36 +
  37 +#ifndef _MBUF_H_
  38 +#define _MBUF_H_
  39 +
  40 +#define m_freem m_free
  41 +
  42 +
  43 +#define MINCSIZE 4096 /* Amount to increase mbuf if too small */
  44 +
  45 +/*
  46 + * Macros for type conversion
  47 + * mtod(m,t) - convert mbuf pointer to data pointer of correct type
  48 + * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX)
  49 + */
  50 +#define mtod(m,t) ((t)(m)->m_data)
  51 +/* #define dtom(x) ((struct mbuf *)((int)(x) & ~(M_SIZE-1))) */
  52 +
  53 +/* XXX About mbufs for slirp:
  54 + * Only one mbuf is ever used in a chain, for each "cell" of data.
  55 + * m_nextpkt points to the next packet, if fragmented.
  56 + * If the data is too large, the M_EXT is used, and a larger block
  57 + * is alloced. Therefore, m_free[m] must check for M_EXT and if set
  58 + * free the m_ext. This is inefficient memory-wise, but who cares.
  59 + */
  60 +
  61 +/* XXX should union some of these! */
  62 +/* header at beginning of each mbuf: */
  63 +struct m_hdr {
  64 + struct mbuf *mh_next; /* Linked list of mbufs */
  65 + struct mbuf *mh_prev;
  66 + struct mbuf *mh_nextpkt; /* Next packet in queue/record */
  67 + struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
  68 + int mh_flags; /* Misc flags */
  69 +
  70 + int mh_size; /* Size of data */
  71 + struct socket *mh_so;
  72 +
  73 + caddr_t mh_data; /* Location of data */
  74 + int mh_len; /* Amount of data in this mbuf */
  75 +};
  76 +
  77 +/*
  78 + * How much room is in the mbuf, from m_data to the end of the mbuf
  79 + */
  80 +#define M_ROOM(m) ((m->m_flags & M_EXT)? \
  81 + (((m)->m_ext + (m)->m_size) - (m)->m_data) \
  82 + : \
  83 + (((m)->m_dat + (m)->m_size) - (m)->m_data))
  84 +
  85 +/*
  86 + * How much free room there is
  87 + */
  88 +#define M_FREEROOM(m) (M_ROOM(m) - (m)->m_len)
  89 +#define M_TRAILINGSPACE M_FREEROOM
  90 +
  91 +struct mbuf {
  92 + struct m_hdr m_hdr;
  93 + union M_dat {
  94 + char m_dat_[1]; /* ANSI don't like 0 sized arrays */
  95 + char *m_ext_;
  96 + } M_dat;
  97 +};
  98 +
  99 +#define m_next m_hdr.mh_next
  100 +#define m_prev m_hdr.mh_prev
  101 +#define m_nextpkt m_hdr.mh_nextpkt
  102 +#define m_prevpkt m_hdr.mh_prevpkt
  103 +#define m_flags m_hdr.mh_flags
  104 +#define m_len m_hdr.mh_len
  105 +#define m_data m_hdr.mh_data
  106 +#define m_size m_hdr.mh_size
  107 +#define m_dat M_dat.m_dat_
  108 +#define m_ext M_dat.m_ext_
  109 +#define m_so m_hdr.mh_so
  110 +
  111 +#define ifq_prev m_prev
  112 +#define ifq_next m_next
  113 +#define ifs_prev m_prevpkt
  114 +#define ifs_next m_nextpkt
  115 +#define ifq_so m_so
  116 +
  117 +#define M_EXT 0x01 /* m_ext points to more (malloced) data */
  118 +#define M_FREELIST 0x02 /* mbuf is on free list */
  119 +#define M_USEDLIST 0x04 /* XXX mbuf is on used list (for dtom()) */
  120 +#define M_DOFREE 0x08 /* when m_free is called on the mbuf, free()
  121 + * it rather than putting it on the free list */
  122 +
  123 +/*
  124 + * Mbuf statistics. XXX
  125 + */
  126 +
  127 +struct mbstat {
  128 + int mbs_alloced; /* Number of mbufs allocated */
  129 +
  130 +};
  131 +
  132 +extern struct mbstat mbstat;
  133 +extern int mbuf_alloced;
  134 +extern struct mbuf m_freelist, m_usedlist;
  135 +extern int mbuf_max;
  136 +
  137 +void m_init _P((void));
  138 +void msize_init _P((void));
  139 +struct mbuf * m_get _P((void));
  140 +void m_free _P((struct mbuf *));
  141 +void m_cat _P((register struct mbuf *, register struct mbuf *));
  142 +void m_inc _P((struct mbuf *, int));
  143 +void m_adj _P((struct mbuf *, int));
  144 +int m_copy _P((struct mbuf *, struct mbuf *, int, int));
  145 +struct mbuf * dtom _P((void *));
  146 +
  147 +#endif
... ...
slirp/misc.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#define WANT_SYS_IOCTL_H
  9 +#include <slirp.h>
  10 +
  11 +u_int curtime, time_fasttimo, last_slowtimo, detach_time;
  12 +u_int detach_wait = 600000; /* 10 minutes */
  13 +
  14 +#if 0
  15 +int x_port = -1;
  16 +int x_display = 0;
  17 +int x_screen = 0;
  18 +
  19 +int
  20 +show_x(buff, inso)
  21 + char *buff;
  22 + struct socket *inso;
  23 +{
  24 + if (x_port < 0) {
  25 + lprint("X Redir: X not being redirected.\r\n");
  26 + } else {
  27 + lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
  28 + inet_ntoa(our_addr), x_port, x_screen);
  29 + lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n",
  30 + inet_ntoa(our_addr), x_port, x_screen);
  31 + if (x_display)
  32 + lprint("X Redir: Redirecting to display %d\r\n", x_display);
  33 + }
  34 +
  35 + return CFG_OK;
  36 +}
  37 +
  38 +
  39 +/*
  40 + * XXX Allow more than one X redirection?
  41 + */
  42 +void
  43 +redir_x(inaddr, start_port, display, screen)
  44 + u_int32_t inaddr;
  45 + int start_port;
  46 + int display;
  47 + int screen;
  48 +{
  49 + int i;
  50 +
  51 + if (x_port >= 0) {
  52 + lprint("X Redir: X already being redirected.\r\n");
  53 + show_x(0, 0);
  54 + } else {
  55 + for (i = 6001 + (start_port-1); i <= 6100; i++) {
  56 + if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
  57 + /* Success */
  58 + x_port = i - 6000;
  59 + x_display = display;
  60 + x_screen = screen;
  61 + show_x(0, 0);
  62 + return;
  63 + }
  64 + }
  65 + lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
  66 + }
  67 +}
  68 +#endif
  69 +
  70 +#ifndef HAVE_INET_ATON
  71 +int
  72 +inet_aton(cp, ia)
  73 + const char *cp;
  74 + struct in_addr *ia;
  75 +{
  76 + u_int32_t addr = inet_addr(cp);
  77 + if (addr == 0xffffffff)
  78 + return 0;
  79 + ia->s_addr = addr;
  80 + return 1;
  81 +}
  82 +#endif
  83 +
  84 +/*
  85 + * Get our IP address and put it in our_addr
  86 + */
  87 +void
  88 +getouraddr()
  89 +{
  90 + char buff[256];
  91 + struct hostent *he;
  92 +
  93 + if (gethostname(buff,256) < 0)
  94 + return;
  95 +
  96 + if ((he = gethostbyname(buff)) == NULL)
  97 + return;
  98 +
  99 + our_addr = *(struct in_addr *)he->h_addr;
  100 +}
  101 +
  102 +#if SIZEOF_CHAR_P == 8
  103 +
  104 +struct quehead_32 {
  105 + u_int32_t qh_link;
  106 + u_int32_t qh_rlink;
  107 +};
  108 +
  109 +inline void
  110 +insque_32(a, b)
  111 + void *a;
  112 + void *b;
  113 +{
  114 + register struct quehead_32 *element = (struct quehead_32 *) a;
  115 + register struct quehead_32 *head = (struct quehead_32 *) b;
  116 + element->qh_link = head->qh_link;
  117 + head->qh_link = (u_int32_t)element;
  118 + element->qh_rlink = (u_int32_t)head;
  119 + ((struct quehead_32 *)(element->qh_link))->qh_rlink
  120 + = (u_int32_t)element;
  121 +}
  122 +
  123 +inline void
  124 +remque_32(a)
  125 + void *a;
  126 +{
  127 + register struct quehead_32 *element = (struct quehead_32 *) a;
  128 + ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
  129 + ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
  130 + element->qh_rlink = 0;
  131 +}
  132 +
  133 +#endif /* SIZEOF_CHAR_P == 8 */
  134 +
  135 +struct quehead {
  136 + struct quehead *qh_link;
  137 + struct quehead *qh_rlink;
  138 +};
  139 +
  140 +inline void
  141 +insque(a, b)
  142 + void *a, *b;
  143 +{
  144 + register struct quehead *element = (struct quehead *) a;
  145 + register struct quehead *head = (struct quehead *) b;
  146 + element->qh_link = head->qh_link;
  147 + head->qh_link = (struct quehead *)element;
  148 + element->qh_rlink = (struct quehead *)head;
  149 + ((struct quehead *)(element->qh_link))->qh_rlink
  150 + = (struct quehead *)element;
  151 +}
  152 +
  153 +inline void
  154 +remque(a)
  155 + void *a;
  156 +{
  157 + register struct quehead *element = (struct quehead *) a;
  158 + ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
  159 + ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
  160 + element->qh_rlink = NULL;
  161 + /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
  162 +}
  163 +
  164 +/* #endif */
  165 +
  166 +
  167 +int
  168 +add_exec(ex_ptr, do_pty, exec, addr, port)
  169 + struct ex_list **ex_ptr;
  170 + int do_pty;
  171 + char *exec;
  172 + int addr;
  173 + int port;
  174 +{
  175 + struct ex_list *tmp_ptr;
  176 +
  177 + /* First, check if the port is "bound" */
  178 + for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
  179 + if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
  180 + return -1;
  181 + }
  182 +
  183 + tmp_ptr = *ex_ptr;
  184 + *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
  185 + (*ex_ptr)->ex_fport = port;
  186 + (*ex_ptr)->ex_addr = addr;
  187 + (*ex_ptr)->ex_pty = do_pty;
  188 + (*ex_ptr)->ex_exec = strdup(exec);
  189 + (*ex_ptr)->ex_next = tmp_ptr;
  190 + return 0;
  191 +}
  192 +
  193 +#ifndef HAVE_STRERROR
  194 +
  195 +/*
  196 + * For systems with no strerror
  197 + */
  198 +
  199 +extern int sys_nerr;
  200 +extern char *sys_errlist[];
  201 +
  202 +char *
  203 +strerror(error)
  204 + int error;
  205 +{
  206 + if (error < sys_nerr)
  207 + return sys_errlist[error];
  208 + else
  209 + return "Unknown error.";
  210 +}
  211 +
  212 +#endif
  213 +
  214 +
  215 +#if 0
  216 +int
  217 +openpty(amaster, aslave)
  218 + int *amaster, *aslave;
  219 +{
  220 + register int master, slave;
  221 +
  222 +#ifdef HAVE_GRANTPT
  223 + char *ptr;
  224 +
  225 + if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
  226 + grantpt(master) < 0 ||
  227 + unlockpt(master) < 0 ||
  228 + (ptr = ptsname(master)) == NULL) {
  229 + close(master);
  230 + return -1;
  231 + }
  232 +
  233 + if ((slave = open(ptr, O_RDWR)) < 0 ||
  234 + ioctl(slave, I_PUSH, "ptem") < 0 ||
  235 + ioctl(slave, I_PUSH, "ldterm") < 0 ||
  236 + ioctl(slave, I_PUSH, "ttcompat") < 0) {
  237 + close(master);
  238 + close(slave);
  239 + return -1;
  240 + }
  241 +
  242 + *amaster = master;
  243 + *aslave = slave;
  244 + return 0;
  245 +
  246 +#else
  247 +
  248 + static char line[] = "/dev/ptyXX";
  249 + register const char *cp1, *cp2;
  250 +
  251 + for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
  252 + line[8] = *cp1;
  253 + for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
  254 + line[9] = *cp2;
  255 + if ((master = open(line, O_RDWR, 0)) == -1) {
  256 + if (errno == ENOENT)
  257 + return (-1); /* out of ptys */
  258 + } else {
  259 + line[5] = 't';
  260 + /* These will fail */
  261 + (void) chown(line, getuid(), 0);
  262 + (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
  263 +#ifdef HAVE_REVOKE
  264 + (void) revoke(line);
  265 +#endif
  266 + if ((slave = open(line, O_RDWR, 0)) != -1) {
  267 + *amaster = master;
  268 + *aslave = slave;
  269 + return 0;
  270 + }
  271 + (void) close(master);
  272 + line[5] = 'p';
  273 + }
  274 + }
  275 + }
  276 + errno = ENOENT; /* out of ptys */
  277 + return (-1);
  278 +#endif
  279 +}
  280 +
  281 +/*
  282 + * XXX This is ugly
  283 + * We create and bind a socket, then fork off to another
  284 + * process, which connects to this socket, after which we
  285 + * exec the wanted program. If something (strange) happens,
  286 + * the accept() call could block us forever.
  287 + *
  288 + * do_pty = 0 Fork/exec inetd style
  289 + * do_pty = 1 Fork/exec using slirp.telnetd
  290 + * do_ptr = 2 Fork/exec using pty
  291 + */
  292 +int
  293 +fork_exec(so, ex, do_pty)
  294 + struct socket *so;
  295 + char *ex;
  296 + int do_pty;
  297 +{
  298 + int s;
  299 + struct sockaddr_in addr;
  300 + int addrlen = sizeof(addr);
  301 + int opt;
  302 + int master;
  303 + char *argv[256];
  304 + char buff[256];
  305 + /* don't want to clobber the original */
  306 + char *bptr;
  307 + char *curarg;
  308 + int c, i;
  309 +
  310 + DEBUG_CALL("fork_exec");
  311 + DEBUG_ARG("so = %lx", (long)so);
  312 + DEBUG_ARG("ex = %lx", (long)ex);
  313 + DEBUG_ARG("do_pty = %lx", (long)do_pty);
  314 +
  315 + if (do_pty == 2) {
  316 + if (openpty(&master, &s) == -1) {
  317 + lprint("Error: openpty failed: %s\n", strerror(errno));
  318 + return 0;
  319 + }
  320 + } else {
  321 + addr.sin_family = AF_INET;
  322 + addr.sin_port = 0;
  323 + addr.sin_addr.s_addr = INADDR_ANY;
  324 +
  325 + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
  326 + bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
  327 + listen(s, 1) < 0) {
  328 + lprint("Error: inet socket: %s\n", strerror(errno));
  329 + close(s);
  330 +
  331 + return 0;
  332 + }
  333 + }
  334 +
  335 + switch(fork()) {
  336 + case -1:
  337 + lprint("Error: fork failed: %s\n", strerror(errno));
  338 + close(s);
  339 + if (do_pty == 2)
  340 + close(master);
  341 + return 0;
  342 +
  343 + case 0:
  344 + /* Set the DISPLAY */
  345 + if (do_pty == 2) {
  346 + (void) close(master);
  347 +#ifdef TIOCSCTTY /* XXXXX */
  348 + (void) setsid();
  349 + ioctl(s, TIOCSCTTY, (char *)NULL);
  350 +#endif
  351 + } else {
  352 + getsockname(s, (struct sockaddr *)&addr, &addrlen);
  353 + close(s);
  354 + /*
  355 + * Connect to the socket
  356 + * XXX If any of these fail, we're in trouble!
  357 + */
  358 + s = socket(AF_INET, SOCK_STREAM, 0);
  359 + addr.sin_addr = loopback_addr;
  360 + connect(s, (struct sockaddr *)&addr, addrlen);
  361 + }
  362 +
  363 + if (x_port >= 0) {
  364 +#ifdef HAVE_SETENV
  365 + sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
  366 + setenv("DISPLAY", buff, 1);
  367 +#else
  368 + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
  369 + putenv(buff);
  370 +#endif
  371 + }
  372 +
  373 + dup2(s, 0);
  374 + dup2(s, 1);
  375 + dup2(s, 2);
  376 + for (s = 3; s <= 255; s++)
  377 + close(s);
  378 +
  379 + i = 0;
  380 + bptr = strdup(ex); /* No need to free() this */
  381 + if (do_pty == 1) {
  382 + /* Setup "slirp.telnetd -x" */
  383 + argv[i++] = "slirp.telnetd";
  384 + argv[i++] = "-x";
  385 + argv[i++] = bptr;
  386 + } else
  387 + do {
  388 + /* Change the string into argv[] */
  389 + curarg = bptr;
  390 + while (*bptr != ' ' && *bptr != (char)0)
  391 + bptr++;
  392 + c = *bptr;
  393 + *bptr++ = (char)0;
  394 + argv[i++] = strdup(curarg);
  395 + } while (c);
  396 +
  397 + argv[i] = 0;
  398 + execvp(argv[0], argv);
  399 +
  400 + /* Ooops, failed, let's tell the user why */
  401 + {
  402 + char buff[256];
  403 +
  404 + sprintf(buff, "Error: execvp of %s failed: %s\n",
  405 + argv[0], strerror(errno));
  406 + write(2, buff, strlen(buff)+1);
  407 + }
  408 + close(0); close(1); close(2); /* XXX */
  409 + exit(1);
  410 +
  411 + default:
  412 + if (do_pty == 2) {
  413 + close(s);
  414 + so->s = master;
  415 + } else {
  416 + /*
  417 + * XXX this could block us...
  418 + * XXX Should set a timer here, and if accept() doesn't
  419 + * return after X seconds, declare it a failure
  420 + * The only reason this will block forever is if socket()
  421 + * of connect() fail in the child process
  422 + */
  423 + so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
  424 + close(s);
  425 + opt = 1;
  426 + setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
  427 + opt = 1;
  428 + setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
  429 + }
  430 + fd_nonblock(so->s);
  431 +
  432 + /* Append the telnet options now */
  433 + if (so->so_m != 0 && do_pty == 1) {
  434 + sbappend(so, so->so_m);
  435 + so->so_m = 0;
  436 + }
  437 +
  438 + return 1;
  439 + }
  440 +}
  441 +#endif
  442 +
  443 +#ifndef HAVE_STRDUP
  444 +char *
  445 +strdup(str)
  446 + const char *str;
  447 +{
  448 + char *bptr;
  449 +
  450 + bptr = (char *)malloc(strlen(str)+1);
  451 + strcpy(bptr, str);
  452 +
  453 + return bptr;
  454 +}
  455 +#endif
  456 +
  457 +#if 0
  458 +void
  459 +snooze_hup(num)
  460 + int num;
  461 +{
  462 + int s, ret;
  463 +#ifndef NO_UNIX_SOCKETS
  464 + struct sockaddr_un sock_un;
  465 +#endif
  466 + struct sockaddr_in sock_in;
  467 + char buff[256];
  468 +
  469 + ret = -1;
  470 + if (slirp_socket_passwd) {
  471 + s = socket(AF_INET, SOCK_STREAM, 0);
  472 + if (s < 0)
  473 + slirp_exit(1);
  474 + sock_in.sin_family = AF_INET;
  475 + sock_in.sin_addr.s_addr = slirp_socket_addr;
  476 + sock_in.sin_port = htons(slirp_socket_port);
  477 + if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
  478 + slirp_exit(1); /* just exit...*/
  479 + sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
  480 + write(s, buff, strlen(buff)+1);
  481 + }
  482 +#ifndef NO_UNIX_SOCKETS
  483 + else {
  484 + s = socket(AF_UNIX, SOCK_STREAM, 0);
  485 + if (s < 0)
  486 + slirp_exit(1);
  487 + sock_un.sun_family = AF_UNIX;
  488 + strcpy(sock_un.sun_path, socket_path);
  489 + if (connect(s, (struct sockaddr *)&sock_un,
  490 + sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
  491 + slirp_exit(1);
  492 + sprintf(buff, "kill none:%d", slirp_socket_unit);
  493 + write(s, buff, strlen(buff)+1);
  494 + }
  495 +#endif
  496 + slirp_exit(0);
  497 +}
  498 +
  499 +
  500 +void
  501 +snooze()
  502 +{
  503 + sigset_t s;
  504 + int i;
  505 +
  506 + /* Don't need our data anymore */
  507 + /* XXX This makes SunOS barf */
  508 +/* brk(0); */
  509 +
  510 + /* Close all fd's */
  511 + for (i = 255; i >= 0; i--)
  512 + close(i);
  513 +
  514 + signal(SIGQUIT, slirp_exit);
  515 + signal(SIGHUP, snooze_hup);
  516 + sigemptyset(&s);
  517 +
  518 + /* Wait for any signal */
  519 + sigsuspend(&s);
  520 +
  521 + /* Just in case ... */
  522 + exit(255);
  523 +}
  524 +
  525 +void
  526 +relay(s)
  527 + int s;
  528 +{
  529 + char buf[8192];
  530 + int n;
  531 + fd_set readfds;
  532 + struct ttys *ttyp;
  533 +
  534 + /* Don't need our data anymore */
  535 + /* XXX This makes SunOS barf */
  536 +/* brk(0); */
  537 +
  538 + signal(SIGQUIT, slirp_exit);
  539 + signal(SIGHUP, slirp_exit);
  540 + signal(SIGINT, slirp_exit);
  541 + signal(SIGTERM, slirp_exit);
  542 +
  543 + /* Fudge to get term_raw and term_restore to work */
  544 + if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
  545 + lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
  546 + slirp_exit (1);
  547 + }
  548 + ttyp->fd = 0;
  549 + ttyp->flags |= TTY_CTTY;
  550 + term_raw(ttyp);
  551 +
  552 + while (1) {
  553 + FD_ZERO(&readfds);
  554 +
  555 + FD_SET(0, &readfds);
  556 + FD_SET(s, &readfds);
  557 +
  558 + n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
  559 +
  560 + if (n <= 0)
  561 + slirp_exit(0);
  562 +
  563 + if (FD_ISSET(0, &readfds)) {
  564 + n = read(0, buf, 8192);
  565 + if (n <= 0)
  566 + slirp_exit(0);
  567 + n = writen(s, buf, n);
  568 + if (n <= 0)
  569 + slirp_exit(0);
  570 + }
  571 +
  572 + if (FD_ISSET(s, &readfds)) {
  573 + n = read(s, buf, 8192);
  574 + if (n <= 0)
  575 + slirp_exit(0);
  576 + n = writen(0, buf, n);
  577 + if (n <= 0)
  578 + slirp_exit(0);
  579 + }
  580 + }
  581 +
  582 + /* Just in case.... */
  583 + exit(1);
  584 +}
  585 +#endif
  586 +
  587 +int (*lprint_print) _P((void *, const char *, va_list));
  588 +char *lprint_ptr, *lprint_ptr2, **lprint_arg;
  589 +
  590 +void
  591 +#ifdef __STDC__
  592 +lprint(const char *format, ...)
  593 +#else
  594 +lprint(va_alist) va_dcl
  595 +#endif
  596 +{
  597 + va_list args;
  598 +
  599 +#ifdef __STDC__
  600 + va_start(args, format);
  601 +#else
  602 + char *format;
  603 + va_start(args);
  604 + format = va_arg(args, char *);
  605 +#endif
  606 +#if 0
  607 + /* If we're printing to an sbuf, make sure there's enough room */
  608 + /* XXX +100? */
  609 + if (lprint_sb) {
  610 + if ((lprint_ptr - lprint_sb->sb_wptr) >=
  611 + (lprint_sb->sb_datalen - (strlen(format) + 100))) {
  612 + int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
  613 + int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
  614 + int deltap = lprint_ptr - lprint_sb->sb_data;
  615 +
  616 + lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
  617 + lprint_sb->sb_datalen + TCP_SNDSPACE);
  618 +
  619 + /* Adjust all values */
  620 + lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
  621 + lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
  622 + lprint_ptr = lprint_sb->sb_data + deltap;
  623 +
  624 + lprint_sb->sb_datalen += TCP_SNDSPACE;
  625 + }
  626 + }
  627 +#endif
  628 + if (lprint_print)
  629 + lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
  630 +
  631 + /* Check if they want output to be logged to file as well */
  632 + if (lfd) {
  633 + /*
  634 + * Remove \r's
  635 + * otherwise you'll get ^M all over the file
  636 + */
  637 + int len = strlen(format);
  638 + char *bptr1, *bptr2;
  639 +
  640 + bptr1 = bptr2 = strdup(format);
  641 +
  642 + while (len--) {
  643 + if (*bptr1 == '\r')
  644 + memcpy(bptr1, bptr1+1, len+1);
  645 + else
  646 + bptr1++;
  647 + }
  648 + vfprintf(lfd, bptr2, args);
  649 + free(bptr2);
  650 + }
  651 + va_end(args);
  652 +}
  653 +
  654 +void
  655 +add_emu(buff)
  656 + char *buff;
  657 +{
  658 + u_int lport, fport;
  659 + u_int8_t tos = 0, emu = 0;
  660 + char buff1[256], buff2[256], buff4[128];
  661 + char *buff3 = buff4;
  662 + struct emu_t *emup;
  663 + struct socket *so;
  664 +
  665 + if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
  666 + lprint("Error: Bad arguments\r\n");
  667 + return;
  668 + }
  669 +
  670 + if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
  671 + lport = 0;
  672 + if (sscanf(buff1, "%d", &fport) != 1) {
  673 + lprint("Error: Bad first argument\r\n");
  674 + return;
  675 + }
  676 + }
  677 +
  678 + if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
  679 + buff3 = 0;
  680 + if (sscanf(buff2, "%256s", buff1) != 1) {
  681 + lprint("Error: Bad second argument\r\n");
  682 + return;
  683 + }
  684 + }
  685 +
  686 + if (buff3) {
  687 + if (strcmp(buff3, "lowdelay") == 0)
  688 + tos = IPTOS_LOWDELAY;
  689 + else if (strcmp(buff3, "throughput") == 0)
  690 + tos = IPTOS_THROUGHPUT;
  691 + else {
  692 + lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
  693 + return;
  694 + }
  695 + }
  696 +
  697 + if (strcmp(buff1, "ftp") == 0)
  698 + emu = EMU_FTP;
  699 + else if (strcmp(buff1, "irc") == 0)
  700 + emu = EMU_IRC;
  701 + else if (strcmp(buff1, "none") == 0)
  702 + emu = EMU_NONE; /* ie: no emulation */
  703 + else {
  704 + lprint("Error: Unknown service\r\n");
  705 + return;
  706 + }
  707 +
  708 + /* First, check that it isn't already emulated */
  709 + for (emup = tcpemu; emup; emup = emup->next) {
  710 + if (emup->lport == lport && emup->fport == fport) {
  711 + lprint("Error: port already emulated\r\n");
  712 + return;
  713 + }
  714 + }
  715 +
  716 + /* link it */
  717 + emup = (struct emu_t *)malloc(sizeof (struct emu_t));
  718 + emup->lport = (u_int16_t)lport;
  719 + emup->fport = (u_int16_t)fport;
  720 + emup->tos = tos;
  721 + emup->emu = emu;
  722 + emup->next = tcpemu;
  723 + tcpemu = emup;
  724 +
  725 + /* And finally, mark all current sessions, if any, as being emulated */
  726 + for (so = tcb.so_next; so != &tcb; so = so->so_next) {
  727 + if ((lport && lport == ntohs(so->so_lport)) ||
  728 + (fport && fport == ntohs(so->so_fport))) {
  729 + if (emu)
  730 + so->so_emu = emu;
  731 + if (tos)
  732 + so->so_iptos = tos;
  733 + }
  734 + }
  735 +
  736 + lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
  737 +}
  738 +
  739 +#ifdef BAD_SPRINTF
  740 +
  741 +#undef vsprintf
  742 +#undef sprintf
  743 +
  744 +/*
  745 + * Some BSD-derived systems have a sprintf which returns char *
  746 + */
  747 +
  748 +int
  749 +vsprintf_len(string, format, args)
  750 + char *string;
  751 + const char *format;
  752 + va_list args;
  753 +{
  754 + vsprintf(string, format, args);
  755 + return strlen(string);
  756 +}
  757 +
  758 +int
  759 +#ifdef __STDC__
  760 +sprintf_len(char *string, const char *format, ...)
  761 +#else
  762 +sprintf_len(va_alist) va_dcl
  763 +#endif
  764 +{
  765 + va_list args;
  766 +#ifdef __STDC__
  767 + va_start(args, format);
  768 +#else
  769 + char *string;
  770 + char *format;
  771 + va_start(args);
  772 + string = va_arg(args, char *);
  773 + format = va_arg(args, char *);
  774 +#endif
  775 + vsprintf(string, format, args);
  776 + return strlen(string);
  777 +}
  778 +
  779 +#endif
  780 +
  781 +void
  782 +u_sleep(usec)
  783 + int usec;
  784 +{
  785 + struct timeval t;
  786 + fd_set fdset;
  787 +
  788 + FD_ZERO(&fdset);
  789 +
  790 + t.tv_sec = 0;
  791 + t.tv_usec = usec * 1000;
  792 +
  793 + select(0, &fdset, &fdset, &fdset, &t);
  794 +}
  795 +
  796 +/*
  797 + * Set fd blocking and non-blocking
  798 + */
  799 +
  800 +void
  801 +fd_nonblock(fd)
  802 + int fd;
  803 +{
  804 +#ifdef FIONBIO
  805 + int opt = 1;
  806 +
  807 + ioctl(fd, FIONBIO, &opt);
  808 +#else
  809 + int opt;
  810 +
  811 + opt = fcntl(fd, F_GETFL, 0);
  812 + opt |= O_NONBLOCK;
  813 + fcntl(fd, F_SETFL, opt);
  814 +#endif
  815 +}
  816 +
  817 +void
  818 +fd_block(fd)
  819 + int fd;
  820 +{
  821 +#ifdef FIONBIO
  822 + int opt = 0;
  823 +
  824 + ioctl(fd, FIONBIO, &opt);
  825 +#else
  826 + int opt;
  827 +
  828 + opt = fcntl(fd, F_GETFL, 0);
  829 + opt &= ~O_NONBLOCK;
  830 + fcntl(fd, F_SETFL, opt);
  831 +#endif
  832 +}
  833 +
  834 +
  835 +#if 0
  836 +/*
  837 + * invoke RSH
  838 + */
  839 +int
  840 +rsh_exec(so,ns, user, host, args)
  841 + struct socket *so;
  842 + struct socket *ns;
  843 + char *user;
  844 + char *host;
  845 + char *args;
  846 +{
  847 + int fd[2];
  848 + int fd0[2];
  849 + int s;
  850 + char buff[256];
  851 +
  852 + DEBUG_CALL("rsh_exec");
  853 + DEBUG_ARG("so = %lx", (long)so);
  854 +
  855 + if (pipe(fd)<0) {
  856 + lprint("Error: pipe failed: %s\n", strerror(errno));
  857 + return 0;
  858 + }
  859 +/* #ifdef HAVE_SOCKETPAIR */
  860 +#if 1
  861 + if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
  862 + close(fd[0]);
  863 + close(fd[1]);
  864 + lprint("Error: openpty failed: %s\n", strerror(errno));
  865 + return 0;
  866 + }
  867 +#else
  868 + if (openpty(&fd0[0], &fd0[1]) == -1) {
  869 + close(fd[0]);
  870 + close(fd[1]);
  871 + lprint("Error: openpty failed: %s\n", strerror(errno));
  872 + return 0;
  873 + }
  874 +#endif
  875 +
  876 + switch(fork()) {
  877 + case -1:
  878 + lprint("Error: fork failed: %s\n", strerror(errno));
  879 + close(fd[0]);
  880 + close(fd[1]);
  881 + close(fd0[0]);
  882 + close(fd0[1]);
  883 + return 0;
  884 +
  885 + case 0:
  886 + close(fd[0]);
  887 + close(fd0[0]);
  888 +
  889 + /* Set the DISPLAY */
  890 + if (x_port >= 0) {
  891 +#ifdef HAVE_SETENV
  892 + sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
  893 + setenv("DISPLAY", buff, 1);
  894 +#else
  895 + sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
  896 + putenv(buff);
  897 +#endif
  898 + }
  899 +
  900 + dup2(fd0[1], 0);
  901 + dup2(fd0[1], 1);
  902 + dup2(fd[1], 2);
  903 + for (s = 3; s <= 255; s++)
  904 + close(s);
  905 +
  906 + execlp("rsh","rsh","-l", user, host, args, NULL);
  907 +
  908 + /* Ooops, failed, let's tell the user why */
  909 +
  910 + sprintf(buff, "Error: execlp of %s failed: %s\n",
  911 + "rsh", strerror(errno));
  912 + write(2, buff, strlen(buff)+1);
  913 + close(0); close(1); close(2); /* XXX */
  914 + exit(1);
  915 +
  916 + default:
  917 + close(fd[1]);
  918 + close(fd0[1]);
  919 + ns->s=fd[0];
  920 + so->s=fd0[0];
  921 +
  922 + return 1;
  923 + }
  924 +}
  925 +#endif
... ...
slirp/misc.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#ifndef _MISC_H_
  9 +#define _MISC_H_
  10 +
  11 +struct ex_list {
  12 + int ex_pty; /* Do we want a pty? */
  13 + int ex_addr; /* The last byte of the address */
  14 + int ex_fport; /* Port to telnet to */
  15 + char *ex_exec; /* Command line of what to exec */
  16 + struct ex_list *ex_next;
  17 +};
  18 +
  19 +extern struct ex_list *exec_list;
  20 +extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
  21 +
  22 +extern int (*lprint_print) _P((void *, const char *, va_list));
  23 +extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
  24 +extern struct sbuf *lprint_sb;
  25 +
  26 +#ifndef HAVE_STRDUP
  27 +char *strdup _P((const char *));
  28 +#endif
  29 +
  30 +void do_wait _P((int));
  31 +
  32 +#define EMU_NONE 0x0
  33 +
  34 +/* TCP emulations */
  35 +#define EMU_CTL 0x1
  36 +#define EMU_FTP 0x2
  37 +#define EMU_KSH 0x3
  38 +#define EMU_IRC 0x4
  39 +#define EMU_REALAUDIO 0x5
  40 +#define EMU_RLOGIN 0x6
  41 +#define EMU_IDENT 0x7
  42 +#define EMU_RSH 0x8
  43 +
  44 +#define EMU_NOCONNECT 0x10 /* Don't connect */
  45 +
  46 +/* UDP emulations */
  47 +#define EMU_TALK 0x1
  48 +#define EMU_NTALK 0x2
  49 +#define EMU_CUSEEME 0x3
  50 +
  51 +struct tos_t {
  52 + u_int16_t lport;
  53 + u_int16_t fport;
  54 + u_int8_t tos;
  55 + u_int8_t emu;
  56 +};
  57 +
  58 +struct emu_t {
  59 + u_int16_t lport;
  60 + u_int16_t fport;
  61 + u_int8_t tos;
  62 + u_int8_t emu;
  63 + struct emu_t *next;
  64 +};
  65 +
  66 +extern struct emu_t *tcpemu;
  67 +
  68 +extern int x_port, x_server, x_display;
  69 +
  70 +int show_x _P((char *, struct socket *));
  71 +void redir_x _P((u_int32_t, int, int, int));
  72 +void getouraddr _P((void));
  73 +inline void slirp_insque _P((void *, void *));
  74 +inline void slirp_remque _P((void *));
  75 +int add_exec _P((struct ex_list **, int, char *, int, int));
  76 +int openpty _P((int *, int *));
  77 +int fork_exec _P((struct socket *, char *, int));
  78 +void snooze_hup _P((int));
  79 +void snooze _P((void));
  80 +void relay _P((int));
  81 +void add_emu _P((char *));
  82 +void u_sleep _P((int));
  83 +void fd_nonblock _P((int));
  84 +void fd_block _P((int));
  85 +int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
  86 +
  87 +#endif
... ...
slirp/sbuf.c 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#include <slirp.h>
  9 +
  10 +/* Done as a macro in socket.h */
  11 +/* int
  12 + * sbspace(struct sockbuff *sb)
  13 + * {
  14 + * return SB_DATALEN - sb->sb_cc;
  15 + * }
  16 + */
  17 +
  18 +void
  19 +sbfree(sb)
  20 + struct sbuf *sb;
  21 +{
  22 + free(sb->sb_data);
  23 +}
  24 +
  25 +void
  26 +sbdrop(sb, num)
  27 + struct sbuf *sb;
  28 + int num;
  29 +{
  30 + /*
  31 + * We can only drop how much we have
  32 + * This should never succeed
  33 + */
  34 + if(num > sb->sb_cc)
  35 + num = sb->sb_cc;
  36 + sb->sb_cc -= num;
  37 + sb->sb_rptr += num;
  38 + if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
  39 + sb->sb_rptr -= sb->sb_datalen;
  40 +
  41 +}
  42 +
  43 +void
  44 +sbreserve(sb, size)
  45 + struct sbuf *sb;
  46 + int size;
  47 +{
  48 + if (sb->sb_data) {
  49 + /* Already alloced, realloc if necessary */
  50 + if (sb->sb_datalen != size) {
  51 + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
  52 + sb->sb_cc = 0;
  53 + if (sb->sb_wptr)
  54 + sb->sb_datalen = size;
  55 + else
  56 + sb->sb_datalen = 0;
  57 + }
  58 + } else {
  59 + sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
  60 + sb->sb_cc = 0;
  61 + if (sb->sb_wptr)
  62 + sb->sb_datalen = size;
  63 + else
  64 + sb->sb_datalen = 0;
  65 + }
  66 +}
  67 +
  68 +/*
  69 + * Try and write() to the socket, whatever doesn't get written
  70 + * append to the buffer... for a host with a fast net connection,
  71 + * this prevents an unnecessary copy of the data
  72 + * (the socket is non-blocking, so we won't hang)
  73 + */
  74 +void
  75 +sbappend(so, m)
  76 + struct socket *so;
  77 + struct mbuf *m;
  78 +{
  79 + int ret = 0;
  80 +
  81 + DEBUG_CALL("sbappend");
  82 + DEBUG_ARG("so = %lx", (long)so);
  83 + DEBUG_ARG("m = %lx", (long)m);
  84 + DEBUG_ARG("m->m_len = %d", m->m_len);
  85 +
  86 + /* Shouldn't happen, but... e.g. foreign host closes connection */
  87 + if (m->m_len <= 0) {
  88 + m_free(m);
  89 + return;
  90 + }
  91 +
  92 + /*
  93 + * If there is urgent data, call sosendoob
  94 + * if not all was sent, sowrite will take care of the rest
  95 + * (The rest of this function is just an optimisation)
  96 + */
  97 + if (so->so_urgc) {
  98 + sbappendsb(&so->so_rcv, m);
  99 + m_free(m);
  100 + sosendoob(so);
  101 + return;
  102 + }
  103 +
  104 + /*
  105 + * We only write if there's nothing in the buffer,
  106 + * ottherwise it'll arrive out of order, and hence corrupt
  107 + */
  108 + if (!so->so_rcv.sb_cc)
  109 + ret = write(so->s, m->m_data, m->m_len);
  110 +
  111 + if (ret <= 0) {
  112 + /*
  113 + * Nothing was written
  114 + * It's possible that the socket has closed, but
  115 + * we don't need to check because if it has closed,
  116 + * it will be detected in the normal way by soread()
  117 + */
  118 + sbappendsb(&so->so_rcv, m);
  119 + } else if (ret != m->m_len) {
  120 + /*
  121 + * Something was written, but not everything..
  122 + * sbappendsb the rest
  123 + */
  124 + m->m_len -= ret;
  125 + m->m_data += ret;
  126 + sbappendsb(&so->so_rcv, m);
  127 + } /* else */
  128 + /* Whatever happened, we free the mbuf */
  129 + m_free(m);
  130 +}
  131 +
  132 +/*
  133 + * Copy the data from m into sb
  134 + * The caller is responsible to make sure there's enough room
  135 + */
  136 +void
  137 +sbappendsb(sb, m)
  138 + struct sbuf *sb;
  139 + struct mbuf *m;
  140 +{
  141 + int len, n, nn;
  142 +
  143 + len = m->m_len;
  144 +
  145 + if (sb->sb_wptr < sb->sb_rptr) {
  146 + n = sb->sb_rptr - sb->sb_wptr;
  147 + if (n > len) n = len;
  148 + memcpy(sb->sb_wptr, m->m_data, n);
  149 + } else {
  150 + /* Do the right edge first */
  151 + n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
  152 + if (n > len) n = len;
  153 + memcpy(sb->sb_wptr, m->m_data, n);
  154 + len -= n;
  155 + if (len) {
  156 + /* Now the left edge */
  157 + nn = sb->sb_rptr - sb->sb_data;
  158 + if (nn > len) nn = len;
  159 + memcpy(sb->sb_data,m->m_data+n,nn);
  160 + n += nn;
  161 + }
  162 + }
  163 +
  164 + sb->sb_cc += n;
  165 + sb->sb_wptr += n;
  166 + if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
  167 + sb->sb_wptr -= sb->sb_datalen;
  168 +}
  169 +
  170 +/*
  171 + * Copy data from sbuf to a normal, straight buffer
  172 + * Don't update the sbuf rptr, this will be
  173 + * done in sbdrop when the data is acked
  174 + */
  175 +void
  176 +sbcopy(sb, off, len, to)
  177 + struct sbuf *sb;
  178 + int off;
  179 + int len;
  180 + char *to;
  181 +{
  182 + char *from;
  183 +
  184 + from = sb->sb_rptr + off;
  185 + if (from >= sb->sb_data + sb->sb_datalen)
  186 + from -= sb->sb_datalen;
  187 +
  188 + if (from < sb->sb_wptr) {
  189 + if (len > sb->sb_cc) len = sb->sb_cc;
  190 + memcpy(to,from,len);
  191 + } else {
  192 + /* re-use off */
  193 + off = (sb->sb_data + sb->sb_datalen) - from;
  194 + if (off > len) off = len;
  195 + memcpy(to,from,off);
  196 + len -= off;
  197 + if (len)
  198 + memcpy(to+off,sb->sb_data,len);
  199 + }
  200 +}
  201 +
... ...
slirp/sbuf.h 0 → 100644
  1 +/*
  2 + * Copyright (c) 1995 Danny Gasparovski.
  3 + *
  4 + * Please read the file COPYRIGHT for the
  5 + * terms and conditions of the copyright.
  6 + */
  7 +
  8 +#ifndef _SBUF_H_
  9 +#define _SBUF_H_
  10 +
  11 +#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
  12 +#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
  13 +
  14 +struct sbuf {
  15 + u_int sb_cc; /* actual chars in buffer */
  16 + u_int sb_datalen; /* Length of data */
  17 + char *sb_wptr; /* write pointer. points to where the next
  18 + * bytes should be written in the sbuf */
  19 + char *sb_rptr; /* read pointer. points to where the next
  20 + * byte should be read from the sbuf */
  21 + char *sb_data; /* Actual data */
  22 +};
  23 +
  24 +void sbfree _P((struct sbuf *));
  25 +void sbdrop _P((struct sbuf *, int));
  26 +void sbreserve _P((struct sbuf *, int));
  27 +void sbappend _P((struct socket *, struct mbuf *));
  28 +void sbappendsb _P((struct sbuf *, struct mbuf *));
  29 +void sbcopy _P((struct sbuf *, int, int, char *));
  30 +
  31 +#endif
... ...