SLIRP 0.9.1

This commit is contained in:
jvernet 2017-10-03 22:34:56 +02:00
parent 000ec0f135
commit 4682bb80a1
39 changed files with 2299 additions and 2006 deletions

View File

@ -16,7 +16,7 @@ The copyright terms and conditions:
---BEGIN--- ---BEGIN---
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved. Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
@ -25,6 +25,9 @@ The copyright terms and conditions:
2. Redistributions in binary form must reproduce the above copyright 2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgment:
This product includes software developed by Danny Gasparovski.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY

View File

@ -1,8 +1,8 @@
/* /*
* QEMU BOOTP/DHCP server * QEMU BOOTP/DHCP server
* *
* Copyright (c) 2004 Fabrice Bellard * Copyright (c) 2004 Fabrice Bellard
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
@ -38,8 +38,17 @@ typedef struct {
BOOTPClient bootp_clients[NB_ADDR]; BOOTPClient bootp_clients[NB_ADDR];
const char *bootp_filename;
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
#ifdef DEBUG
#define dprintf(fmt, args...) \
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
#else
#define dprintf(fmt, args...)
#endif
static BOOTPClient *get_new_addr(struct in_addr *paddr) static BOOTPClient *get_new_addr(struct in_addr *paddr)
{ {
BOOTPClient *bc; BOOTPClient *bc;
@ -80,7 +89,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
const uint8_t *p, *p_end; const uint8_t *p, *p_end;
int len, tag; int len, tag;
*pmsg_type = 0; *pmsg_type = 0;
p = buf; p = buf;
p_end = buf + size; p_end = buf + size;
@ -92,7 +101,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
while (p < p_end) { while (p < p_end) {
tag = p[0]; tag = p[0];
if (tag == RFC1533_PAD) { if (tag == RFC1533_PAD) {
p++; p++;
} else if (tag == RFC1533_END) { } else if (tag == RFC1533_END) {
break; break;
} else { } else {
@ -100,6 +109,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
if (p >= p_end) if (p >= p_end)
break; break;
len = *p++; len = *p++;
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
switch(tag) { switch(tag) {
case RFC2132_MSG_TYPE: case RFC2132_MSG_TYPE:
@ -126,19 +136,20 @@ static void bootp_reply(struct bootp_t *bp)
/* extract exact DHCP msg type */ /* extract exact DHCP msg type */
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type); dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
if (dhcp_msg_type == 0) if (dhcp_msg_type == 0)
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
if (dhcp_msg_type != DHCPDISCOVER && if (dhcp_msg_type != DHCPDISCOVER &&
dhcp_msg_type != DHCPREQUEST) dhcp_msg_type != DHCPREQUEST)
return; return;
/* XXX: this is a hack to get the client mac address */ /* XXX: this is a hack to get the client mac address */
memcpy(client_ethaddr, bp->bp_hwaddr, 6); memcpy(client_ethaddr, bp->bp_hwaddr, 6);
if ((m = m_get()) == NULL) if ((m = m_get()) == NULL)
return; return;
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
rbp = (struct bootp_t *)m->m_data; rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr); m->m_data += sizeof(struct udpiphdr);
memset(rbp, 0, sizeof(struct bootp_t)); memset(rbp, 0, sizeof(struct bootp_t));
@ -146,8 +157,10 @@ static void bootp_reply(struct bootp_t *bp)
if (dhcp_msg_type == DHCPDISCOVER) { if (dhcp_msg_type == DHCPDISCOVER) {
new_addr: new_addr:
bc = get_new_addr(&daddr.sin_addr); bc = get_new_addr(&daddr.sin_addr);
if (!bc) if (!bc) {
dprintf("no address left\n");
return; return;
}
memcpy(bc->macaddr, client_ethaddr, 6); memcpy(bc->macaddr, client_ethaddr, 6);
} else { } else {
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
@ -158,6 +171,11 @@ static void bootp_reply(struct bootp_t *bp)
} }
} }
if (bootp_filename)
snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
saddr.sin_port = htons(BOOTP_SERVER); saddr.sin_port = htons(BOOTP_SERVER);
@ -185,7 +203,7 @@ static void bootp_reply(struct bootp_t *bp)
*q++ = 1; *q++ = 1;
*q++ = DHCPACK; *q++ = DHCPACK;
} }
if (dhcp_msg_type == DHCPDISCOVER || if (dhcp_msg_type == DHCPDISCOVER ||
dhcp_msg_type == DHCPREQUEST) { dhcp_msg_type == DHCPREQUEST) {
*q++ = RFC2132_SRV_ID; *q++ = RFC2132_SRV_ID;
@ -199,12 +217,12 @@ static void bootp_reply(struct bootp_t *bp)
*q++ = 0xff; *q++ = 0xff;
*q++ = 0xff; *q++ = 0xff;
*q++ = 0x00; *q++ = 0x00;
*q++ = RFC1533_GATEWAY; *q++ = RFC1533_GATEWAY;
*q++ = 4; *q++ = 4;
memcpy(q, &saddr.sin_addr, 4); memcpy(q, &saddr.sin_addr, 4);
q += 4; q += 4;
*q++ = RFC1533_DNS; *q++ = RFC1533_DNS;
*q++ = 4; *q++ = 4;
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
@ -226,8 +244,8 @@ static void bootp_reply(struct bootp_t *bp)
} }
} }
*q++ = RFC1533_END; *q++ = RFC1533_END;
m->m_len = sizeof(struct bootp_t) - m->m_len = sizeof(struct bootp_t) -
sizeof(struct ip) - sizeof(struct udphdr); sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
} }

View File

@ -90,10 +90,6 @@
#define BOOTP_VENDOR_LEN 64 #define BOOTP_VENDOR_LEN 64
#define DHCP_OPT_LEN 312 #define DHCP_OPT_LEN 312
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct bootp_t { struct bootp_t {
struct ip ip; struct ip ip;
struct udphdr udp; struct udphdr udp;
@ -112,10 +108,6 @@ struct bootp_t {
uint8_t bp_sname[64]; uint8_t bp_sname[64];
uint8_t bp_file[128]; uint8_t bp_file[128];
uint8_t bp_vend[DHCP_OPT_LEN]; uint8_t bp_vend[DHCP_OPT_LEN];
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
void bootp_input(struct mbuf *m); void bootp_input(struct mbuf *m);

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -37,7 +41,7 @@
* *
* This routine is very heavily used in the network * This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible. * code and should be modified for each CPU to be as fast as possible.
* *
* XXX Since we will never span more than 1 mbuf, we can optimise this * XXX Since we will never span more than 1 mbuf, we can optimise this
*/ */
@ -59,13 +63,13 @@ int cksum(struct mbuf *m, int len)
u_int16_t s[2]; u_int16_t s[2];
u_int32_t l; u_int32_t l;
} l_util; } l_util;
if (m->m_len == 0) if (m->m_len == 0)
goto cont; goto cont;
w = mtod(m, u_int16_t *); w = mtod(m, u_int16_t *);
mlen = m->m_len; mlen = m->m_len;
if (len < mlen) if (len < mlen)
mlen = len; mlen = len;
len -= mlen; len -= mlen;
@ -103,7 +107,7 @@ int cksum(struct mbuf *m, int len)
while ((mlen -= 2) >= 0) { while ((mlen -= 2) >= 0) {
sum += *w++; sum += *w++;
} }
if (byte_swapped) { if (byte_swapped) {
REDUCE; REDUCE;
sum <<= 8; sum <<= 8;
@ -113,11 +117,11 @@ int cksum(struct mbuf *m, int len)
sum += s_util.s; sum += s_util.s;
mlen = 0; mlen = 0;
} else } else
mlen = -1; mlen = -1;
} else if (mlen == -1) } else if (mlen == -1)
s_util.c[0] = *(u_int8_t *)w; s_util.c[0] = *(u_int8_t *)w;
cont: cont:
#ifdef DEBUG #ifdef DEBUG
if (len) { if (len) {

View File

@ -1,8 +1,8 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* Portions copyright (c) 2000 Kelly Price. * Portions copyright (c) 2000 Kelly Price.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -16,8 +16,11 @@ int dostats = 0;
#endif #endif
int slirp_debug = 0; int slirp_debug = 0;
/* Carry over one item from main.c so that the tty's restored. extern char *strerror _P((int));
/* Carry over one item from main.c so that the tty's restored.
* Only done when the tty being used is /dev/tty --RedWolf */ * Only done when the tty being used is /dev/tty --RedWolf */
#ifndef CONFIG_QEMU
extern struct termios slirp_tty_settings; extern struct termios slirp_tty_settings;
extern int slirp_tty_restore; extern int slirp_tty_restore;
@ -30,7 +33,7 @@ debug_init(file, dbg)
/* Close the old debugging file */ /* Close the old debugging file */
if (dfd) if (dfd)
fclose(dfd); fclose(dfd);
dfd = fopen(file,"w"); dfd = fopen(file,"w");
if (dfd != NULL) { if (dfd != NULL) {
#if 0 #if 0
@ -56,7 +59,7 @@ dump_packet(dat, n)
{ {
u_char *pptr = (u_char *)dat; u_char *pptr = (u_char *)dat;
int j,k; int j,k;
n /= 16; n /= 16;
n++; n++;
DEBUG_MISC((dfd, "PACKET DUMPED: \n")); DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
@ -68,28 +71,30 @@ dump_packet(dat, n)
} }
} }
#endif #endif
#endif
#ifdef LOG_ENABLED
#if 0 #if 0
/* /*
* Statistic routines * Statistic routines
* *
* These will print statistics to the screen, the debug file (dfd), or * These will print statistics to the screen, the debug file (dfd), or
* a buffer, depending on "type", so that the stats can be sent over * a buffer, depending on "type", so that the stats can be sent over
* the link as well. * the link as well.
*/ */
void static void
ttystats(ttyp) ttystats(ttyp)
struct ttys *ttyp; struct ttys *ttyp;
{ {
struct slirp_ifstats *is = &ttyp->ifstats; struct slirp_ifstats *is = &ttyp->ifstats;
char buff[512]; char buff[512];
lprint(" \r\n"); lprint(" \r\n");
if (if_comp & IF_COMPRESS) if (IF_COMP & IF_COMPRESS)
strcpy(buff, "on"); strcpy(buff, "on");
else if (if_comp & IF_NOCOMPRESS) else if (IF_COMP & IF_NOCOMPRESS)
strcpy(buff, "off"); strcpy(buff, "off");
else else
strcpy(buff, "off (for now)"); strcpy(buff, "off (for now)");
@ -117,20 +122,20 @@ ttystats(ttyp)
lprint(" %6d bad input packets\r\n", is->in_mbad); lprint(" %6d bad input packets\r\n", is->in_mbad);
} }
void static void
allttystats() allttystats(void)
{ {
struct ttys *ttyp; struct ttys *ttyp;
for (ttyp = ttys; ttyp; ttyp = ttyp->next) for (ttyp = ttys; ttyp; ttyp = ttyp->next)
ttystats(ttyp); ttystats(ttyp);
} }
#endif #endif
void static void
ipstats() ipstats(void)
{ {
lprint(" \r\n"); lprint(" \r\n");
lprint("IP stats:\r\n"); lprint("IP stats:\r\n");
lprint(" %6d total packets received (%d were unaligned)\r\n", lprint(" %6d total packets received (%d were unaligned)\r\n",
@ -151,14 +156,14 @@ ipstats()
lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
} }
#if 0 #ifndef CONFIG_QEMU
void static void
vjstats() vjstats(void)
{ {
lprint(" \r\n"); lprint(" \r\n");
lprint("VJ compression stats:\r\n"); lprint("VJ compression stats:\r\n");
lprint(" %6d outbound packets (%d compressed)\r\n", lprint(" %6d outbound packets (%d compressed)\r\n",
comp_s.sls_packets, comp_s.sls_compressed); comp_s.sls_packets, comp_s.sls_compressed);
lprint(" %6d searches for connection stats (%d misses)\r\n", lprint(" %6d searches for connection stats (%d misses)\r\n",
@ -170,13 +175,13 @@ vjstats()
} }
#endif #endif
void static void
tcpstats() tcpstats(void)
{ {
lprint(" \r\n"); lprint(" \r\n");
lprint("TCP stats:\r\n"); lprint("TCP stats:\r\n");
lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
lprint(" %6d data packets (%d bytes)\r\n", lprint(" %6d data packets (%d bytes)\r\n",
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
@ -189,8 +194,8 @@ tcpstats()
lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
lprint(" %6d acks (for %d bytes)\r\n", lprint(" %6d acks (for %d bytes)\r\n",
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
@ -199,7 +204,7 @@ tcpstats()
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
lprint(" %6d completely duplicate packets (%d bytes)\r\n", lprint(" %6d completely duplicate packets (%d bytes)\r\n",
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
lprint(" %6d out-of-order packets (%d bytes)\r\n", lprint(" %6d out-of-order packets (%d bytes)\r\n",
@ -212,7 +217,7 @@ tcpstats()
lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
lprint(" %6d discarded for bad header offset fields\r\n", lprint(" %6d discarded for bad header offset fields\r\n",
tcpstat.tcps_rcvbadoff); tcpstat.tcps_rcvbadoff);
lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
@ -231,15 +236,15 @@ tcpstats()
lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ /* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */ /* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
} }
void static void
udpstats() udpstats(void)
{ {
lprint(" \r\n"); lprint(" \r\n");
@ -252,8 +257,8 @@ udpstats()
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
} }
void static void
icmpstats() icmpstats(void)
{ {
lprint(" \r\n"); lprint(" \r\n");
lprint("ICMP stats:\r\n"); lprint("ICMP stats:\r\n");
@ -265,23 +270,23 @@ icmpstats()
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
} }
void static void
mbufstats() mbufstats(void)
{ {
struct mbuf *m; struct mbuf *m;
int i; int i;
lprint(" \r\n"); lprint(" \r\n");
lprint("Mbuf stats:\r\n"); lprint("Mbuf stats:\r\n");
lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max); lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
i = 0; i = 0;
for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next) for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
i++; i++;
lprint(" %6d mbufs on free list\r\n", i); lprint(" %6d mbufs on free list\r\n", i);
i = 0; i = 0;
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
i++; i++;
@ -289,59 +294,55 @@ mbufstats()
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
} }
void static void
sockstats() sockstats(void)
{ {
char addr[INET_ADDRSTRLEN];
char buff[256]; char buff[256];
int n; int n;
struct socket *so; struct socket *so;
lprint(" \r\n"); lprint(" \r\n");
lprint( lprint(
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n");
for (so = tcb.so_next; so != &tcb; so = so->so_next) { for (so = tcb.so_next; so != &tcb; so = so->so_next) {
n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
while (n < 17) while (n < 17)
buff[n++] = ' '; buff[n++] = ' ';
buff[17] = 0; buff[17] = 0;
lprint("%s %3d %15s %5d ", lprint("%s %3d %15s %5d ",
buff, so->s, buff, so->s,
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), inet_ntoa(so->so_laddr), ntohs(so->so_lport));
ntohs(so->so_lport));
lprint("%15s %5d %5d %5d\r\n", lprint("%15s %5d %5d %5d\r\n",
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), inet_ntoa(so->so_faddr), ntohs(so->so_fport),
ntohs(so->so_fport),
so->so_rcv.sb_cc, so->so_snd.sb_cc); so->so_rcv.sb_cc, so->so_snd.sb_cc);
} }
for (so = udb.so_next; so != &udb; so = so->so_next) { for (so = udb.so_next; so != &udb; so = so->so_next) {
n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
while (n < 17) while (n < 17)
buff[n++] = ' '; buff[n++] = ' ';
buff[17] = 0; buff[17] = 0;
lprint("%s %3d %15s %5d ", lprint("%s %3d %15s %5d ",
buff, so->s, buff, so->s,
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), inet_ntoa(so->so_laddr), ntohs(so->so_lport));
ntohs(so->so_lport));
lprint("%15s %5d %5d %5d\r\n", lprint("%15s %5d %5d %5d\r\n",
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), inet_ntoa(so->so_faddr), ntohs(so->so_fport),
ntohs(so->so_fport),
so->so_rcv.sb_cc, so->so_snd.sb_cc); so->so_rcv.sb_cc, so->so_snd.sb_cc);
} }
} }
#endif
#if 0 #ifndef CONFIG_QEMU
void void
slirp_exit(exit_status) slirp_exit(exit_status)
int exit_status; int exit_status;
{ {
struct ttys *ttyp; struct ttys *ttyp;
DEBUG_CALL("slirp_exit"); DEBUG_CALL("slirp_exit");
DEBUG_ARG("exit_status = %d", exit_status); DEBUG_ARG("exit_status = %d", exit_status);
@ -350,7 +351,7 @@ slirp_exit(exit_status)
if (!dfd) if (!dfd)
debug_init("slirp_stats", 0xf); debug_init("slirp_stats", 0xf);
lprint_arg = (char **)&dfd; lprint_arg = (char **)&dfd;
ipstats(); ipstats();
tcpstats(); tcpstats();
udpstats(); udpstats();
@ -360,20 +361,35 @@ slirp_exit(exit_status)
allttystats(); allttystats();
vjstats(); vjstats();
} }
for (ttyp = ttys; ttyp; ttyp = ttyp->next) for (ttyp = ttys; ttyp; ttyp = ttyp->next)
tty_detached(ttyp, 1); tty_detached(ttyp, 1);
if (slirp_forked) { if (slirp_forked) {
/* Menendez time */ /* Menendez time */
if (kill(getppid(), SIGQUIT) < 0) if (kill(getppid(), SIGQUIT) < 0)
lprint("Couldn't kill parent process %ld!\n", lprint("Couldn't kill parent process %ld!\n",
(long) getppid()); (long) getppid());
} }
/* Restore the terminal if we gotta */ /* Restore the terminal if we gotta */
if(slirp_tty_restore) if(slirp_tty_restore)
tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */ tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
exit(exit_status); exit(exit_status);
} }
#endif #endif
void
slirp_stats(void)
{
#ifdef LOG_ENABLED
ipstats();
tcpstats();
udpstats();
icmpstats();
mbufstats();
sockstats();
#else
lprint("SLIRP statistics code not compiled.\n");
#endif
}

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -36,15 +36,5 @@ extern int slirp_debug;
#endif #endif
void debug_init(char *, int); void debug_init _P((char *, int));
//void ttystats(struct ttys *);
void allttystats(void);
void ipstats(void);
void vjstats(void);
void tcpstats(void);
void udpstats(void);
void icmpstats(void);
void mbufstats(void);
void sockstats(void);
void slirp_exit(int);

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -60,6 +64,8 @@ struct icmpstat {
{ "stats", CTLTYPE_STRUCT }, \ { "stats", CTLTYPE_STRUCT }, \
} }
#ifdef LOG_ENABLED
extern struct icmpstat icmpstat; extern struct icmpstat icmpstat;
#endif
#endif #endif

View File

@ -7,12 +7,7 @@
#include <slirp.h> #include <slirp.h>
size_t if_mtu, if_mru; int if_queued = 0; /* Number of packets queued so far */
int if_comp;
int if_maxlinkhdr;
int if_queued = 0; /* Number of packets queued so far */
int if_thresh = 10; /* Number of packets queued before we start sending
* (to prevent allocing too many mbufs) */
struct mbuf if_fastq; /* fast queue (for interactive data) */ struct mbuf if_fastq; /* fast queue (for interactive data) */
struct mbuf if_batchq; /* queue for non-interactive data */ struct mbuf if_batchq; /* queue for non-interactive data */
@ -41,23 +36,6 @@ ifs_remque(ifm)
void void
if_init() if_init()
{ {
#if 0
/*
* Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
* and 8 bytes for PPP, but need to have it on an 8byte boundary
*/
#ifdef USE_PPP
if_maxlinkhdr = 48;
#else
if_maxlinkhdr = 40;
#endif
#else
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
if_maxlinkhdr = 2 + 14 + 40;
#endif
if_mtu = 1500;
if_mru = 1500;
if_comp = IF_AUTOCOMP;
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
// sl_compress_init(&comp_s); // sl_compress_init(&comp_s);
@ -77,12 +55,12 @@ writen(fd, bptr, n)
{ {
int ret; int ret;
int total; int total;
/* This should succeed most of the time */ /* This should succeed most of the time */
ret = send(fd, bptr, n,0); ret = send(fd, bptr, n,0);
if (ret == n || ret <= 0) if (ret == n || ret <= 0)
return ret; return ret;
/* Didn't write everything, go into the loop */ /* Didn't write everything, go into the loop */
total = ret; total = ret;
while (n > total) { while (n > total) {
@ -97,7 +75,7 @@ writen(fd, bptr, n)
/* /*
* if_input - read() the tty, do "top level" processing (ie: check for any escapes), * if_input - read() the tty, do "top level" processing (ie: check for any escapes),
* and pass onto (*ttyp->if_input) * and pass onto (*ttyp->if_input)
* *
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet. * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
*/ */
#define INBUFF_SIZE 2048 /* XXX */ #define INBUFF_SIZE 2048 /* XXX */
@ -107,17 +85,16 @@ if_input(ttyp)
{ {
u_char if_inbuff[INBUFF_SIZE]; u_char if_inbuff[INBUFF_SIZE];
int if_n; int if_n;
DEBUG_CALL("if_input"); DEBUG_CALL("if_input");
DEBUG_ARG("ttyp = %lx", (long)ttyp); DEBUG_ARG("ttyp = %lx", (long)ttyp);
if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0); if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
DEBUG_MISC((dfd, " read %d bytes\n", if_n)); DEBUG_MISC((dfd, " read %d bytes\n", if_n));
if (if_n <= 0) { if (if_n <= 0) {
int error = WSAGetLastError(); if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) {
if (ttyp->up) if (ttyp->up)
link_up--; link_up--;
tty_detached(ttyp, 0); tty_detached(ttyp, 0);
@ -139,19 +116,19 @@ if_input(ttyp)
} }
} }
ttyp->ones = ttyp->zeros = 0; ttyp->ones = ttyp->zeros = 0;
(*ttyp->if_input)(ttyp, if_inbuff, if_n); (*ttyp->if_input)(ttyp, if_inbuff, if_n);
} }
#endif #endif
/* /*
* if_output: Queue packet into an output queue. * if_output: Queue packet into an output queue.
* There are 2 output queue's, if_fastq and if_batchq. * There are 2 output queue's, if_fastq and if_batchq.
* Each output queue is a doubly linked list of double linked lists * Each output queue is a doubly linked list of double linked lists
* of mbufs, each list belonging to one "session" (socket). This * of mbufs, each list belonging to one "session" (socket). This
* way, we can output packets fairly by sending one packet from each * way, we can output packets fairly by sending one packet from each
* session, instead of all the packets from one session, then all packets * session, instead of all the packets from one session, then all packets
* from the next session, etc. Packets on the if_fastq get absolute * from the next session, etc. Packets on the if_fastq get absolute
* priority, but if one session hogs the link, it gets "downgraded" * priority, but if one session hogs the link, it gets "downgraded"
* to the batchq until it runs out of packets, then it'll return * to the batchq until it runs out of packets, then it'll return
* to the fastq (eg. if the user does an ls -alR in a telnet session, * to the fastq (eg. if the user does an ls -alR in a telnet session,
@ -164,11 +141,11 @@ if_output(so, ifm)
{ {
struct mbuf *ifq; struct mbuf *ifq;
int on_fastq = 1; int on_fastq = 1;
DEBUG_CALL("if_output"); DEBUG_CALL("if_output");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("ifm = %lx", (long)ifm); DEBUG_ARG("ifm = %lx", (long)ifm);
/* /*
* First remove the mbuf from m_usedlist, * First remove the mbuf from m_usedlist,
* since we're gonna use m_next and m_prev ourselves * since we're gonna use m_next and m_prev ourselves
@ -178,9 +155,9 @@ if_output(so, ifm)
remque(ifm); remque(ifm);
ifm->m_flags &= ~M_USEDLIST; ifm->m_flags &= ~M_USEDLIST;
} }
/* /*
* See if there's already a batchq list for this session. * See if there's already a batchq list for this session.
* This can include an interactive session, which should go on fastq, * This can include an interactive session, which should go on fastq,
* but gets too greedy... hence it'll be downgraded from fastq to batchq. * but gets too greedy... hence it'll be downgraded from fastq to batchq.
* We mustn't put this packet back on the fastq (or we'll send it out of order) * We mustn't put this packet back on the fastq (or we'll send it out of order)
@ -194,7 +171,7 @@ if_output(so, ifm)
goto diddit; goto diddit;
} }
} }
/* No match, check which queue to put it on */ /* No match, check which queue to put it on */
if (so && (so->so_iptos & IPTOS_LOWDELAY)) { if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
ifq = if_fastq.ifq_prev; ifq = if_fastq.ifq_prev;
@ -210,15 +187,15 @@ if_output(so, ifm)
} }
} else } else
ifq = if_batchq.ifq_prev; ifq = if_batchq.ifq_prev;
/* Create a new doubly linked list for this session */ /* Create a new doubly linked list for this session */
ifm->ifq_so = so; ifm->ifq_so = so;
ifs_init(ifm); ifs_init(ifm);
insque(ifm, ifq); insque(ifm, ifq);
diddit: diddit:
++if_queued; ++if_queued;
if (so) { if (so) {
/* Update *_queued */ /* Update *_queued */
so->so_queued++; so->so_queued++;
@ -230,12 +207,12 @@ diddit:
* have been sent over the link * have been sent over the link
* (XXX These are arbitrary numbers, probably not optimal..) * (XXX These are arbitrary numbers, probably not optimal..)
*/ */
if (on_fastq && ((so->so_nqueued >= 6) && if (on_fastq && ((so->so_nqueued >= 6) &&
(so->so_nqueued - so->so_queued) >= 3)) { (so->so_nqueued - so->so_queued) >= 3)) {
/* Remove from current queue... */ /* Remove from current queue... */
remque(ifm->ifs_next); remque(ifm->ifs_next);
/* ...And insert in the new. That'll teach ya! */ /* ...And insert in the new. That'll teach ya! */
insque(ifm->ifs_next, &if_batchq); insque(ifm->ifs_next, &if_batchq);
} }
@ -268,16 +245,16 @@ void
if_start(void) if_start(void)
{ {
struct mbuf *ifm, *ifqt; struct mbuf *ifm, *ifqt;
DEBUG_CALL("if_start"); DEBUG_CALL("if_start");
if (if_queued == 0) if (if_queued == 0)
return; /* Nothing to do */ return; /* Nothing to do */
again: again:
/* check if we can really output */ /* check if we can really output */
if (!slirp_can_output()) if (!slirp_can_output())
return; return;
/* /*
* See which queue to get next packet from * See which queue to get next packet from
@ -291,7 +268,7 @@ if_start(void)
ifm = next_m; ifm = next_m;
else else
ifm = if_batchq.ifq_next; ifm = if_batchq.ifq_next;
/* Set which packet to send on next iteration */ /* Set which packet to send on next iteration */
next_m = ifm->ifq_next; next_m = ifm->ifq_next;
} }
@ -299,24 +276,24 @@ if_start(void)
ifqt = ifm->ifq_prev; ifqt = ifm->ifq_prev;
remque(ifm); remque(ifm);
--if_queued; --if_queued;
/* If there are more packets for this session, re-queue them */ /* If there are more packets for this session, re-queue them */
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
insque(ifm->ifs_next, ifqt); insque(ifm->ifs_next, ifqt);
ifs_remque(ifm); ifs_remque(ifm);
} }
/* Update so_queued */ /* Update so_queued */
if (ifm->ifq_so) { if (ifm->ifq_so) {
if (--ifm->ifq_so->so_queued == 0) if (--ifm->ifq_so->so_queued == 0)
/* If there's no more queued, reset nqueued */ /* If there's no more queued, reset nqueued */
ifm->ifq_so->so_nqueued = 0; ifm->ifq_so->so_nqueued = 0;
} }
/* Encapsulate the packet for sending */
if_encap((uint8_t*)ifm->m_data, ifm->m_len);
m_free(ifm); /* Encapsulate the packet for sending */
if_encap(ifm->m_data, ifm->m_len);
m_free(ifm);
if (if_queued) if (if_queued)
goto again; goto again;

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -13,15 +13,26 @@
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */
#define IF_NOCIDCOMP 0x08 /* CID compression */ #define IF_NOCIDCOMP 0x08 /* CID compression */
/* Needed for FreeBSD */ #define IF_MTU 1500
#undef if_mtu #define IF_MRU 1500
extern size_t if_mtu; #define IF_COMP IF_AUTOCOMP /* Flags for compression */
extern size_t if_mru; /* MTU and MRU */
extern int if_comp; /* Flags for compression */ #if 0
extern int if_maxlinkhdr; /*
* Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
* and 8 bytes for PPP, but need to have it on an 8byte boundary
*/
#ifdef USE_PPP
#define IF_MAXLINKHDR 48
#else
#define IF_MAXLINKHDR 40
#endif
#else
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
#define IF_MAXLINKHDR (2 + 14 + 40)
#endif
extern int if_queued; /* Number of packets queued so far */ extern int if_queued; /* Number of packets queued so far */
extern int if_thresh; /* Number of packets queued before we start sending
* (to prevent allocing too many mbufs) */
extern struct mbuf if_fastq; /* fast queue (for interactive data) */ extern struct mbuf if_fastq; /* fast queue (for interactive data) */
extern struct mbuf if_batchq; /* queue for non-interactive data */ extern struct mbuf if_batchq; /* queue for non-interactive data */
@ -29,6 +40,7 @@ extern struct mbuf *next_m;
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
#ifdef LOG_ENABLED
/* Interface statistics */ /* Interface statistics */
struct slirp_ifstats { struct slirp_ifstats {
u_int out_pkts; /* Output packets */ u_int out_pkts; /* Output packets */
@ -39,12 +51,13 @@ struct slirp_ifstats {
u_int in_bytes; /* Input bytes */ u_int in_bytes; /* Input bytes */
u_int in_errpkts; /* Input Error Packets */ u_int in_errpkts; /* Input Error Packets */
u_int in_errbytes; /* Input Error Bytes */ u_int in_errbytes; /* Input Error Bytes */
u_int bytes_saved; /* Number of bytes that compression "saved" */ u_int bytes_saved; /* Number of bytes that compression "saved" */
/* ie: number of bytes that didn't need to be sent over the link /* ie: number of bytes that didn't need to be sent over the link
* because of compression */ * because of compression */
u_int in_mbad; /* Bad incoming packets */ u_int in_mbad; /* Bad incoming packets */
}; };
#endif
#endif #endif

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -72,16 +76,12 @@ typedef u_int32_t n_long; /* long as received from the net */
/* /*
* Structure of an internet header, naked of options. * Structure of an internet header, naked of options.
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ip { struct ip {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
u_char ip_v:4, /* version */ u_int ip_v:4, /* version */
ip_hl:4; /* header length */ ip_hl:4; /* header length */
#else #else
u_char ip_hl:4, /* header length */ u_int ip_hl:4, /* header length */
ip_v:4; /* version */ ip_v:4; /* version */
#endif #endif
u_int8_t ip_tos; /* type of service */ u_int8_t ip_tos; /* type of service */
@ -95,11 +95,7 @@ struct ip {
u_int8_t ip_p; /* protocol */ u_int8_t ip_p; /* protocol */
u_int16_t ip_sum; /* checksum */ u_int16_t ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */ struct in_addr ip_src,ip_dst; /* source and dest address */
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
#define IP_MAXPACKET 65535 /* maximum packet size */ #define IP_MAXPACKET 65535 /* maximum packet size */
@ -143,19 +139,15 @@ struct ip {
/* /*
* Time stamp option structure. * Time stamp option structure.
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ip_timestamp { struct ip_timestamp {
u_int8_t ipt_code; /* IPOPT_TS */ u_int8_t ipt_code; /* IPOPT_TS */
u_int8_t ipt_len; /* size of structure (variable) */ u_int8_t ipt_len; /* size of structure (variable) */
u_int8_t ipt_ptr; /* index of current entry */ u_int8_t ipt_ptr; /* index of current entry */
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
u_char ipt_oflw:4, /* overflow counter */ u_int ipt_oflw:4, /* overflow counter */
ipt_flg:4; /* flags, see below */ ipt_flg:4; /* flags, see below */
#else #else
u_char ipt_flg:4, /* flags, see below */ u_int ipt_flg:4, /* flags, see below */
ipt_oflw:4; /* overflow counter */ ipt_oflw:4; /* overflow counter */
#endif #endif
union ipt_timestamp { union ipt_timestamp {
@ -165,11 +157,7 @@ struct ip_timestamp {
n_long ipt_time; n_long ipt_time;
} ipt_ta[1]; } ipt_ta[1];
} ipt_timestamp; } ipt_timestamp;
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
/* flag bits for ipt_flg */ /* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */ #define IPOPT_TS_TSONLY 0 /* timestamps only */
@ -216,10 +204,6 @@ typedef caddr32_t ipasfragp_32;
/* /*
* Overlay for ip header used by other protocols (tcp, udp). * Overlay for ip header used by other protocols (tcp, udp).
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct ipovly { struct ipovly {
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */ caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
u_int8_t ih_x1; /* (unused) */ u_int8_t ih_x1; /* (unused) */
@ -227,11 +211,7 @@ struct ipovly {
u_int16_t ih_len; /* protocol length */ u_int16_t ih_len; /* protocol length */
struct in_addr ih_src; /* source internet address */ struct in_addr ih_src; /* source internet address */
struct in_addr ih_dst; /* destination internet address */ struct in_addr ih_dst; /* destination internet address */
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
/* /*
* Ip reassembly queue structure. Each fragment * Ip reassembly queue structure. Each fragment
@ -257,10 +237,10 @@ struct ipq {
*/ */
struct ipasfrag { struct ipasfrag {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
u_char ip_v:4, u_int ip_v:4,
ip_hl:4; ip_hl:4;
#else #else
u_char ip_hl:4, u_int ip_hl:4,
ip_v:4; ip_v:4;
#endif #endif
/* BUG : u_int changed to u_int8_t. /* BUG : u_int changed to u_int8_t.
@ -292,6 +272,7 @@ struct ipoption {
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
}; };
#ifdef LOG_ENABLED
/* /*
* Structure attached to inpcb.ip_moptions and * Structure attached to inpcb.ip_moptions and
* passed to ip_output when IP multicast options are in use. * passed to ip_output when IP multicast options are in use.
@ -326,8 +307,9 @@ struct ipstat {
}; };
extern struct ipstat ipstat; extern struct ipstat ipstat;
#endif
extern struct ipq ipq; /* ip reass. queue */ extern struct ipq ipq; /* ip reass. queue */
extern u_int16_t ip_id; /* ip packet ctr, for ids */ extern u_int16_t ip_id; /* ip packet ctr, for ids */
extern int ip_defttl; /* default IP ttl */
#endif #endif

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -33,14 +37,16 @@
#include "slirp.h" #include "slirp.h"
#include "ip_icmp.h" #include "ip_icmp.h"
#ifdef LOG_ENABLED
struct icmpstat icmpstat; struct icmpstat icmpstat;
#endif
/* The message sent when emulating PING */ /* The message sent when emulating PING */
/* Be nice and tell them it's just a psuedo-ping packet */ /* Be nice and tell them it's just a pseudo-ping packet */
char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
/* list of actions for icmp_error() on RX of an icmp message */ /* list of actions for icmp_error() on RX of an icmp message */
static int icmp_flush[19] = { static const int icmp_flush[19] = {
/* ECHO REPLY (0) */ 0, /* ECHO REPLY (0) */ 0,
1, 1,
1, 1,
@ -59,7 +65,7 @@ static int icmp_flush[19] = {
/* INFO (15) */ 0, /* INFO (15) */ 0,
/* INFO REPLY (16) */ 0, /* INFO REPLY (16) */ 0,
/* ADDR MASK (17) */ 0, /* ADDR MASK (17) */ 0,
/* ADDR MASK REPLY (18) */ 0 /* ADDR MASK REPLY (18) */ 0
}; };
/* /*
@ -74,19 +80,19 @@ icmp_input(m, hlen)
register struct ip *ip=mtod(m, struct ip *); register struct ip *ip=mtod(m, struct ip *);
int icmplen=ip->ip_len; int icmplen=ip->ip_len;
/* int code; */ /* int code; */
DEBUG_CALL("icmp_input"); DEBUG_CALL("icmp_input");
DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m = %lx", (long )m);
DEBUG_ARG("m_len = %zu", m->m_len); DEBUG_ARG("m_len = %d", m->m_len);
STAT(icmpstat.icps_received++);
icmpstat.icps_received++;
/* /*
* Locate icmp structure in mbuf, and check * Locate icmp structure in mbuf, and check
* that its not corrupted and of at least minimum length. * that its not corrupted and of at least minimum length.
*/ */
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
icmpstat.icps_tooshort++; STAT(icmpstat.icps_tooshort++);
freeit: freeit:
m_freem(m); m_freem(m);
goto end_error; goto end_error;
@ -96,12 +102,12 @@ icmp_input(m, hlen)
m->m_data += hlen; m->m_data += hlen;
icp = mtod(m, struct icmp *); icp = mtod(m, struct icmp *);
if (cksum(m, icmplen)) { if (cksum(m, icmplen)) {
icmpstat.icps_checksum++; STAT(icmpstat.icps_checksum++);
goto freeit; goto freeit;
} }
m->m_len += hlen; m->m_len += hlen;
m->m_data -= hlen; m->m_data -= hlen;
/* icmpstat.icps_inhist[icp->icmp_type]++; */ /* icmpstat.icps_inhist[icp->icmp_type]++; */
/* code = icp->icmp_code; */ /* code = icp->icmp_code; */
@ -117,7 +123,7 @@ icmp_input(m, hlen)
struct sockaddr_in addr; struct sockaddr_in addr;
if ((so = socreate()) == NULL) goto freeit; if ((so = socreate()) == NULL) goto freeit;
if(udp_attach(so) == -1) { if(udp_attach(so) == -1) {
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
sofree(so); sofree(so);
m_free(m); m_free(m);
@ -131,7 +137,7 @@ icmp_input(m, hlen)
so->so_iptos = ip->ip_tos; so->so_iptos = ip->ip_tos;
so->so_type = IPPROTO_ICMP; so->so_type = IPPROTO_ICMP;
so->so_state = SS_ISFCONNECTED; so->so_state = SS_ISFCONNECTED;
/* Send the packet */ /* Send the packet */
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
@ -153,7 +159,7 @@ icmp_input(m, hlen)
(struct sockaddr *)&addr, sizeof(addr)) == -1) { (struct sockaddr *)&addr, sizeof(addr)) == -1) {
DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
udp_detach(so); udp_detach(so);
} }
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */ } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
@ -166,12 +172,12 @@ icmp_input(m, hlen)
case ICMP_TSTAMP: case ICMP_TSTAMP:
case ICMP_MASKREQ: case ICMP_MASKREQ:
case ICMP_REDIRECT: case ICMP_REDIRECT:
icmpstat.icps_notsupp++; STAT(icmpstat.icps_notsupp++);
m_freem(m); m_freem(m);
break; break;
default: default:
icmpstat.icps_badtype++; STAT(icmpstat.icps_badtype++);
m_freem(m); m_freem(m);
} /* swith */ } /* swith */
@ -195,18 +201,18 @@ end_error:
* mbuf *msrc is used as a template, but is NOT m_free()'d. * mbuf *msrc is used as a template, but is NOT m_free()'d.
* It is reported as the bad ip packet. The header should * It is reported as the bad ip packet. The header should
* be fully correct and in host byte order. * be fully correct and in host byte order.
* ICMP fragmentation is illegal. All machines must accept 576 bytes in one * ICMP fragmentation is illegal. All machines must accept 576 bytes in one
* packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548 * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
*/ */
#define ICMP_MAXDATALEN (IP_MSS-28) #define ICMP_MAXDATALEN (IP_MSS-28)
void void
icmp_error( icmp_error(msrc, type, code, minsize, message)
struct mbuf *msrc, struct mbuf *msrc;
u_char type, u_char type;
u_char code, u_char code;
int minsize, int minsize;
char *message) char *message;
{ {
unsigned hlen, shlen, s_ip_len; unsigned hlen, shlen, s_ip_len;
register struct ip *ip; register struct ip *ip;
@ -215,17 +221,17 @@ icmp_error(
DEBUG_CALL("icmp_error"); DEBUG_CALL("icmp_error");
DEBUG_ARG("msrc = %lx", (long )msrc); DEBUG_ARG("msrc = %lx", (long )msrc);
DEBUG_ARG("msrc_len = %zu", msrc->m_len); DEBUG_ARG("msrc_len = %d", msrc->m_len);
if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error; if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
/* check msrc */ /* check msrc */
if(!msrc) goto end_error; if(!msrc) goto end_error;
ip = mtod(msrc, struct ip *); ip = mtod(msrc, struct ip *);
#if DEBUG #if DEBUG
{ char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN]; { char bufa[20], bufb[20];
inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa)); strcpy(bufa, inet_ntoa(ip->ip_src));
inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb)); strcpy(bufb, inet_ntoa(ip->ip_dst));
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb)); DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
} }
#endif #endif
@ -244,7 +250,7 @@ icmp_error(
/* make a copy */ /* make a copy */
if(!(m=m_get())) goto end_error; /* get mbuf */ if(!(m=m_get())) goto end_error; /* get mbuf */
{ u_int new_m_size; { int new_m_size;
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
if(new_m_size>m->m_size) m_inc(m, new_m_size); if(new_m_size>m->m_size) m_inc(m, new_m_size);
} }
@ -254,9 +260,9 @@ icmp_error(
/* make the header of the reply packet */ /* make the header of the reply packet */
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
hlen= sizeof(struct ip ); /* no options in reply */ hlen= sizeof(struct ip ); /* no options in reply */
/* fill in icmp */ /* fill in icmp */
m->m_data += hlen; m->m_data += hlen;
m->m_len -= hlen; m->m_len -= hlen;
icp = mtod(m, struct icmp *); icp = mtod(m, struct icmp *);
@ -265,7 +271,7 @@ icmp_error(
else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */ else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
s_ip_len=ICMP_MAXDATALEN; s_ip_len=ICMP_MAXDATALEN;
m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */ m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
/* min. size = 8+sizeof(struct ip)+8 */ /* min. size = 8+sizeof(struct ip)+8 */
@ -299,8 +305,8 @@ icmp_error(
/* fill in ip */ /* fill in ip */
ip->ip_hl = hlen >> 2; ip->ip_hl = hlen >> 2;
ip->ip_len = (u_int16_t)m->m_len; ip->ip_len = m->m_len;
ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
ip->ip_ttl = MAXTTL; ip->ip_ttl = MAXTTL;
@ -309,8 +315,8 @@ icmp_error(
ip->ip_src = alias_addr; ip->ip_src = alias_addr;
(void ) ip_output((struct socket *)NULL, m); (void ) ip_output((struct socket *)NULL, m);
icmpstat.icps_reflect++; STAT(icmpstat.icps_reflect++);
end_error: end_error:
return; return;
@ -367,5 +373,5 @@ icmp_reflect(m)
(void ) ip_output((struct socket *)NULL, m); (void ) ip_output((struct socket *)NULL, m);
icmpstat.icps_reflect++; STAT(icmpstat.icps_reflect++);
} }

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -43,10 +47,6 @@ typedef u_int32_t n_time;
/* /*
* Structure of an icmp header. * Structure of an icmp header.
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct icmp { struct icmp {
u_char icmp_type; /* type of message, see below */ u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */ u_char icmp_code; /* type sub code */
@ -92,11 +92,7 @@ struct icmp {
#define icmp_ip icmp_dun.id_ip.idi_ip #define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_mask icmp_dun.id_mask #define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data #define icmp_data icmp_dun.id_data
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
/* /*
* Lower bounds on packet lengths for various types. * Lower bounds on packet lengths for various types.
@ -161,8 +157,8 @@ struct icmp {
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
void icmp_input(struct mbuf *, int); void icmp_input _P((struct mbuf *, int));
void icmp_error(struct mbuf *, u_char, u_char, int, char *); void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
void icmp_reflect(struct mbuf *); void icmp_reflect _P((struct mbuf *));
#endif #endif

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -33,7 +37,7 @@
/* /*
* Changes and additions relating to SLiRP are * Changes and additions relating to SLiRP are
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -41,10 +45,19 @@
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
int ip_defttl; #ifdef LOG_ENABLED
struct ipstat ipstat; struct ipstat ipstat;
#endif
struct ipq ipq; struct ipq ipq;
static struct ip *ip_reass(register struct ipasfrag *ip,
register struct ipq *fp);
static void ip_freef(struct ipq *fp);
static void ip_enq(register struct ipasfrag *p,
register struct ipasfrag *prev);
static void ip_deq(register struct ipasfrag *p);
/* /*
* IP initialization: fill in IP protocol switch table. * IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler. * All protocols not implemented in kernel go to raw IP protocol handler.
@ -56,7 +69,6 @@ ip_init()
ip_id = tt.tv_sec & 0xffff; ip_id = tt.tv_sec & 0xffff;
udp_init(); udp_init();
tcp_init(); tcp_init();
ip_defttl = IPDEFTTL;
} }
/* /*
@ -68,38 +80,38 @@ ip_input(m)
struct mbuf *m; struct mbuf *m;
{ {
register struct ip *ip; register struct ip *ip;
u_int hlen; int hlen;
DEBUG_CALL("ip_input"); DEBUG_CALL("ip_input");
DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m_len = %zu", m->m_len); DEBUG_ARG("m_len = %d", m->m_len);
STAT(ipstat.ips_total++);
ipstat.ips_total++;
if (m->m_len < sizeof (struct ip)) { if (m->m_len < sizeof (struct ip)) {
ipstat.ips_toosmall++; STAT(ipstat.ips_toosmall++);
return; return;
} }
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
if (ip->ip_v != IPVERSION) { if (ip->ip_v != IPVERSION) {
ipstat.ips_badvers++; STAT(ipstat.ips_badvers++);
goto bad; goto bad;
} }
hlen = ip->ip_hl << 2; hlen = ip->ip_hl << 2;
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */ if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
ipstat.ips_badhlen++; /* or packet too short */ STAT(ipstat.ips_badhlen++); /* or packet too short */
goto bad; goto bad;
} }
/* keep ip header intact for ICMP reply /* keep ip header intact for ICMP reply
* ip->ip_sum = cksum(m, hlen); * ip->ip_sum = cksum(m, hlen);
* if (ip->ip_sum) { * if (ip->ip_sum) {
*/ */
if(cksum(m,hlen)) { if(cksum(m,hlen)) {
ipstat.ips_badsum++; STAT(ipstat.ips_badsum++);
goto bad; goto bad;
} }
@ -108,7 +120,7 @@ ip_input(m)
*/ */
NTOHS(ip->ip_len); NTOHS(ip->ip_len);
if (ip->ip_len < hlen) { if (ip->ip_len < hlen) {
ipstat.ips_badlen++; STAT(ipstat.ips_badlen++);
goto bad; goto bad;
} }
NTOHS(ip->ip_id); NTOHS(ip->ip_id);
@ -121,7 +133,7 @@ ip_input(m)
* Drop packet if shorter than we expect. * Drop packet if shorter than we expect.
*/ */
if (m->m_len < ip->ip_len) { if (m->m_len < ip->ip_len) {
ipstat.ips_tooshort++; STAT(ipstat.ips_tooshort++);
goto bad; goto bad;
} }
/* Should drop packet if mbuf too long? hmmm... */ /* Should drop packet if mbuf too long? hmmm... */
@ -150,7 +162,7 @@ ip_input(m)
* (We could look in the reassembly queue to see * (We could look in the reassembly queue to see
* if the packet was previously fragmented, * if the packet was previously fragmented,
* but it's not worth the time; just let them time out.) * but it's not worth the time; just let them time out.)
* *
* XXX This should fail, don't fragment yet * XXX This should fail, don't fragment yet
*/ */
if (ip->ip_off &~ IP_DF) { if (ip->ip_off &~ IP_DF) {
@ -177,7 +189,7 @@ ip_input(m)
ip->ip_len -= hlen; ip->ip_len -= hlen;
if (ip->ip_off & IP_MF) if (ip->ip_off & IP_MF)
((struct ipasfrag *)ip)->ipf_mff |= 1; ((struct ipasfrag *)ip)->ipf_mff |= 1;
else else
((struct ipasfrag *)ip)->ipf_mff &= ~1; ((struct ipasfrag *)ip)->ipf_mff &= ~1;
ip->ip_off <<= 3; ip->ip_off <<= 3;
@ -188,11 +200,11 @@ ip_input(m)
* attempt reassembly; if it succeeds, proceed. * attempt reassembly; if it succeeds, proceed.
*/ */
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
ipstat.ips_fragments++; STAT(ipstat.ips_fragments++);
ip = ip_reass((struct ipasfrag *)ip, fp); ip = ip_reass((struct ipasfrag *)ip, fp);
if (ip == 0) if (ip == 0)
return; return;
ipstat.ips_reassembled++; STAT(ipstat.ips_reassembled++);
m = dtom(ip); m = dtom(ip);
} else } else
if (fp) if (fp)
@ -204,7 +216,7 @@ ip_input(m)
/* /*
* Switch out to protocol's input routine. * Switch out to protocol's input routine.
*/ */
ipstat.ips_delivered++; STAT(ipstat.ips_delivered++);
switch (ip->ip_p) { switch (ip->ip_p) {
case IPPROTO_TCP: case IPPROTO_TCP:
tcp_input(m, hlen, (struct socket *)NULL); tcp_input(m, hlen, (struct socket *)NULL);
@ -216,7 +228,7 @@ ip_input(m)
icmp_input(m, hlen); icmp_input(m, hlen);
break; break;
default: default:
ipstat.ips_noproto++; STAT(ipstat.ips_noproto++);
m_free(m); m_free(m);
} }
return; return;
@ -231,16 +243,14 @@ bad:
* reassembly of this datagram already exists, then it * reassembly of this datagram already exists, then it
* is given as fp; otherwise have to make a chain. * is given as fp; otherwise have to make a chain.
*/ */
struct ip * static struct ip *
ip_reass(ip, fp) ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
register struct ipasfrag *ip;
register struct ipq *fp;
{ {
register struct mbuf *m = dtom(ip); register struct mbuf *m = dtom(ip);
register struct ipasfrag *q; register struct ipasfrag *q;
int hlen = ip->ip_hl << 2; int hlen = ip->ip_hl << 2;
int i, next; int i, next;
DEBUG_CALL("ip_reass"); DEBUG_CALL("ip_reass");
DEBUG_ARG("ip = %lx", (long)ip); DEBUG_ARG("ip = %lx", (long)ip);
DEBUG_ARG("fp = %lx", (long)fp); DEBUG_ARG("fp = %lx", (long)fp);
@ -271,7 +281,7 @@ ip_reass(ip, fp)
q = (struct ipasfrag *)fp; q = (struct ipasfrag *)fp;
goto insert; goto insert;
} }
/* /*
* Find a segment which begins after this one does. * Find a segment which begins after this one does.
*/ */
@ -365,7 +375,7 @@ insert:
ip = (struct ipasfrag *)(m->m_ext + delta); ip = (struct ipasfrag *)(m->m_ext + delta);
} }
/* DEBUG_ARG("ip = %lx", (long)ip); /* DEBUG_ARG("ip = %lx", (long)ip);
* ip=(struct ipasfrag *)m->m_data; */ * ip=(struct ipasfrag *)m->m_data; */
ip->ip_len = next; ip->ip_len = next;
@ -381,7 +391,7 @@ insert:
return ((struct ip *)ip); return ((struct ip *)ip);
dropfrag: dropfrag:
ipstat.ips_fragdropped++; STAT(ipstat.ips_fragdropped++);
m_freem(m); m_freem(m);
return (0); return (0);
} }
@ -390,9 +400,8 @@ dropfrag:
* Free a fragment reassembly header and all * Free a fragment reassembly header and all
* associated datagrams. * associated datagrams.
*/ */
void static void
ip_freef(fp) ip_freef(struct ipq *fp)
struct ipq *fp;
{ {
register struct ipasfrag *q, *p; register struct ipasfrag *q, *p;
@ -410,9 +419,8 @@ ip_freef(fp)
* Put an ip fragment on a reassembly chain. * Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure. * Like insque, but pointers in middle of structure.
*/ */
void static void
ip_enq(p, prev) ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
register struct ipasfrag *p, *prev;
{ {
DEBUG_CALL("ip_enq"); DEBUG_CALL("ip_enq");
DEBUG_ARG("prev = %lx", (long)prev); DEBUG_ARG("prev = %lx", (long)prev);
@ -425,9 +433,8 @@ ip_enq(p, prev)
/* /*
* To ip_enq as remque is to insque. * To ip_enq as remque is to insque.
*/ */
void static void
ip_deq(p) ip_deq(register struct ipasfrag *p)
register struct ipasfrag *p;
{ {
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
@ -442,9 +449,9 @@ void
ip_slowtimo() ip_slowtimo()
{ {
register struct ipq *fp; register struct ipq *fp;
DEBUG_CALL("ip_slowtimo"); DEBUG_CALL("ip_slowtimo");
fp = (struct ipq *) ipq.next; fp = (struct ipq *) ipq.next;
if (fp == 0) if (fp == 0)
return; return;
@ -453,7 +460,7 @@ ip_slowtimo()
--fp->ipq_ttl; --fp->ipq_ttl;
fp = (struct ipq *) fp->next; fp = (struct ipq *) fp->next;
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
ipstat.ips_fragtimeout++; STAT(ipstat.ips_fragtimeout++);
ip_freef((struct ipq *) fp->prev); ip_freef((struct ipq *) fp->prev);
} }
} }
@ -660,7 +667,7 @@ bad:
/* Not yet */ /* Not yet */
icmp_error(m, type, code, 0, 0); icmp_error(m, type, code, 0, 0);
ipstat.ips_badoptions++; STAT(ipstat.ips_badoptions++);
return (1); return (1);
} }
@ -688,6 +695,6 @@ ip_stripoptions(m, mopt)
i = m->m_len - (sizeof (struct ip) + olen); i = m->m_len - (sizeof (struct ip) + olen);
memcpy(opts, opts + olen, (unsigned)i); memcpy(opts, opts + olen, (unsigned)i);
m->m_len -= olen; m->m_len -= olen;
ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_hl = sizeof(struct ip) >> 2;
} }

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -42,6 +46,10 @@
u_int16_t ip_id; u_int16_t ip_id;
/* Number of packets queued before we start sending
* (to prevent allocing too many mbufs) */
#define IF_THRESH 10
/* /*
* IP output. The packet in mbuf chain m contains a skeletal IP * IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst). * header (with len, off, ttl, proto, tos, src, dst).
@ -55,14 +63,13 @@ ip_output(so, m0)
{ {
register struct ip *ip; register struct ip *ip;
register struct mbuf *m = m0; register struct mbuf *m = m0;
register u_int hlen = sizeof(struct ip); register int hlen = sizeof(struct ip );
u_int len, off; int len, off, error = 0;
int error = 0;
DEBUG_CALL("ip_output"); DEBUG_CALL("ip_output");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m0 = %lx", (long)m0); DEBUG_ARG("m0 = %lx", (long)m0);
/* We do no options */ /* We do no options */
/* if (opt) { /* if (opt) {
* m = ip_insertoptions(m, opt, &len); * m = ip_insertoptions(m, opt, &len);
@ -77,23 +84,23 @@ ip_output(so, m0)
ip->ip_off &= IP_DF; ip->ip_off &= IP_DF;
ip->ip_id = htons(ip_id++); ip->ip_id = htons(ip_id++);
ip->ip_hl = hlen >> 2; ip->ip_hl = hlen >> 2;
ipstat.ips_localout++; STAT(ipstat.ips_localout++);
/* /*
* Verify that we have any chance at all of being able to queue * Verify that we have any chance at all of being able to queue
* the packet or packet fragments * the packet or packet fragments
*/ */
/* XXX Hmmm... */ /* XXX Hmmm... */
/* if (if_queued > if_thresh && towrite <= 0) { /* if (if_queued > IF_THRESH && towrite <= 0) {
* error = ENOBUFS; * error = ENOBUFS;
* goto bad; * goto bad;
* } * }
*/ */
/* /*
* If small enough for interface, can just send directly. * If small enough for interface, can just send directly.
*/ */
if ((u_int16_t)ip->ip_len <= if_mtu) { if ((u_int16_t)ip->ip_len <= IF_MTU) {
ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_len = htons((u_int16_t)ip->ip_len);
ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_off = htons((u_int16_t)ip->ip_off);
ip->ip_sum = 0; ip->ip_sum = 0;
@ -109,11 +116,11 @@ ip_output(so, m0)
*/ */
if (ip->ip_off & IP_DF) { if (ip->ip_off & IP_DF) {
error = -1; error = -1;
ipstat.ips_cantfrag++; STAT(ipstat.ips_cantfrag++);
goto bad; goto bad;
} }
len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
if (len < 8) { if (len < 8) {
error = -1; error = -1;
goto bad; goto bad;
@ -129,18 +136,18 @@ ip_output(so, m0)
*/ */
m0 = m; m0 = m;
mhlen = sizeof (struct ip); mhlen = sizeof (struct ip);
for (off = hlen + len; off < ip->ip_len; off += len) { for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
register struct ip *mhip; register struct ip *mhip;
m = m_get(); m = m_get();
if (m == 0) { if (m == 0) {
error = -1; error = -1;
ipstat.ips_odropped++; STAT(ipstat.ips_odropped++);
goto sendorfree; goto sendorfree;
} }
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
mhip = mtod(m, struct ip *); mhip = mtod(m, struct ip *);
*mhip = *ip; *mhip = *ip;
/* No options */ /* No options */
/* if (hlen > sizeof (struct ip)) { /* if (hlen > sizeof (struct ip)) {
* mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
@ -153,28 +160,28 @@ ip_output(so, m0)
mhip->ip_off |= IP_MF; mhip->ip_off |= IP_MF;
if (off + len >= (u_int16_t)ip->ip_len) if (off + len >= (u_int16_t)ip->ip_len)
len = (u_int16_t)ip->ip_len - off; len = (u_int16_t)ip->ip_len - off;
else else
mhip->ip_off |= IP_MF; mhip->ip_off |= IP_MF;
mhip->ip_len = htons((u_int16_t)(len + mhlen)); mhip->ip_len = htons((u_int16_t)(len + mhlen));
if (m_copy(m, m0, off, len) < 0) { if (m_copy(m, m0, off, len) < 0) {
error = -1; error = -1;
goto sendorfree; goto sendorfree;
} }
mhip->ip_off = htons((u_int16_t)mhip->ip_off); mhip->ip_off = htons((u_int16_t)mhip->ip_off);
mhip->ip_sum = 0; mhip->ip_sum = 0;
mhip->ip_sum = cksum(m, mhlen); mhip->ip_sum = cksum(m, mhlen);
*mnext = m; *mnext = m;
mnext = &m->m_nextpkt; mnext = &m->m_nextpkt;
ipstat.ips_ofragments++; STAT(ipstat.ips_ofragments++);
} }
/* /*
* Update first fragment by trimming what's been copied out * Update first fragment by trimming what's been copied out
* and updating header, then send each fragment (in order). * and updating header, then send each fragment (in order).
*/ */
m = m0; m = m0;
m_adj(m, hlen + firstlen - ip->ip_len); m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
ip->ip_len = htons((u_int16_t)m->m_len); ip->ip_len = htons((u_int16_t)m->m_len);
ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
ip->ip_sum = 0; ip->ip_sum = 0;
@ -190,7 +197,7 @@ sendorfree:
} }
if (error == 0) if (error == 0)
ipstat.ips_fragmented++; STAT(ipstat.ips_fragmented++);
} }
done: done:

View File

@ -1,39 +1,33 @@
#ifndef _LIBSLIRP_H #ifndef _LIBSLIRP_H
#define _LIBSLIRP_H #define _LIBSLIRP_H
#ifdef _WIN32
#include <winsock2.h>
int inet_aton(const char *cp, struct in_addr *ia);
#else
#include <sys/select.h>
#include <arpa/inet.h>
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
int slirp_init(void); void slirp_init(void);
int slirp_select_fill(int *pnfds, void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds); fd_set *readfds, fd_set *writefds, fd_set *xfds);
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
void slirp_input(const uint8 *pkt, int pkt_len); void slirp_input(const uint8_t *pkt, int pkt_len);
/* you must provide the following functions: */ /* you must provide the following functions: */
int slirp_can_output(void); int slirp_can_output(void);
void slirp_output(const uint8 *pkt, int pkt_len); void slirp_output(const uint8_t *pkt, int pkt_len);
int slirp_redir(int is_udp, int host_port, int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port); struct in_addr guest_addr, int guest_port);
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
int guest_port); int guest_port);
extern const char *tftp_prefix; extern const char *tftp_prefix;
extern char slirp_hostname[33]; extern char slirp_hostname[33];
void slirp_stats(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -42,7 +42,6 @@ extern char *username;
extern char *socket_path; extern char *socket_path;
extern int towrite_max; extern int towrite_max;
extern int ppp_exit; extern int ppp_exit;
extern int so_options;
extern int tcp_keepintvl; extern int tcp_keepintvl;
extern uint8_t client_ethaddr[6]; extern uint8_t client_ethaddr[6];

View File

@ -15,54 +15,49 @@
* the flags * the flags
*/ */
#include <stdlib.h>
#include <slirp.h> #include <slirp.h>
struct mbuf *mbutl; struct mbuf *mbutl;
char *mclrefcnt; char *mclrefcnt;
int mbuf_alloced = 0; int mbuf_alloced = 0;
struct mbuf m_freelist, m_usedlist; struct mbuf m_freelist, m_usedlist;
int mbuf_thresh = 30; #define MBUF_THRESH 30
int mbuf_max = 0; int mbuf_max = 0;
size_t msize;
void m_init() /*
* Find a nice value for msize
* XXX if_maxlinkhdr already in mtu
*/
#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
void
m_init()
{ {
m_freelist.m_next = m_freelist.m_prev = &m_freelist; m_freelist.m_next = m_freelist.m_prev = &m_freelist;
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
msize_init();
}
void msize_init()
{
/*
* Find a nice value for msize
* XXX if_maxlinkhdr already in mtu
*/
msize = (if_mtu>if_mru?if_mtu:if_mru) +
if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
} }
/* /*
* Get an mbuf from the free list, if there are none * Get an mbuf from the free list, if there are none
* malloc one * malloc one
* *
* Because fragmentation can occur if we alloc new mbufs and * Because fragmentation can occur if we alloc new mbufs and
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
* which tells m_free to actually free() it * which tells m_free to actually free() it
*/ */
struct mbuf *m_get() struct mbuf *
m_get()
{ {
register struct mbuf *m; register struct mbuf *m;
int flags = 0; int flags = 0;
DEBUG_CALL("m_get"); DEBUG_CALL("m_get");
if (m_freelist.m_next == &m_freelist) { if (m_freelist.m_next == &m_freelist) {
m = (struct mbuf *)malloc(msize); m = (struct mbuf *)malloc(MSIZE);
if (m == NULL) goto end_error; if (m == NULL) goto end_error;
mbuf_alloced++; mbuf_alloced++;
if (mbuf_alloced > mbuf_thresh) if (mbuf_alloced > MBUF_THRESH)
flags = M_DOFREE; flags = M_DOFREE;
if (mbuf_alloced > mbuf_max) if (mbuf_alloced > mbuf_max)
mbuf_max = mbuf_alloced; mbuf_max = mbuf_alloced;
@ -70,13 +65,13 @@ struct mbuf *m_get()
m = m_freelist.m_next; m = m_freelist.m_next;
remque(m); remque(m);
} }
/* Insert it in the used list */ /* Insert it in the used list */
insque(m,&m_usedlist); insque(m,&m_usedlist);
m->m_flags = (flags | M_USEDLIST); m->m_flags = (flags | M_USEDLIST);
/* Initialise it */ /* Initialise it */
m->m_size = msize - sizeof(struct m_hdr); m->m_size = MSIZE - sizeof(struct m_hdr);
m->m_data = m->m_dat; m->m_data = m->m_dat;
m->m_len = 0; m->m_len = 0;
m->m_nextpkt = 0; m->m_nextpkt = 0;
@ -86,17 +81,19 @@ end_error:
return m; return m;
} }
void m_free(struct mbuf *m) void
m_free(m)
struct mbuf *m;
{ {
DEBUG_CALL("m_free"); DEBUG_CALL("m_free");
DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m = %lx", (long )m);
if(m) { if(m) {
/* Remove from m_usedlist */ /* Remove from m_usedlist */
if (m->m_flags & M_USEDLIST) if (m->m_flags & M_USEDLIST)
remque(m); remque(m);
/* If it's M_EXT, free() it */ /* If it's M_EXT, free() it */
if (m->m_flags & M_EXT) if (m->m_flags & M_EXT)
free(m->m_ext); free(m->m_ext);
@ -119,14 +116,16 @@ void m_free(struct mbuf *m)
* the other.. if result is too big for one mbuf, malloc() * the other.. if result is too big for one mbuf, malloc()
* an M_EXT data segment * an M_EXT data segment
*/ */
void m_cat(register struct mbuf *m, register struct mbuf *n) void
m_cat(m, n)
register struct mbuf *m, *n;
{ {
/* /*
* If there's no room, realloc * If there's no room, realloc
*/ */
if (M_FREEROOM(m) < n->m_len) if (M_FREEROOM(m) < n->m_len)
m_inc(m,m->m_size+MINCSIZE); m_inc(m,m->m_size+MINCSIZE);
memcpy(m->m_data+m->m_len, n->m_data, n->m_len); memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
m->m_len += n->m_len; m->m_len += n->m_len;
@ -135,20 +134,23 @@ void m_cat(register struct mbuf *m, register struct mbuf *n)
/* make m size bytes large */ /* make m size bytes large */
void m_inc(struct mbuf *m, u_int size) void
m_inc(m, size)
struct mbuf *m;
int size;
{ {
int datasize; int datasize;
/* some compiles throw up on gotos. This one we can fake. */ /* some compiles throw up on gotos. This one we can fake. */
if(m->m_size>size) return; if(m->m_size>size) return;
if (m->m_flags & M_EXT) { if (m->m_flags & M_EXT) {
datasize = m->m_data - m->m_ext; datasize = m->m_data - m->m_ext;
m->m_ext = (char *)realloc(m->m_ext,size); m->m_ext = (char *)realloc(m->m_ext,size);
/* if (m->m_ext == NULL) /* if (m->m_ext == NULL)
* return (struct mbuf *)NULL; * return (struct mbuf *)NULL;
*/ */
m->m_data = m->m_ext + datasize; m->m_data = m->m_ext + datasize;
} else { } else {
char *dat; char *dat;
datasize = m->m_data - m->m_dat; datasize = m->m_data - m->m_dat;
@ -157,19 +159,22 @@ void m_inc(struct mbuf *m, u_int size)
* return (struct mbuf *)NULL; * return (struct mbuf *)NULL;
*/ */
memcpy(dat, m->m_dat, m->m_size); memcpy(dat, m->m_dat, m->m_size);
m->m_ext = dat; m->m_ext = dat;
m->m_data = m->m_ext + datasize; m->m_data = m->m_ext + datasize;
m->m_flags |= M_EXT; m->m_flags |= M_EXT;
} }
m->m_size = size; m->m_size = size;
} }
void m_adj(struct mbuf *m, int len) void
m_adj(m, len)
struct mbuf *m;
int len;
{ {
if (m == NULL) if (m == NULL)
return; return;
@ -189,7 +194,9 @@ void m_adj(struct mbuf *m, int len)
* Copy len bytes from m, starting off bytes into n * Copy len bytes from m, starting off bytes into n
*/ */
int int
m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len) m_copy(n, m, off, len)
struct mbuf *n, *m;
int off, len;
{ {
if (len > M_FREEROOM(n)) if (len > M_FREEROOM(n))
return -1; return -1;
@ -205,10 +212,12 @@ m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len)
* XXX This is a kludge, I should eliminate the need for it * XXX This is a kludge, I should eliminate the need for it
* Fortunately, it's not used often * Fortunately, it's not used often
*/ */
struct mbuf *dtom(void *dat) struct mbuf *
dtom(dat)
void *dat;
{ {
struct mbuf *m; struct mbuf *m;
DEBUG_CALL("dtom"); DEBUG_CALL("dtom");
DEBUG_ARG("dat = %lx", (long )dat); DEBUG_ARG("dat = %lx", (long )dat);
@ -222,9 +231,9 @@ struct mbuf *dtom(void *dat)
return m; return m;
} }
} }
DEBUG_ERROR((dfd, "dtom failed")); DEBUG_ERROR((dfd, "dtom failed"));
return (struct mbuf *)0; return (struct mbuf *)0;
} }

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -63,14 +67,14 @@ struct m_hdr {
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
int mh_flags; /* Misc flags */ int mh_flags; /* Misc flags */
size_t mh_size; /* Size of data */ int mh_size; /* Size of data */
struct socket *mh_so; struct socket *mh_so;
caddr_t mh_data; /* Location of data */ caddr_t mh_data; /* Location of data */
size_t mh_len; /* Amount of data in this mbuf */ int mh_len; /* Amount of data in this mbuf */
}; };
/* /*
* How much room is in the mbuf, from m_data to the end of the mbuf * How much room is in the mbuf, from m_data to the end of the mbuf
*/ */
#define M_ROOM(m) ((m->m_flags & M_EXT)? \ #define M_ROOM(m) ((m->m_flags & M_EXT)? \
@ -122,7 +126,7 @@ struct mbuf {
struct mbstat { struct mbstat {
int mbs_alloced; /* Number of mbufs allocated */ int mbs_alloced; /* Number of mbufs allocated */
}; };
extern struct mbstat mbstat; extern struct mbstat mbstat;
@ -130,14 +134,13 @@ extern int mbuf_alloced;
extern struct mbuf m_freelist, m_usedlist; extern struct mbuf m_freelist, m_usedlist;
extern int mbuf_max; extern int mbuf_max;
void m_init(void); void m_init _P((void));
void msize_init(void); struct mbuf * m_get _P((void));
struct mbuf * m_get(void); void m_free _P((struct mbuf *));
void m_free(struct mbuf *); void m_cat _P((register struct mbuf *, register struct mbuf *));
void m_cat(register struct mbuf *, register struct mbuf *); void m_inc _P((struct mbuf *, int));
void m_inc(struct mbuf *, u_int); void m_adj _P((struct mbuf *, int));
void m_adj(struct mbuf *, int); int m_copy _P((struct mbuf *, struct mbuf *, int, int));
int m_copy(struct mbuf *, struct mbuf *, u_int, u_int); struct mbuf * dtom _P((void *));
struct mbuf * dtom(void *);
#endif #endif

View File

@ -1,23 +1,24 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#define WANT_SYS_IOCTL_H #define WANT_SYS_IOCTL_H
#include <stdlib.h>
#include <slirp.h> #include <slirp.h>
u_int curtime, time_fasttimo, last_slowtimo, detach_time; u_int curtime, time_fasttimo, last_slowtimo;
u_int detach_wait = 600000; /* 10 minutes */
#if 0 #if 0
int x_port = -1; int x_port = -1;
int x_display = 0; int x_display = 0;
int x_screen = 0; int x_screen = 0;
int show_x(char *buff, struct socket *inso) int
show_x(buff, inso)
char *buff;
struct socket *inso;
{ {
if (x_port < 0) { if (x_port < 0) {
lprint("X Redir: X not being redirected.\r\n"); lprint("X Redir: X not being redirected.\r\n");
@ -29,7 +30,7 @@ int show_x(char *buff, struct socket *inso)
if (x_display) if (x_display)
lprint("X Redir: Redirecting to display %d\r\n", x_display); lprint("X Redir: Redirecting to display %d\r\n", x_display);
} }
return CFG_OK; return CFG_OK;
} }
@ -37,10 +38,15 @@ int show_x(char *buff, struct socket *inso)
/* /*
* XXX Allow more than one X redirection? * XXX Allow more than one X redirection?
*/ */
void redir_x(u_int32_t inaddr, int start_port, int display, int screen) void
redir_x(inaddr, start_port, display, screen)
u_int32_t inaddr;
int start_port;
int display;
int screen;
{ {
int i; int i;
if (x_port >= 0) { if (x_port >= 0) {
lprint("X Redir: X already being redirected.\r\n"); lprint("X Redir: X already being redirected.\r\n");
show_x(0, 0); show_x(0, 0);
@ -61,33 +67,34 @@ void redir_x(u_int32_t inaddr, int start_port, int display, int screen)
#endif #endif
#ifndef HAVE_INET_ATON #ifndef HAVE_INET_ATON
int inet_aton(const char *cp, struct in_addr *ia) int
inet_aton(cp, ia)
const char *cp;
struct in_addr *ia;
{ {
return inet_pton(AF_INET, cp, &ia->s_addr); u_int32_t addr = inet_addr(cp);
if (addr == 0xffffffff)
return 0;
ia->s_addr = addr;
return 1;
} }
#endif #endif
/* /*
* Get our IP address and put it in our_addr * Get our IP address and put it in our_addr
*/ */
void getouraddr() void
getouraddr()
{ {
char buff[256]; char buff[256];
struct hostent *he = NULL;
if (gethostname(buff, sizeof(buff)) == 0) if (gethostname(buff,256) == 0)
{ he = gethostbyname(buff);
struct addrinfo hints = { 0 }; if (he)
hints.ai_flags = AI_NUMERICHOST; our_addr = *(struct in_addr *)he->h_addr;
hints.ai_family = AF_INET; if (our_addr.s_addr == 0)
struct addrinfo* ai; our_addr.s_addr = loopback_addr.s_addr;
if (getaddrinfo(buff, NULL, &hints, &ai) == 0)
{
our_addr = *(struct in_addr *)ai->ai_addr->sa_data;
freeaddrinfo(ai);
}
}
if (our_addr.s_addr == 0)
our_addr.s_addr = loopback_addr.s_addr;
} }
#if SIZEOF_CHAR_P == 8 #if SIZEOF_CHAR_P == 8
@ -97,7 +104,10 @@ struct quehead_32 {
u_int32_t qh_rlink; u_int32_t qh_rlink;
}; };
inline void insque_32(void *a, void *b) inline void
insque_32(a, b)
void *a;
void *b;
{ {
register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *element = (struct quehead_32 *) a;
register struct quehead_32 *head = (struct quehead_32 *) b; register struct quehead_32 *head = (struct quehead_32 *) b;
@ -108,7 +118,9 @@ inline void insque_32(void *a, void *b)
= (u_int32_t)element; = (u_int32_t)element;
} }
inline void remque_32(void *a) inline void
remque_32(a)
void *a;
{ {
register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *element = (struct quehead_32 *) a;
((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
@ -123,7 +135,9 @@ struct quehead {
struct quehead *qh_rlink; struct quehead *qh_rlink;
}; };
void insque(void *a, void *b) inline void
insque(a, b)
void *a, *b;
{ {
register struct quehead *element = (struct quehead *) a; register struct quehead *element = (struct quehead *) a;
register struct quehead *head = (struct quehead *) b; register struct quehead *head = (struct quehead *) b;
@ -134,7 +148,9 @@ void insque(void *a, void *b)
= (struct quehead *)element; = (struct quehead *)element;
} }
void remque(void *a) inline void
remque(a)
void *a;
{ {
register struct quehead *element = (struct quehead *) a; register struct quehead *element = (struct quehead *) a;
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
@ -146,16 +162,22 @@ void remque(void *a)
/* #endif */ /* #endif */
int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) int
add_exec(ex_ptr, do_pty, exec, addr, port)
struct ex_list **ex_ptr;
int do_pty;
char *exec;
int addr;
int port;
{ {
struct ex_list *tmp_ptr; struct ex_list *tmp_ptr;
/* First, check if the port is "bound" */ /* First, check if the port is "bound" */
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
return -1; return -1;
} }
tmp_ptr = *ex_ptr; tmp_ptr = *ex_ptr;
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
(*ex_ptr)->ex_fport = port; (*ex_ptr)->ex_fport = port;
@ -175,7 +197,9 @@ int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port
extern int sys_nerr; extern int sys_nerr;
extern char *sys_errlist[]; extern char *sys_errlist[];
char *strerror(int error) char *
strerror(error)
int error;
{ {
if (error < sys_nerr) if (error < sys_nerr)
return sys_errlist[error]; return sys_errlist[error];
@ -188,7 +212,8 @@ char *strerror(int error)
#ifdef _WIN32 #ifdef _WIN32
int fork_exec(struct socket *so, char *ex, int do_pty) int
fork_exec(struct socket *so, const char *ex, int do_pty)
{ {
/* not implemented */ /* not implemented */
return 0; return 0;
@ -196,13 +221,16 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
#else #else
int slirp_openpty(int *amaster, int *aslave) #ifndef CONFIG_QEMU
int
slirp_openpty(amaster, aslave)
int *amaster, *aslave;
{ {
register int master, slave; register int master, slave;
#ifdef HAVE_GRANTPT #ifdef HAVE_GRANTPT
char *ptr; char *ptr;
if ((master = open("/dev/ptmx", O_RDWR)) < 0 || if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
grantpt(master) < 0 || grantpt(master) < 0 ||
unlockpt(master) < 0 || unlockpt(master) < 0 ||
@ -210,7 +238,7 @@ int slirp_openpty(int *amaster, int *aslave)
close(master); close(master);
return -1; return -1;
} }
if ((slave = open(ptr, O_RDWR)) < 0 || if ((slave = open(ptr, O_RDWR)) < 0 ||
ioctl(slave, I_PUSH, "ptem") < 0 || ioctl(slave, I_PUSH, "ptem") < 0 ||
ioctl(slave, I_PUSH, "ldterm") < 0 || ioctl(slave, I_PUSH, "ldterm") < 0 ||
@ -219,16 +247,16 @@ int slirp_openpty(int *amaster, int *aslave)
close(slave); close(slave);
return -1; return -1;
} }
*amaster = master; *amaster = master;
*aslave = slave; *aslave = slave;
return 0; return 0;
#else #else
static char line[] = "/dev/ptyXX"; static char line[] = "/dev/ptyXX";
register const char *cp1, *cp2; register const char *cp1, *cp2;
for (cp1 = "pqrsPQRS"; *cp1; cp1++) { for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
line[8] = *cp1; line[8] = *cp1;
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
@ -258,6 +286,7 @@ int slirp_openpty(int *amaster, int *aslave)
return (-1); return (-1);
#endif #endif
} }
#endif
/* /*
* XXX This is ugly * XXX This is ugly
@ -265,53 +294,57 @@ int slirp_openpty(int *amaster, int *aslave)
* process, which connects to this socket, after which we * process, which connects to this socket, after which we
* exec the wanted program. If something (strange) happens, * exec the wanted program. If something (strange) happens,
* the accept() call could block us forever. * the accept() call could block us forever.
* *
* do_pty = 0 Fork/exec inetd style * do_pty = 0 Fork/exec inetd style
* do_pty = 1 Fork/exec using slirp.telnetd * do_pty = 1 Fork/exec using slirp.telnetd
* do_ptr = 2 Fork/exec using pty * do_ptr = 2 Fork/exec using pty
*/ */
int fork_exec(struct socket *so, char *ex, int do_pty) int
fork_exec(struct socket *so, const char *ex, int do_pty)
{ {
int s; int s;
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr); int addrlen = sizeof(addr);
int opt; int opt;
int master; int master = -1;
char *argv[256]; char *argv[256];
#if 0 #if 0
char buff[256]; char buff[256];
#endif #endif
/* don't want to clobber the original */ /* don't want to clobber the original */
char *bptr; char *bptr;
char *curarg; const char *curarg;
int c, i, ret; int c, i, ret;
DEBUG_CALL("fork_exec"); DEBUG_CALL("fork_exec");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("ex = %lx", (long)ex); DEBUG_ARG("ex = %lx", (long)ex);
DEBUG_ARG("do_pty = %lx", (long)do_pty); DEBUG_ARG("do_pty = %lx", (long)do_pty);
if (do_pty == 2) { if (do_pty == 2) {
#if 0
if (slirp_openpty(&master, &s) == -1) { if (slirp_openpty(&master, &s) == -1) {
lprint("Error: openpty failed: %s\n", strerror(errno)); lprint("Error: openpty failed: %s\n", strerror(errno));
return 0; return 0;
} }
#else
return 0;
#endif
} else { } else {
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = 0; addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
listen(s, 1) < 0) { listen(s, 1) < 0) {
lprint("Error: inet socket: %s\n", strerror(errno)); lprint("Error: inet socket: %s\n", strerror(errno));
closesocket(s); closesocket(s);
return 0; return 0;
} }
} }
switch(fork()) { switch(fork()) {
case -1: case -1:
lprint("Error: fork failed: %s\n", strerror(errno)); lprint("Error: fork failed: %s\n", strerror(errno));
@ -319,7 +352,7 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
if (do_pty == 2) if (do_pty == 2)
close(master); close(master);
return 0; return 0;
case 0: case 0:
/* Set the DISPLAY */ /* Set the DISPLAY */
if (do_pty == 2) { if (do_pty == 2) {
@ -341,7 +374,7 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
ret = connect(s, (struct sockaddr *)&addr, addrlen); ret = connect(s, (struct sockaddr *)&addr, addrlen);
} while (ret < 0 && errno == EINTR); } while (ret < 0 && errno == EINTR);
} }
#if 0 #if 0
if (x_port >= 0) { if (x_port >= 0) {
#ifdef HAVE_SETENV #ifdef HAVE_SETENV
@ -352,13 +385,13 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
putenv(buff); putenv(buff);
#endif #endif
} }
#endif #endif
dup2(s, 0); dup2(s, 0);
dup2(s, 1); dup2(s, 1);
dup2(s, 2); dup2(s, 2);
for (s = 3; s <= 255; s++) for (s = getdtablesize() - 1; s >= 3; s--)
close(s); close(s);
i = 0; i = 0;
bptr = strdup(ex); /* No need to free() this */ bptr = strdup(ex); /* No need to free() this */
if (do_pty == 1) { if (do_pty == 1) {
@ -376,21 +409,21 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
*bptr++ = (char)0; *bptr++ = (char)0;
argv[i++] = strdup(curarg); argv[i++] = strdup(curarg);
} while (c); } while (c);
argv[i] = 0; argv[i] = 0;
execvp(argv[0], argv); execvp(argv[0], argv);
/* Ooops, failed, let's tell the user why */ /* Ooops, failed, let's tell the user why */
{ {
char buff[256]; char buff[256];
sprintf(buff, "Error: execvp of %s failed: %s\n", sprintf(buff, "Error: execvp of %s failed: %s\n",
argv[0], strerror(errno)); argv[0], strerror(errno));
write(2, buff, strlen(buff)+1); write(2, buff, strlen(buff)+1);
} }
close(0); close(1); close(2); /* XXX */ close(0); close(1); close(2); /* XXX */
exit(1); exit(1);
default: default:
if (do_pty == 2) { if (do_pty == 2) {
close(s); close(s);
@ -413,32 +446,36 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
} }
fd_nonblock(so->s); fd_nonblock(so->s);
/* Append the telnet options now */ /* Append the telnet options now */
if (so->so_m != 0 && do_pty == 1) { if (so->so_m != 0 && do_pty == 1) {
sbappend(so, so->so_m); sbappend(so, so->so_m);
so->so_m = 0; so->so_m = 0;
} }
return 1; return 1;
} }
} }
#endif #endif
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
char *strdup(const char *str) char *
strdup(str)
const char *str;
{ {
char *bptr; char *bptr;
bptr = (char *)malloc(strlen(str)+1); bptr = (char *)malloc(strlen(str)+1);
strcpy(bptr, str); strcpy(bptr, str);
return bptr; return bptr;
} }
#endif #endif
#if 0 #if 0
void snooze_hup(int num) void
snooze_hup(num)
int num;
{ {
int s, ret; int s, ret;
#ifndef NO_UNIX_SOCKETS #ifndef NO_UNIX_SOCKETS
@ -446,7 +483,7 @@ void snooze_hup(int num)
#endif #endif
struct sockaddr_in sock_in; struct sockaddr_in sock_in;
char buff[256]; char buff[256];
ret = -1; ret = -1;
if (slirp_socket_passwd) { if (slirp_socket_passwd) {
s = socket(AF_INET, SOCK_STREAM, 0); s = socket(AF_INET, SOCK_STREAM, 0);
@ -476,48 +513,51 @@ void snooze_hup(int num)
#endif #endif
slirp_exit(0); slirp_exit(0);
} }
void snooze() void
snooze()
{ {
sigset_t s; sigset_t s;
int i; int i;
/* Don't need our data anymore */ /* Don't need our data anymore */
/* XXX This makes SunOS barf */ /* XXX This makes SunOS barf */
/* brk(0); */ /* brk(0); */
/* Close all fd's */ /* Close all fd's */
for (i = 255; i >= 0; i--) for (i = 255; i >= 0; i--)
close(i); close(i);
signal(SIGQUIT, slirp_exit); signal(SIGQUIT, slirp_exit);
signal(SIGHUP, snooze_hup); signal(SIGHUP, snooze_hup);
sigemptyset(&s); sigemptyset(&s);
/* Wait for any signal */ /* Wait for any signal */
sigsuspend(&s); sigsuspend(&s);
/* Just in case ... */ /* Just in case ... */
exit(255); exit(255);
} }
void relay(int s) void
relay(s)
int s;
{ {
char buf[8192]; char buf[8192];
int n; int n;
fd_set readfds; fd_set readfds;
struct ttys *ttyp; struct ttys *ttyp;
/* Don't need our data anymore */ /* Don't need our data anymore */
/* XXX This makes SunOS barf */ /* XXX This makes SunOS barf */
/* brk(0); */ /* brk(0); */
signal(SIGQUIT, slirp_exit); signal(SIGQUIT, slirp_exit);
signal(SIGHUP, slirp_exit); signal(SIGHUP, slirp_exit);
signal(SIGINT, slirp_exit); signal(SIGINT, slirp_exit);
signal(SIGTERM, slirp_exit); signal(SIGTERM, slirp_exit);
/* Fudge to get term_raw and term_restore to work */ /* Fudge to get term_raw and term_restore to work */
if (NULL == (ttyp = tty_attach (0, slirp_tty))) { if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
@ -526,18 +566,18 @@ void relay(int s)
ttyp->fd = 0; ttyp->fd = 0;
ttyp->flags |= TTY_CTTY; ttyp->flags |= TTY_CTTY;
term_raw(ttyp); term_raw(ttyp);
while (1) { while (1) {
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(0, &readfds); FD_SET(0, &readfds);
FD_SET(s, &readfds); FD_SET(s, &readfds);
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
if (n <= 0) if (n <= 0)
slirp_exit(0); slirp_exit(0);
if (FD_ISSET(0, &readfds)) { if (FD_ISSET(0, &readfds)) {
n = read(0, buf, 8192); n = read(0, buf, 8192);
if (n <= 0) if (n <= 0)
@ -546,7 +586,7 @@ void relay(int s)
if (n <= 0) if (n <= 0)
slirp_exit(0); slirp_exit(0);
} }
if (FD_ISSET(s, &readfds)) { if (FD_ISSET(s, &readfds)) {
n = read(s, buf, 8192); n = read(s, buf, 8192);
if (n <= 0) if (n <= 0)
@ -556,20 +596,43 @@ void relay(int s)
slirp_exit(0); slirp_exit(0);
} }
} }
/* Just in case.... */ /* Just in case.... */
exit(1); exit(1);
} }
#endif #endif
int (*lprint_print)(void *, const char *, va_list); #ifdef CONFIG_QEMU
char *lprint_ptr, *lprint_ptr2, **lprint_arg; extern void term_vprintf(const char *fmt, va_list ap);
void lprint(const char *format, ...) void lprint(const char *format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
term_vprintf(format, args);
va_end(args);
}
#else
int (*lprint_print) _P((void *, const char *, va_list));
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
void
#ifdef __STDC__
lprint(const char *format, ...)
#else
lprint(va_alist) va_dcl
#endif
{
va_list args;
#ifdef __STDC__
va_start(args, format);
#else
char *format;
va_start(args);
format = va_arg(args, char *);
#endif
#if 0 #if 0
/* If we're printing to an sbuf, make sure there's enough room */ /* If we're printing to an sbuf, make sure there's enough room */
/* XXX +100? */ /* XXX +100? */
@ -579,33 +642,33 @@ void lprint(const char *format, ...)
int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
int deltap = lprint_ptr - lprint_sb->sb_data; int deltap = lprint_ptr - lprint_sb->sb_data;
lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
lprint_sb->sb_datalen + TCP_SNDSPACE); lprint_sb->sb_datalen + TCP_SNDSPACE);
/* Adjust all values */ /* Adjust all values */
lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
lprint_ptr = lprint_sb->sb_data + deltap; lprint_ptr = lprint_sb->sb_data + deltap;
lprint_sb->sb_datalen += TCP_SNDSPACE; lprint_sb->sb_datalen += TCP_SNDSPACE;
} }
} }
#endif #endif
if (lprint_print) if (lprint_print)
lprint_ptr += (*lprint_print)(*lprint_arg, format, args); lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
/* Check if they want output to be logged to file as well */ /* Check if they want output to be logged to file as well */
if (lfd) { if (lfd) {
/* /*
* Remove \r's * Remove \r's
* otherwise you'll get ^M all over the file * otherwise you'll get ^M all over the file
*/ */
int len = strlen(format); int len = strlen(format);
char *bptr1, *bptr2; char *bptr1, *bptr2;
bptr1 = bptr2 = strdup(format); bptr1 = bptr2 = strdup(format);
while (len--) { while (len--) {
if (*bptr1 == '\r') if (*bptr1 == '\r')
memcpy(bptr1, bptr1+1, len+1); memcpy(bptr1, bptr1+1, len+1);
@ -618,7 +681,9 @@ void lprint(const char *format, ...)
va_end(args); va_end(args);
} }
void add_emu(char *buff) void
add_emu(buff)
char *buff;
{ {
u_int lport, fport; u_int lport, fport;
u_int8_t tos = 0, emu = 0; u_int8_t tos = 0, emu = 0;
@ -626,12 +691,12 @@ void add_emu(char *buff)
char *buff3 = buff4; char *buff3 = buff4;
struct emu_t *emup; struct emu_t *emup;
struct socket *so; struct socket *so;
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
lprint("Error: Bad arguments\r\n"); lprint("Error: Bad arguments\r\n");
return; return;
} }
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
lport = 0; lport = 0;
if (sscanf(buff1, "%d", &fport) != 1) { if (sscanf(buff1, "%d", &fport) != 1) {
@ -639,7 +704,7 @@ void add_emu(char *buff)
return; return;
} }
} }
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
buff3 = 0; buff3 = 0;
if (sscanf(buff2, "%256s", buff1) != 1) { if (sscanf(buff2, "%256s", buff1) != 1) {
@ -647,7 +712,7 @@ void add_emu(char *buff)
return; return;
} }
} }
if (buff3) { if (buff3) {
if (strcmp(buff3, "lowdelay") == 0) if (strcmp(buff3, "lowdelay") == 0)
tos = IPTOS_LOWDELAY; tos = IPTOS_LOWDELAY;
@ -658,7 +723,7 @@ void add_emu(char *buff)
return; return;
} }
} }
if (strcmp(buff1, "ftp") == 0) if (strcmp(buff1, "ftp") == 0)
emu = EMU_FTP; emu = EMU_FTP;
else if (strcmp(buff1, "irc") == 0) else if (strcmp(buff1, "irc") == 0)
@ -669,7 +734,7 @@ void add_emu(char *buff)
lprint("Error: Unknown service\r\n"); lprint("Error: Unknown service\r\n");
return; return;
} }
/* First, check that it isn't already emulated */ /* First, check that it isn't already emulated */
for (emup = tcpemu; emup; emup = emup->next) { for (emup = tcpemu; emup; emup = emup->next) {
if (emup->lport == lport && emup->fport == fport) { if (emup->lport == lport && emup->fport == fport) {
@ -677,7 +742,7 @@ void add_emu(char *buff)
return; return;
} }
} }
/* link it */ /* link it */
emup = (struct emu_t *)malloc(sizeof (struct emu_t)); emup = (struct emu_t *)malloc(sizeof (struct emu_t));
emup->lport = (u_int16_t)lport; emup->lport = (u_int16_t)lport;
@ -686,7 +751,7 @@ void add_emu(char *buff)
emup->emu = emu; emup->emu = emu;
emup->next = tcpemu; emup->next = tcpemu;
tcpemu = emup; tcpemu = emup;
/* And finally, mark all current sessions, if any, as being emulated */ /* And finally, mark all current sessions, if any, as being emulated */
for (so = tcb.so_next; so != &tcb; so = so->so_next) { for (so = tcb.so_next; so != &tcb; so = so->so_next) {
if ((lport && lport == ntohs(so->so_lport)) || if ((lport && lport == ntohs(so->so_lport)) ||
@ -697,9 +762,10 @@ void add_emu(char *buff)
so->so_iptos = tos; so->so_iptos = tos;
} }
} }
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
} }
#endif
#ifdef BAD_SPRINTF #ifdef BAD_SPRINTF
@ -710,33 +776,51 @@ void add_emu(char *buff)
* Some BSD-derived systems have a sprintf which returns char * * Some BSD-derived systems have a sprintf which returns char *
*/ */
int vsprintf_len(char *string, const char *format, va_list args) int
vsprintf_len(string, format, args)
char *string;
const char *format;
va_list args;
{ {
vsprintf(string, format, args); vsprintf(string, format, args);
return strlen(string); return strlen(string);
} }
int sprintf_len(char *string, const char *format, ...) int
#ifdef __STDC__
sprintf_len(char *string, const char *format, ...)
#else
sprintf_len(va_alist) va_dcl
#endif
{ {
va_list args; va_list args;
#ifdef __STDC__
va_start(args, format); va_start(args, format);
#else
char *string;
char *format;
va_start(args);
string = va_arg(args, char *);
format = va_arg(args, char *);
#endif
vsprintf(string, format, args); vsprintf(string, format, args);
va_end(args);
return strlen(string); return strlen(string);
} }
#endif #endif
void u_sleep(int usec) void
u_sleep(usec)
int usec;
{ {
struct timeval t; struct timeval t;
fd_set fdset; fd_set fdset;
FD_ZERO(&fdset); FD_ZERO(&fdset);
t.tv_sec = 0; t.tv_sec = 0;
t.tv_usec = usec * 1000; t.tv_usec = usec * 1000;
select(0, &fdset, &fdset, &fdset, &t); select(0, &fdset, &fdset, &fdset, &t);
} }
@ -744,30 +828,34 @@ void u_sleep(int usec)
* Set fd blocking and non-blocking * Set fd blocking and non-blocking
*/ */
void fd_nonblock(int fd) void
fd_nonblock(fd)
int fd;
{ {
#if defined USE_FIONBIO && defined FIONBIO #ifdef FIONBIO
ioctlsockopt_t opt = 1; int opt = 1;
ioctlsocket(fd, FIONBIO, &opt); ioctlsocket(fd, FIONBIO, &opt);
#else #else
int opt; int opt;
opt = fcntl(fd, F_GETFL, 0); opt = fcntl(fd, F_GETFL, 0);
opt |= O_NONBLOCK; opt |= O_NONBLOCK;
fcntl(fd, F_SETFL, opt); fcntl(fd, F_SETFL, opt);
#endif #endif
} }
void fd_block(int fd) void
fd_block(fd)
int fd;
{ {
#if defined USE_FIONBIO && defined FIONBIO #ifdef FIONBIO
ioctlsockopt_t opt = 0; int opt = 0;
ioctlsocket(fd, FIONBIO, &opt); ioctlsocket(fd, FIONBIO, &opt);
#else #else
int opt; int opt;
opt = fcntl(fd, F_GETFL, 0); opt = fcntl(fd, F_GETFL, 0);
opt &= ~O_NONBLOCK; opt &= ~O_NONBLOCK;
fcntl(fd, F_SETFL, opt); fcntl(fd, F_SETFL, opt);
@ -779,17 +867,22 @@ void fd_block(int fd)
/* /*
* invoke RSH * invoke RSH
*/ */
int rsh_exec(struct socket *so, struct socket *ns, int
char *user, char *host, char *args) rsh_exec(so,ns, user, host, args)
struct socket *so;
struct socket *ns;
char *user;
char *host;
char *args;
{ {
int fd[2]; int fd[2];
int fd0[2]; int fd0[2];
int s; int s;
char buff[256]; char buff[256];
DEBUG_CALL("rsh_exec"); DEBUG_CALL("rsh_exec");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
if (pipe(fd)<0) { if (pipe(fd)<0) {
lprint("Error: pipe failed: %s\n", strerror(errno)); lprint("Error: pipe failed: %s\n", strerror(errno));
return 0; return 0;
@ -810,7 +903,7 @@ int rsh_exec(struct socket *so, struct socket *ns,
return 0; return 0;
} }
#endif #endif
switch(fork()) { switch(fork()) {
case -1: case -1:
lprint("Error: fork failed: %s\n", strerror(errno)); lprint("Error: fork failed: %s\n", strerror(errno));
@ -819,11 +912,11 @@ int rsh_exec(struct socket *so, struct socket *ns,
close(fd0[0]); close(fd0[0]);
close(fd0[1]); close(fd0[1]);
return 0; return 0;
case 0: case 0:
close(fd[0]); close(fd[0]);
close(fd0[0]); close(fd0[0]);
/* Set the DISPLAY */ /* Set the DISPLAY */
if (x_port >= 0) { if (x_port >= 0) {
#ifdef HAVE_SETENV #ifdef HAVE_SETENV
@ -834,29 +927,29 @@ int rsh_exec(struct socket *so, struct socket *ns,
putenv(buff); putenv(buff);
#endif #endif
} }
dup2(fd0[1], 0); dup2(fd0[1], 0);
dup2(fd0[1], 1); dup2(fd0[1], 1);
dup2(fd[1], 2); dup2(fd[1], 2);
for (s = 3; s <= 255; s++) for (s = 3; s <= 255; s++)
close(s); close(s);
execlp("rsh","rsh","-l", user, host, args, NULL); execlp("rsh","rsh","-l", user, host, args, NULL);
/* Ooops, failed, let's tell the user why */ /* Ooops, failed, let's tell the user why */
sprintf(buff, "Error: execlp of %s failed: %s\n", sprintf(buff, "Error: execlp of %s failed: %s\n",
"rsh", strerror(errno)); "rsh", strerror(errno));
write(2, buff, strlen(buff)+1); write(2, buff, strlen(buff)+1);
close(0); close(1); close(2); /* XXX */ close(0); close(1); close(2); /* XXX */
exit(1); exit(1);
default: default:
close(fd[1]); close(fd[1]);
close(fd0[1]); close(fd0[1]);
ns->s=fd[0]; ns->s=fd[0];
so->s=fd0[0]; so->s=fd0[0];
return 1; return 1;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -12,22 +12,22 @@ struct ex_list {
int ex_pty; /* Do we want a pty? */ int ex_pty; /* Do we want a pty? */
int ex_addr; /* The last byte of the address */ int ex_addr; /* The last byte of the address */
int ex_fport; /* Port to telnet to */ int ex_fport; /* Port to telnet to */
char *ex_exec; /* Command line of what to exec */ const char *ex_exec; /* Command line of what to exec */
struct ex_list *ex_next; struct ex_list *ex_next;
}; };
extern struct ex_list *exec_list; extern struct ex_list *exec_list;
extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; extern u_int curtime, time_fasttimo, last_slowtimo;
extern int (*lprint_print)(void *, const char *, va_list); extern int (*lprint_print) _P((void *, const char *, va_list));
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
extern struct sbuf *lprint_sb; extern struct sbuf *lprint_sb;
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
char *strdup(const char *); char *strdup _P((const char *));
#endif #endif
void do_wait(int); void do_wait _P((int));
#define EMU_NONE 0x0 #define EMU_NONE 0x0
@ -63,25 +63,27 @@ struct emu_t {
struct emu_t *next; struct emu_t *next;
}; };
#ifndef CONFIG_QEMU
extern struct emu_t *tcpemu; extern struct emu_t *tcpemu;
#endif
extern int x_port, x_server, x_display; extern int x_port, x_server, x_display;
int show_x(char *, struct socket *); int show_x _P((char *, struct socket *));
void redir_x(u_int32_t, int, int, int); void redir_x _P((u_int32_t, int, int, int));
void getouraddr(void); void getouraddr _P((void));
void slirp_insque(void *, void *); inline void slirp_insque _P((void *, void *));
void slirp_remque(void *); inline void slirp_remque _P((void *));
int add_exec(struct ex_list **, int, char *, int, int); int add_exec _P((struct ex_list **, int, char *, int, int));
int slirp_openpty(int *, int *); int slirp_openpty _P((int *, int *));
int fork_exec(struct socket *, char *, int); int fork_exec(struct socket *so, const char *ex, int do_pty);
void snooze_hup(int); void snooze_hup _P((int));
void snooze(void); void snooze _P((void));
void relay(int); void relay _P((int));
void add_emu(char *); void add_emu _P((char *));
void u_sleep(int); void u_sleep _P((int));
void fd_nonblock(int); void fd_nonblock _P((int));
void fd_block(int); void fd_block _P((int));
int rsh_exec(struct socket *, struct socket *, char *, char *, char *); int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
#endif #endif

View File

@ -1,31 +1,37 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#include <stdlib.h>
#include <slirp.h> #include <slirp.h>
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
/* Done as a macro in socket.h */ /* Done as a macro in socket.h */
/* int /* int
* sbspace(struct sockbuff *sb) * sbspace(struct sockbuff *sb)
* { * {
* return SB_DATALEN - sb->sb_cc; * return SB_DATALEN - sb->sb_cc;
* } * }
*/ */
void sbfree(struct sbuf *sb) void
sbfree(sb)
struct sbuf *sb;
{ {
free(sb->sb_data); free(sb->sb_data);
} }
void sbdrop(struct sbuf *sb, u_int num) void
sbdrop(sb, num)
struct sbuf *sb;
int num;
{ {
/* /*
* We can only drop how much we have * We can only drop how much we have
* This should never succeed * This should never succeed
*/ */
if(num > sb->sb_cc) if(num > sb->sb_cc)
num = sb->sb_cc; num = sb->sb_cc;
@ -33,10 +39,13 @@ void sbdrop(struct sbuf *sb, u_int num)
sb->sb_rptr += num; sb->sb_rptr += num;
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
sb->sb_rptr -= sb->sb_datalen; sb->sb_rptr -= sb->sb_datalen;
} }
void sbreserve(struct sbuf *sb, size_t size) void
sbreserve(sb, size)
struct sbuf *sb;
int size;
{ {
if (sb->sb_data) { if (sb->sb_data) {
/* Already alloced, realloc if necessary */ /* Already alloced, realloc if necessary */
@ -64,21 +73,24 @@ void sbreserve(struct sbuf *sb, size_t size)
* this prevents an unnecessary copy of the data * this prevents an unnecessary copy of the data
* (the socket is non-blocking, so we won't hang) * (the socket is non-blocking, so we won't hang)
*/ */
void sbappend(struct socket *so, struct mbuf *m) void
sbappend(so, m)
struct socket *so;
struct mbuf *m;
{ {
int ret = 0; int ret = 0;
DEBUG_CALL("sbappend"); DEBUG_CALL("sbappend");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("m->m_len = %zu", m->m_len); DEBUG_ARG("m->m_len = %d", m->m_len);
/* Shouldn't happen, but... e.g. foreign host closes connection */ /* Shouldn't happen, but... e.g. foreign host closes connection */
if (m->m_len <= 0) { if (m->m_len <= 0) {
m_free(m); m_free(m);
return; return;
} }
/* /*
* If there is urgent data, call sosendoob * If there is urgent data, call sosendoob
* if not all was sent, sowrite will take care of the rest * if not all was sent, sowrite will take care of the rest
@ -90,16 +102,16 @@ void sbappend(struct socket *so, struct mbuf *m)
sosendoob(so); sosendoob(so);
return; return;
} }
/* /*
* We only write if there's nothing in the buffer, * We only write if there's nothing in the buffer,
* ottherwise it'll arrive out of order, and hence corrupt * ottherwise it'll arrive out of order, and hence corrupt
*/ */
if (!so->so_rcv.sb_cc) if (!so->so_rcv.sb_cc)
ret = send(so->s, m->m_data, m->m_len, 0); ret = send(so->s, m->m_data, m->m_len, 0);
if (ret <= 0) { if (ret <= 0) {
/* /*
* Nothing was written * Nothing was written
* It's possible that the socket has closed, but * It's possible that the socket has closed, but
* we don't need to check because if it has closed, * we don't need to check because if it has closed,
@ -123,10 +135,11 @@ void sbappend(struct socket *so, struct mbuf *m)
* Copy the data from m into sb * Copy the data from m into sb
* The caller is responsible to make sure there's enough room * The caller is responsible to make sure there's enough room
*/ */
void sbappendsb(struct sbuf *sb, struct mbuf *m) static void
sbappendsb(struct sbuf *sb, struct mbuf *m)
{ {
int len, n, nn; int len, n, nn;
len = m->m_len; len = m->m_len;
if (sb->sb_wptr < sb->sb_rptr) { if (sb->sb_wptr < sb->sb_rptr) {
@ -159,10 +172,15 @@ void sbappendsb(struct sbuf *sb, struct mbuf *m)
* Don't update the sbuf rptr, this will be * Don't update the sbuf rptr, this will be
* done in sbdrop when the data is acked * done in sbdrop when the data is acked
*/ */
void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to) void
sbcopy(sb, off, len, to)
struct sbuf *sb;
int off;
int len;
char *to;
{ {
char *from; char *from;
from = sb->sb_rptr + off; from = sb->sb_rptr + off;
if (from >= sb->sb_data + sb->sb_datalen) if (from >= sb->sb_data + sb->sb_datalen)
from -= sb->sb_datalen; from -= sb->sb_datalen;
@ -180,4 +198,4 @@ void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to)
memcpy(to+off,sb->sb_data,len); memcpy(to+off,sb->sb_data,len);
} }
} }

View File

@ -1,15 +1,13 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#ifndef _SBUF_H_ #ifndef _SBUF_H_
#define _SBUF_H_ #define _SBUF_H_
#include <stddef.h>
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc) #define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
@ -23,11 +21,10 @@ struct sbuf {
char *sb_data; /* Actual data */ char *sb_data; /* Actual data */
}; };
void sbfree(struct sbuf *); void sbfree _P((struct sbuf *));
void sbdrop(struct sbuf *, u_int); void sbdrop _P((struct sbuf *, int));
void sbreserve(struct sbuf *, size_t); void sbreserve _P((struct sbuf *, int));
void sbappend(struct socket *, struct mbuf *); void sbappend _P((struct socket *, struct mbuf *));
void sbappendsb(struct sbuf *, struct mbuf *); void sbcopy _P((struct sbuf *, int, int, char *));
void sbcopy(struct sbuf *, u_int, u_int, char *);
#endif #endif

View File

@ -12,7 +12,7 @@ struct in_addr special_addr;
/* virtual address alias for host */ /* virtual address alias for host */
struct in_addr alias_addr; struct in_addr alias_addr;
const uint8_t special_ethaddr[6] = { static const uint8_t special_ethaddr[6] = {
0x52, 0x54, 0x00, 0x12, 0x35, 0x00 0x52, 0x54, 0x00, 0x12, 0x35, 0x00
}; };
@ -38,10 +38,10 @@ static int get_dns_addr(struct in_addr *pdns_addr)
DWORD ret; DWORD ret;
IP_ADDR_STRING *pIPAddr; IP_ADDR_STRING *pIPAddr;
struct in_addr tmp_addr; struct in_addr tmp_addr;
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
BufLen = sizeof(FIXED_INFO); BufLen = sizeof(FIXED_INFO);
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
if (FixedInfo) { if (FixedInfo) {
GlobalFree(FixedInfo); GlobalFree(FixedInfo);
@ -49,7 +49,7 @@ static int get_dns_addr(struct in_addr *pdns_addr)
} }
FixedInfo = GlobalAlloc(GPTR, BufLen); FixedInfo = GlobalAlloc(GPTR, BufLen);
} }
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
if (FixedInfo) { if (FixedInfo) {
@ -58,14 +58,14 @@ static int get_dns_addr(struct in_addr *pdns_addr)
} }
return -1; return -1;
} }
pIPAddr = &(FixedInfo->DnsServerList); pIPAddr = &(FixedInfo->DnsServerList);
inet_aton(pIPAddr->IpAddress.String, &tmp_addr); inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
*pdns_addr = tmp_addr; *pdns_addr = tmp_addr;
#if 0 #if 0
printf( "DNS Servers:\n" ); printf( "DNS Servers:\n" );
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String ); printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
pIPAddr = FixedInfo -> DnsServerList.Next; pIPAddr = FixedInfo -> DnsServerList.Next;
while ( pIPAddr ) { while ( pIPAddr ) {
printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String ); printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
@ -84,16 +84,18 @@ static int get_dns_addr(struct in_addr *pdns_addr)
static int get_dns_addr(struct in_addr *pdns_addr) static int get_dns_addr(struct in_addr *pdns_addr)
{ {
char buff[512]; char buff[512];
char buff2[256+1]; char buff2[256];
FILE *f; FILE *f;
int found = 0; int found = 0;
struct in_addr tmp_addr; struct in_addr tmp_addr;
f = fopen("/etc/resolv.conf", "r"); f = fopen("/etc/resolv.conf", "r");
if (!f) if (!f)
return -1; return -1;
#ifdef DEBUG
lprint("IP address of your DNS(s): "); lprint("IP address of your DNS(s): ");
#endif
while (fgets(buff, 512, f) != NULL) { while (fgets(buff, 512, f) != NULL) {
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
if (!inet_aton(buff2, &tmp_addr)) if (!inet_aton(buff2, &tmp_addr))
@ -103,13 +105,20 @@ static int get_dns_addr(struct in_addr *pdns_addr)
/* If it's the first one, set it to dns_addr */ /* If it's the first one, set it to dns_addr */
if (!found) if (!found)
*pdns_addr = tmp_addr; *pdns_addr = tmp_addr;
#ifdef DEBUG
else else
lprint(", "); lprint(", ");
#endif
if (++found > 3) { if (++found > 3) {
#ifdef DEBUG
lprint("(more)"); lprint("(more)");
#endif
break; break;
} else }
#ifdef DEBUG
else
lprint("%s", inet_ntoa(tmp_addr)); lprint("%s", inet_ntoa(tmp_addr));
#endif
} }
} }
fclose(f); fclose(f);
@ -121,16 +130,16 @@ static int get_dns_addr(struct in_addr *pdns_addr)
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
void slirp_cleanup(void) static void slirp_cleanup(void)
{ {
WSACleanup(); WSACleanup();
} }
#endif #endif
int slirp_init(void) void slirp_init(void)
{ {
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT); // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
#ifdef _WIN32 #ifdef _WIN32
{ {
WSADATA Data; WSADATA Data;
@ -150,13 +159,14 @@ int slirp_init(void)
/* set default addresses */ /* set default addresses */
inet_aton("127.0.0.1", &loopback_addr); inet_aton("127.0.0.1", &loopback_addr);
if (get_dns_addr(&dns_addr) < 0) if (get_dns_addr(&dns_addr) < 0) {
return -1; dns_addr = loopback_addr;
fprintf (stderr, "Warning: No DNS servers found\n");
}
inet_aton(CTL_SPECIAL, &special_addr); inet_aton(CTL_SPECIAL, &special_addr);
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
getouraddr(); getouraddr();
return 0;
} }
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@ -179,56 +189,57 @@ static void updtime(void)
static void updtime(void) static void updtime(void)
{ {
gettimeofday(&tt, 0); gettimeofday(&tt, 0);
curtime = (u_int)tt.tv_sec * (u_int)1000; curtime = (u_int)tt.tv_sec * (u_int)1000;
curtime += (u_int)tt.tv_usec / (u_int)1000; curtime += (u_int)tt.tv_usec / (u_int)1000;
if ((tt.tv_usec % 1000) >= 500) if ((tt.tv_usec % 1000) >= 500)
curtime++; curtime++;
} }
#endif #endif
int slirp_select_fill(int *pnfds, void slirp_select_fill(int *pnfds,
fd_set *readfds, fd_set *writefds, fd_set *xfds) fd_set *readfds, fd_set *writefds, fd_set *xfds)
{ {
struct socket *so, *so_next; struct socket *so, *so_next;
struct timeval timeout;
int nfds; int nfds;
int timeout, tmp_time; int tmp_time;
/* fail safe */ /* fail safe */
global_readfds = NULL; global_readfds = NULL;
global_writefds = NULL; global_writefds = NULL;
global_xfds = NULL; global_xfds = NULL;
nfds = *pnfds; nfds = *pnfds;
/* /*
* First, TCP sockets * First, TCP sockets
*/ */
do_slowtimo = 0; do_slowtimo = 0;
if (link_up) { if (link_up) {
/* /*
* *_slowtimo needs calling if there are IP fragments * *_slowtimo needs calling if there are IP fragments
* in the fragment queue, or there are TCP connections active * in the fragment queue, or there are TCP connections active
*/ */
do_slowtimo = ((tcb.so_next != &tcb) || do_slowtimo = ((tcb.so_next != &tcb) ||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
for (so = tcb.so_next; so != &tcb; so = so_next) { for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next; so_next = so->so_next;
/* /*
* See if we need a tcp_fasttimo * See if we need a tcp_fasttimo
*/ */
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
time_fasttimo = curtime; /* Flag when we want a fasttimo */ time_fasttimo = curtime; /* Flag when we want a fasttimo */
/* /*
* NOFDREF can include still connecting to local-host, * NOFDREF can include still connecting to local-host,
* newly socreated() sockets etc. Don't want to select these. * newly socreated() sockets etc. Don't want to select these.
*/ */
if (so->so_state & SS_NOFDREF || so->s == -1) if (so->so_state & SS_NOFDREF || so->s == -1)
continue; continue;
/* /*
* Set for reading sockets which are accepting * Set for reading sockets which are accepting
*/ */
@ -237,7 +248,7 @@ int slirp_select_fill(int *pnfds,
UPD_NFDS(so->s); UPD_NFDS(so->s);
continue; continue;
} }
/* /*
* Set for writing sockets which are connecting * Set for writing sockets which are connecting
*/ */
@ -246,7 +257,7 @@ int slirp_select_fill(int *pnfds,
UPD_NFDS(so->s); UPD_NFDS(so->s);
continue; continue;
} }
/* /*
* Set for writing if we are connected, can send more, and * Set for writing if we are connected, can send more, and
* we have something to send * we have something to send
@ -255,7 +266,7 @@ int slirp_select_fill(int *pnfds,
FD_SET(so->s, writefds); FD_SET(so->s, writefds);
UPD_NFDS(so->s); UPD_NFDS(so->s);
} }
/* /*
* Set for reading (and urgent data) if we are connected, can * Set for reading (and urgent data) if we are connected, can
* receive more, and we have room for it XXX /2 ? * receive more, and we have room for it XXX /2 ?
@ -266,13 +277,13 @@ int slirp_select_fill(int *pnfds,
UPD_NFDS(so->s); UPD_NFDS(so->s);
} }
} }
/* /*
* UDP sockets * UDP sockets
*/ */
for (so = udb.so_next; so != &udb; so = so_next) { for (so = udb.so_next; so != &udb; so = so_next) {
so_next = so->so_next; so_next = so->so_next;
/* /*
* See if it's timed out * See if it's timed out
*/ */
@ -283,7 +294,7 @@ int slirp_select_fill(int *pnfds,
} else } else
do_slowtimo = 1; /* Let socket expire */ do_slowtimo = 1; /* Let socket expire */
} }
/* /*
* When UDP packets are received from over the * When UDP packets are received from over the
* link, they're sendto()'d straight away, so * link, they're sendto()'d straight away, so
@ -300,58 +311,51 @@ int slirp_select_fill(int *pnfds,
} }
} }
} }
/* /*
* Setup timeout to use minimum CPU usage, especially when idle * Setup timeout to use minimum CPU usage, especially when idle
*/ */
timeout = -1;
/* /*
* If a slowtimo is needed, set timeout to 5ms from the last * First, see the timeout needed by *timo
* slow timeout. If a fast timeout is needed, set timeout within */
* 2ms of when it was requested. timeout.tv_sec = 0;
timeout.tv_usec = -1;
/*
* If a slowtimo is needed, set timeout to 500ms from the last
* slow timeout. If a fast timeout is needed, set timeout within
* 200ms of when it was requested.
*/ */
# define SLOW_TIMO 5
# define FAST_TIMO 2
if (do_slowtimo) { if (do_slowtimo) {
timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000; /* XXX + 10000 because some select()'s aren't that accurate */
if (timeout < 0) timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
timeout = 0; if (timeout.tv_usec < 0)
else if (timeout > (SLOW_TIMO * 1000)) timeout.tv_usec = 0;
timeout = SLOW_TIMO * 1000; else if (timeout.tv_usec > 510000)
timeout.tv_usec = 510000;
/* Can only fasttimo if we also slowtimo */ /* Can only fasttimo if we also slowtimo */
if (time_fasttimo) { if (time_fasttimo) {
tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000; tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
if (tmp_time < 0) if (tmp_time < 0)
tmp_time = 0; tmp_time = 0;
/* Choose the smallest of the 2 */ /* Choose the smallest of the 2 */
if (tmp_time < timeout) if (tmp_time < timeout.tv_usec)
timeout = tmp_time; timeout.tv_usec = (u_int)tmp_time;
} }
} }
*pnfds = nfds; *pnfds = nfds;
}
/*
* Adjust the timeout to make the minimum timeout
* 2ms (XXX?) to lessen the CPU load
*/
if (timeout < (FAST_TIMO * 1000))
timeout = FAST_TIMO * 1000;
return timeout;
}
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
{ {
struct socket *so, *so_next; struct socket *so, *so_next;
int ret; int ret;
global_readfds = readfds; global_readfds = readfds;
global_writefds = writefds; global_writefds = writefds;
global_xfds = xfds; global_xfds = xfds;
/* Update time */ /* Update time */
updtime(); updtime();
@ -360,11 +364,11 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
* See if anything has timed out * See if anything has timed out
*/ */
if (link_up) { if (link_up) {
if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) { if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
tcp_fasttimo(); tcp_fasttimo();
time_fasttimo = 0; time_fasttimo = 0;
} }
if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) { if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
ip_slowtimo(); ip_slowtimo();
tcp_slowtimo(); tcp_slowtimo();
last_slowtimo = curtime; last_slowtimo = curtime;
@ -386,7 +390,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
* (and they can crash the program) * (and they can crash the program)
*/ */
if (so->so_state & SS_NOFDREF || so->s == -1) if (so->so_state & SS_NOFDREF || so->s == -1)
continue; continue;
/* /*
* Check for URG data * Check for URG data
@ -394,7 +398,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
* test for readfds below if this succeeds * test for readfds below if this succeeds
*/ */
if (FD_ISSET(so->s, xfds)) if (FD_ISSET(so->s, xfds))
sorecvoob(so); sorecvoob(so);
/* /*
* Check sockets for reading * Check sockets for reading
*/ */
@ -410,88 +414,82 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
/* Output it if we read something */ /* Output it if we read something */
if (ret > 0) if (ret > 0)
tcp_output(sototcpcb(so)); tcp_output(sototcpcb(so));
} }
/* /*
* Check sockets for writing * Check sockets for writing
*/ */
if (FD_ISSET(so->s, writefds)) { if (FD_ISSET(so->s, writefds)) {
/* /*
* Check for non-blocking, still-connecting sockets * Check for non-blocking, still-connecting sockets
*/ */
if (so->so_state & SS_ISFCONNECTING) { if (so->so_state & SS_ISFCONNECTING) {
/* Connected */ /* Connected */
so->so_state &= ~SS_ISFCONNECTING; so->so_state &= ~SS_ISFCONNECTING;
ret = send(so->s, (char*)&ret, 0, 0); ret = send(so->s, &ret, 0, 0);
if (ret < 0) { if (ret < 0) {
/* XXXXX Must fix, zero bytes is a NOP */ /* XXXXX Must fix, zero bytes is a NOP */
int error = WSAGetLastError(); if (errno == EAGAIN || errno == EWOULDBLOCK ||
if (error == EAGAIN || error == WSAEWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN)
error == WSAEINPROGRESS || error == WSAENOTCONN) continue;
continue;
/* else failed */ /* else failed */
so->so_state = SS_NOFDREF; so->so_state = SS_NOFDREF;
} }
/* else so->so_state &= ~SS_ISFCONNECTING; */ /* else so->so_state &= ~SS_ISFCONNECTING; */
/* /*
* Continue tcp_input * Continue tcp_input
*/ */
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
/* continue; */ /* continue; */
} } else
else ret = sowrite(so);
ret = sowrite(so); /*
/* * XXXXX If we wrote something (a lot), there
* XXXXX If we wrote something (a lot), there * could be a need for a window update.
* could be a need for a window update. * In the worst case, the remote will send
* In the worst case, the remote will send * a window probe to get things going again
* a window probe to get things going again */
*/
} }
/* /*
* Probe a still-connecting, non-blocking socket * Probe a still-connecting, non-blocking socket
* to check if it's still alive * to check if it's still alive
*/ */
#ifdef PROBE_CONN #ifdef PROBE_CONN
if (so->so_state & SS_ISFCONNECTING) { if (so->so_state & SS_ISFCONNECTING) {
ret = recv(so->s, (char *)&ret, 0, 0); ret = recv(so->s, (char *)&ret, 0,0);
if (ret < 0) { if (ret < 0) {
/* XXX */ /* XXX */
int error = WSAGetLastError(); if (errno == EAGAIN || errno == EWOULDBLOCK ||
if (error == EAGAIN || error == WSAEWOULDBLOCK || errno == EINPROGRESS || errno == ENOTCONN)
error == WSAEINPROGRESS || error == WSAENOTCONN) continue; /* Still connecting, continue */
continue; /* Still connecting, continue */
/* else failed */ /* else failed */
so->so_state = SS_NOFDREF; so->so_state = SS_NOFDREF;
/* tcp_input will take care of it */ /* tcp_input will take care of it */
} } else {
else { ret = send(so->s, &ret, 0,0);
ret = send(so->s, &ret, 0, 0); if (ret < 0) {
if (ret < 0) { /* XXX */
/* XXX */ if (errno == EAGAIN || errno == EWOULDBLOCK ||
int error = WSAGetLastError(); errno == EINPROGRESS || errno == ENOTCONN)
if (error == EAGAIN || error == WSAEWOULDBLOCK || continue;
error == WSAEINPROGRESS || error == WSAENOTCONN) /* else failed */
continue; so->so_state = SS_NOFDREF;
/* else failed */ } else
so->so_state = SS_NOFDREF; so->so_state &= ~SS_ISFCONNECTING;
}
else
so->so_state &= ~SS_ISFCONNECTING;
} }
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
} /* SS_ISFCONNECTING */ } /* SS_ISFCONNECTING */
#endif #endif
} }
/* /*
* Now UDP sockets. * Now UDP sockets.
@ -502,25 +500,25 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
so_next = so->so_next; so_next = so->so_next;
if (so->s != -1 && FD_ISSET(so->s, readfds)) { if (so->s != -1 && FD_ISSET(so->s, readfds)) {
sorecvfrom(so); sorecvfrom(so);
} }
} }
} }
/* /*
* See if we can start outputting * See if we can start outputting
*/ */
if (if_queued && link_up) if (if_queued && link_up)
if_start(); if_start();
/* clear global file descriptor sets. /* clear global file descriptor sets.
* these reside on the stack in vl.c * these reside on the stack in vl.c
* so they're unusable if we're not in * so they're unusable if we're not in
* slirp_select_fill or slirp_select_poll. * slirp_select_fill or slirp_select_poll.
*/ */
global_readfds = NULL; global_readfds = NULL;
global_writefds = NULL; global_writefds = NULL;
global_xfds = NULL; global_xfds = NULL;
} }
#define ETH_ALEN 6 #define ETH_ALEN 6
@ -532,7 +530,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
#define ARPOP_REQUEST 1 /* ARP request */ #define ARPOP_REQUEST 1 /* ARP request */
#define ARPOP_REPLY 2 /* ARP reply */ #define ARPOP_REPLY 2 /* ARP reply */
struct ethhdr struct ethhdr
{ {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */
@ -570,7 +568,7 @@ void arp_input(const uint8_t *pkt, int pkt_len)
switch(ar_op) { switch(ar_op) {
case ARPOP_REQUEST: case ARPOP_REQUEST:
if (!memcmp(ah->ar_tip, &special_addr, 3)) { if (!memcmp(ah->ar_tip, &special_addr, 3)) {
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
goto arp_ok; goto arp_ok;
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_addr == ah->ar_tip[3]) if (ex_ptr->ex_addr == ah->ar_tip[3])
@ -611,8 +609,8 @@ void slirp_input(const uint8_t *pkt, int pkt_len)
if (pkt_len < ETH_HLEN) if (pkt_len < ETH_HLEN)
return; return;
proto = (pkt[12] << 8) | pkt[13]; proto = ntohs(*(uint16_t *)(pkt + 12));
switch(proto) { switch(proto) {
case ETH_P_ARP: case ETH_P_ARP:
arp_input(pkt, pkt_len); arp_input(pkt, pkt_len);
@ -653,24 +651,24 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
slirp_output(buf, ip_data_len + ETH_HLEN); slirp_output(buf, ip_data_len + ETH_HLEN);
} }
int slirp_redir(int is_udp, int host_port, int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port) struct in_addr guest_addr, int guest_port)
{ {
if (is_udp) { if (is_udp) {
if (!udp_listen(htons(host_port), guest_addr.s_addr, if (!udp_listen(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0)) htons(guest_port), 0))
return -1; return -1;
} else { } else {
if (!solisten(htons(host_port), guest_addr.s_addr, if (!solisten(htons(host_port), guest_addr.s_addr,
htons(guest_port), 0)) htons(guest_port), 0))
return -1; return -1;
} }
return 0; return 0;
} }
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
int guest_port) int guest_port)
{ {
return add_exec(&exec_list, do_pty, (char *)args, return add_exec(&exec_list, do_pty, (char *)args,
addr_low_byte, htons(guest_port)); addr_low_byte, htons(guest_port));
} }

View File

@ -3,12 +3,21 @@
#define CONFIG_QEMU #define CONFIG_QEMU
#define DEBUG 1 //#define DEBUG 1
// Uncomment the following line to enable SLIRP statistics printing in Qemu
//#define LOG_ENABLED
#ifdef LOG_ENABLED
#define STAT(expr) expr
#else
#define STAT(expr) do { } while(0)
#endif
#ifndef CONFIG_QEMU #ifndef CONFIG_QEMU
#include "version.h" #include "version.h"
#endif #endif
#include "config.h" #include "config-host.h"
#include "slirp_config.h" #include "slirp_config.h"
#ifdef _WIN32 #ifdef _WIN32
@ -19,31 +28,20 @@ typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t; typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t; typedef uint64_t u_int64_t;
typedef char *caddr_t; typedef char *caddr_t;
typedef int socklen_t;
typedef unsigned long ioctlsockopt_t;
#define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <winsock2.h> # include <winsock2.h>
# include <WS2tcpip.h>
# include <sys/timeb.h> # include <sys/timeb.h>
# include <iphlpapi.h> # include <iphlpapi.h>
# define USE_FIONBIO 1 # define EWOULDBLOCK WSAEWOULDBLOCK
# define EINPROGRESS WSAEINPROGRESS
/* Basilisk II Router defines those */ # define ENOTCONN WSAENOTCONN
# define udp_read_completion slirp_udp_read_completion # define EHOSTUNREACH WSAEHOSTUNREACH
# define write_udp slirp_write_udp # define ENETUNREACH WSAENETUNREACH
# define init_udp slirp_init_udp # define ECONNREFUSED WSAECONNREFUSED
# define final_udp slirp_final_udp
#else #else
# define WSAGetLastError() (int)(errno)
# define WSASetLastError(e) (void)(errno = (e))
# define WSAEWOULDBLOCK EWOULDBLOCK
# define WSAEINPROGRESS EINPROGRESS
# define WSAENOTCONN ENOTCONN
# define WSAEHOSTUNREACH EHOSTUNREACH
# define WSAENETUNREACH ENETUNREACH
# define WSAECONNREFUSED ECONNREFUSED
typedef int ioctlsockopt_t;
# define ioctlsocket ioctl # define ioctlsocket ioctl
# define closesocket(s) close(s) # define closesocket(s) close(s)
# define O_BINARY 0 # define O_BINARY 0
@ -53,13 +51,8 @@ typedef int ioctlsockopt_t;
#ifdef HAVE_SYS_BITYPES_H #ifdef HAVE_SYS_BITYPES_H
# include <sys/bitypes.h> # include <sys/bitypes.h>
#endif #endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#ifndef _WIN32
#include <sys/time.h> #include <sys/time.h>
#endif
#ifdef NEED_TYPEDEFS #ifdef NEED_TYPEDEFS
typedef char int8_t; typedef char int8_t;
@ -90,11 +83,6 @@ typedef unsigned char u_int8_t;
# endif # endif
#endif /* NEED_TYPEDEFS */ #endif /* NEED_TYPEDEFS */
/* Basilisk II types glue */
typedef u_int8_t uint8;
typedef u_int16_t uint16;
typedef u_int32_t uint32;
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
@ -129,6 +117,17 @@ typedef u_int32_t uint32;
#ifndef _WIN32 #ifndef _WIN32
#include <sys/uio.h> #include <sys/uio.h>
#endif
#ifndef _P
#ifndef NO_PROTOTYPES
# define _P(x) x
#else
# define _P(x) ()
#endif
#endif
#ifndef _WIN32
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
@ -139,23 +138,20 @@ typedef u_int32_t uint32;
/* Systems lacking strdup() definition in <string.h>. */ /* Systems lacking strdup() definition in <string.h>. */
#if defined(ultrix) #if defined(ultrix)
char *strdup(const char *); char *strdup _P((const char *));
#endif #endif
/* Systems lacking malloc() definition in <stdlib.h>. */ /* Systems lacking malloc() definition in <stdlib.h>. */
#if defined(ultrix) || defined(hcx) #if defined(ultrix) || defined(hcx)
void *malloc(size_t arg); void *malloc _P((size_t arg));
void free(void *ptr); void free _P((void *ptr));
#endif #endif
#ifndef HAVE_INET_ATON #ifndef HAVE_INET_ATON
int inet_aton(const char *cp, struct in_addr *ia); int inet_aton _P((const char *cp, struct in_addr *ia));
#endif #endif
#include <fcntl.h> #include <fcntl.h>
#ifdef _WIN32
#include <io.h>
#endif
#ifndef NO_UNIX_SOCKETS #ifndef NO_UNIX_SOCKETS
#include <sys/un.h> #include <sys/un.h>
#endif #endif
@ -187,7 +183,11 @@ int inet_aton(const char *cp, struct in_addr *ia);
#include <ppp/slirppp.h> #include <ppp/slirppp.h>
#endif #endif
#ifdef __STDC__
#include <stdarg.h> #include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <sys/stat.h> #include <sys/stat.h>
@ -202,20 +202,6 @@ int inet_aton(const char *cp, struct in_addr *ia);
#include "debug.h" #include "debug.h"
#if defined __GNUC__
#define PACKED__ __attribute__ ((packed))
#elif defined _MSC_VER
#define PRAGMA_PACK_SUPPORTED 1
#define PACK_RESET
#define PACKED__
#elif defined __sgi
#define PRAGMA_PACK_SUPPORTED 1
#define PACK_RESET 0
#define PACKED__
#else
#error "Packed attribute or pragma shall be supported"
#endif
#include "ip.h" #include "ip.h"
#include "tcp.h" #include "tcp.h"
#include "tcp_timer.h" #include "tcp_timer.h"
@ -246,47 +232,45 @@ extern struct ttys *ttys_unit[MAX_INTERFACES];
#endif #endif
#ifndef FULL_BOLT #ifndef FULL_BOLT
void if_start(void); void if_start _P((void));
#else #else
void if_start(struct ttys *); void if_start _P((struct ttys *));
#endif #endif
#ifdef BAD_SPRINTF #ifdef BAD_SPRINTF
# define vsprintf vsprintf_len # define vsprintf vsprintf_len
# define sprintf sprintf_len # define sprintf sprintf_len
extern int vsprintf_len(char *, const char *, va_list); extern int vsprintf_len _P((char *, const char *, va_list));
extern int sprintf_len(char *, const char *, ...); extern int sprintf_len _P((char *, const char *, ...));
#endif #endif
#ifdef DECLARE_SPRINTF #ifdef DECLARE_SPRINTF
# ifndef BAD_SPRINTF # ifndef BAD_SPRINTF
extern int vsprintf(char *, const char *, va_list); extern int vsprintf _P((char *, const char *, va_list));
# endif # endif
extern int vfprintf(FILE *, const char *, va_list); extern int vfprintf _P((FILE *, const char *, va_list));
#endif #endif
#ifndef HAVE_STRERROR #ifndef HAVE_STRERROR
extern char *strerror(int error); extern char *strerror _P((int error));
#endif #endif
#ifndef HAVE_INDEX #ifndef HAVE_INDEX
char *index(const char *, int); char *index _P((const char *, int));
#endif #endif
#ifndef HAVE_GETHOSTID #ifndef HAVE_GETHOSTID
long gethostid(void); long gethostid _P((void));
#endif #endif
void lprint(const char *, ...); void lprint _P((const char *, ...));
extern int do_echo;
#if SIZEOF_CHAR_P == 4 #if SIZEOF_CHAR_P == 4
# define insque_32 insque # define insque_32 insque
# define remque_32 remque # define remque_32 remque
#else #else
extern inline void insque_32(void *, void *); inline void insque_32 _P((void *, void *));
extern inline void remque_32(void *); inline void remque_32 _P((void *));
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
@ -295,51 +279,46 @@ extern int do_echo;
#define DEFAULT_BAUD 115200 #define DEFAULT_BAUD 115200
#define SO_OPTIONS DO_KEEPALIVE
#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
/* cksum.c */ /* cksum.c */
int cksum(struct mbuf *m, int len); int cksum(struct mbuf *m, int len);
/* if.c */ /* if.c */
void if_init(void); void if_init _P((void));
void if_output(struct socket *, struct mbuf *); void if_output _P((struct socket *, struct mbuf *));
/* ip_input.c */ /* ip_input.c */
void ip_init(void); void ip_init _P((void));
void ip_input(struct mbuf *); void ip_input _P((struct mbuf *));
struct ip * ip_reass(register struct ipasfrag *, register struct ipq *); void ip_slowtimo _P((void));
void ip_freef(struct ipq *); void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
void ip_enq(register struct ipasfrag *, register struct ipasfrag *);
void ip_deq(register struct ipasfrag *);
void ip_slowtimo(void);
void ip_stripoptions(register struct mbuf *, struct mbuf *);
/* ip_output.c */ /* ip_output.c */
int ip_output(struct socket *, struct mbuf *); int ip_output _P((struct socket *, struct mbuf *));
/* tcp_input.c */ /* tcp_input.c */
int tcp_reass(register struct tcpcb *, register struct tcpiphdr *, struct mbuf *); void tcp_input _P((register struct mbuf *, int, struct socket *));
void tcp_input(register struct mbuf *, int, struct socket *); int tcp_mss _P((register struct tcpcb *, u_int));
void tcp_dooptions(struct tcpcb *, u_char *, int, struct tcpiphdr *);
void tcp_xmit_timer(register struct tcpcb *, int);
u_int tcp_mss(register struct tcpcb *, u_int);
/* tcp_output.c */ /* tcp_output.c */
int tcp_output(register struct tcpcb *); int tcp_output _P((register struct tcpcb *));
void tcp_setpersist(register struct tcpcb *); void tcp_setpersist _P((register struct tcpcb *));
/* tcp_subr.c */ /* tcp_subr.c */
void tcp_init(void); void tcp_init _P((void));
void tcp_template(struct tcpcb *); void tcp_template _P((struct tcpcb *));
void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int); void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
struct tcpcb * tcp_newtcpcb(struct socket *); struct tcpcb * tcp_newtcpcb _P((struct socket *));
struct tcpcb * tcp_close(register struct tcpcb *); struct tcpcb * tcp_close _P((register struct tcpcb *));
void tcp_drain(void); void tcp_sockclosed _P((struct tcpcb *));
void tcp_sockclosed(struct tcpcb *); int tcp_fconnect _P((struct socket *));
int tcp_fconnect(struct socket *); void tcp_connect _P((struct socket *));
void tcp_connect(struct socket *); int tcp_attach _P((struct socket *));
int tcp_attach(struct socket *); u_int8_t tcp_tos _P((struct socket *));
u_int8_t tcp_tos(struct socket *); int tcp_emu _P((struct socket *, struct mbuf *));
int tcp_emu(struct socket *, struct mbuf *); int tcp_ctl _P((struct socket *));
int tcp_ctl(struct socket *);
struct tcpcb *tcp_drop(struct tcpcb *tp, int err); struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
#ifdef USE_PPP #ifdef USE_PPP
@ -355,4 +334,9 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
#define max(x,y) ((x) > (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y))
#endif #endif
#ifdef _WIN32
#undef errno
#define errno (WSAGetLastError())
#endif
#endif #endif

View File

@ -40,6 +40,11 @@
*/ */
#undef USE_LOWCPU #undef USE_LOWCPU
/* Define this if your compiler doesn't like prototypes */
#ifndef __STDC__
#define NO_PROTOTYPES
#endif
/*********************************************************/ /*********************************************************/
/* /*
* Autoconf defined configuration options * Autoconf defined configuration options
@ -49,11 +54,40 @@
/* Ignore this */ /* Ignore this */
#undef DUMMY_PPP #undef DUMMY_PPP
/* XXX: Define according to how time.h should be included */ /* Define if you have unistd.h */
#undef TIME_WITH_SYS_TIME #define HAVE_UNISTD_H
/* Define if you have stdlib.h */
#define HAVE_STDLIB_H
/* Define if you have sys/ioctl.h */
#undef HAVE_SYS_IOCTL_H
#ifndef _WIN32
#define HAVE_SYS_IOCTL_H
#endif
/* Define if you have sys/filio.h */
#undef HAVE_SYS_FILIO_H
#ifdef __APPLE__
#define HAVE_SYS_FILIO_H
#endif
/* Define if you have strerror */
#define HAVE_STRERROR
/* Define if you have strdup() */
#define HAVE_STRDUP
/* Define according to how time.h should be included */
#define TIME_WITH_SYS_TIME 0 #define TIME_WITH_SYS_TIME 0
#undef HAVE_SYS_TIME_H #undef HAVE_SYS_TIME_H
/* Define if you have sys/bitypes.h */
#undef HAVE_SYS_BITYPES_H
/* Define if the machine is big endian */
//#undef WORDS_BIGENDIAN
/* Define if your sprintf returns char * instead of int */ /* Define if your sprintf returns char * instead of int */
#undef BAD_SPRINTF #undef BAD_SPRINTF
@ -69,17 +103,56 @@
/* Define if a declaration of sprintf/fprintf is needed */ /* Define if a declaration of sprintf/fprintf is needed */
#undef DECLARE_SPRINTF #undef DECLARE_SPRINTF
/* Define if you have a POSIX.1 sys/wait.h */
#undef HAVE_SYS_WAIT_H
/* Define if you have sys/select.h */
#undef HAVE_SYS_SELECT_H
#ifndef _WIN32
#define HAVE_SYS_SELECT_H
#endif
/* Define if you have strings.h */
#define HAVE_STRING_H
/* Define if you have arpa/inet.h */
#undef HAVE_ARPA_INET_H
#ifndef _WIN32
#define HAVE_ARPA_INET_H
#endif
/* Define if you have sys/signal.h */
#undef HAVE_SYS_SIGNAL_H
/* Define if you have sys/stropts.h */ /* Define if you have sys/stropts.h */
#undef HAVE_SYS_STROPTS_H #undef HAVE_SYS_STROPTS_H
/* Define to whatever your compiler thinks inline should be */
#define inline inline
/* Define to whatever your compiler thinks const should be */
#define const const
/* Define if your compiler doesn't like prototypes */
#undef NO_PROTOTYPES
/* Define if you don't have u_int32_t etc. typedef'd */ /* Define if you don't have u_int32_t etc. typedef'd */
#undef NEED_TYPEDEFS #undef NEED_TYPEDEFS
#ifdef __sun__ #ifdef __sun__
#define NEED_TYPEDEFS #define NEED_TYPEDEFS
#endif #endif
/* Define to sizeof(char) */
#define SIZEOF_CHAR 1
/* Define to sizeof(short) */
#define SIZEOF_SHORT 2
/* Define to sizeof(int) */
#define SIZEOF_INT 4
/* Define to sizeof(char *) */ /* Define to sizeof(char *) */
#define SIZEOF_CHAR_P SIZEOF_VOID_P #define SIZEOF_CHAR_P (HOST_LONG_BITS / 8)
/* Define if you have random() */ /* Define if you have random() */
#undef HAVE_RANDOM #undef HAVE_RANDOM
@ -87,6 +160,12 @@
/* Define if you have srandom() */ /* Define if you have srandom() */
#undef HAVE_SRANDOM #undef HAVE_SRANDOM
/* Define if you have inet_aton */
#undef HAVE_INET_ATON
#ifndef _WIN32
#define HAVE_INET_ATON
#endif
/* Define if you have setenv */ /* Define if you have setenv */
#undef HAVE_SETENV #undef HAVE_SETENV

View File

@ -1,12 +1,11 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#define WANT_SYS_IOCTL_H #define WANT_SYS_IOCTL_H
#include <stdlib.h>
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
#include "main.h" #include "main.h"
@ -14,18 +13,16 @@
#include <sys/filio.h> #include <sys/filio.h>
#endif #endif
#ifdef _WIN32 static void sofcantrcvmore(struct socket *so);
#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN) static void sofcantsendmore(struct socket *so);
#else
#define IS_EAGAIN(e) ((e) == EAGAIN)
#endif
void #if 0
static void
so_init() so_init()
{ {
/* Nothing yet */ /* Nothing yet */
} }
#endif
struct socket * struct socket *
solookup(head, laddr, lport, faddr, fport) solookup(head, laddr, lport, faddr, fport)
@ -36,19 +33,19 @@ solookup(head, laddr, lport, faddr, fport)
u_int fport; u_int fport;
{ {
struct socket *so; struct socket *so;
for (so = head->so_next; so != head; so = so->so_next) { for (so = head->so_next; so != head; so = so->so_next) {
if (so->so_lport == lport && if (so->so_lport == lport &&
so->so_laddr.s_addr == laddr.s_addr && so->so_laddr.s_addr == laddr.s_addr &&
so->so_faddr.s_addr == faddr.s_addr && so->so_faddr.s_addr == faddr.s_addr &&
so->so_fport == fport) so->so_fport == fport)
break; break;
} }
if (so == head) if (so == head)
return (struct socket *)NULL; return (struct socket *)NULL;
return so; return so;
} }
/* /*
@ -60,7 +57,7 @@ struct socket *
socreate() socreate()
{ {
struct socket *so; struct socket *so;
so = (struct socket *)malloc(sizeof(struct socket)); so = (struct socket *)malloc(sizeof(struct socket));
if(so) { if(so) {
memset(so, 0, sizeof(struct socket)); memset(so, 0, sizeof(struct socket));
@ -85,10 +82,10 @@ sofree(so)
tcp_last_so = &tcb; tcp_last_so = &tcb;
else if (so == udp_last_so) else if (so == udp_last_so)
udp_last_so = &udb; udp_last_so = &udb;
m_free(so->so_m); m_free(so->so_m);
if(so->so_next && so->so_prev) if(so->so_next && so->so_prev)
remque(so); /* crashes if so is not in a queue */ remque(so); /* crashes if so is not in a queue */
free(so); free(so);
@ -103,23 +100,22 @@ int
soread(so) soread(so)
struct socket *so; struct socket *so;
{ {
int n, nn; int n, nn, lss, total;
u_int lss, total;
struct sbuf *sb = &so->so_snd; struct sbuf *sb = &so->so_snd;
u_int len = sb->sb_datalen - sb->sb_cc; int len = sb->sb_datalen - sb->sb_cc;
struct iovec iov[2]; struct iovec iov[2];
u_int mss = so->so_tcpcb->t_maxseg; int mss = so->so_tcpcb->t_maxseg;
DEBUG_CALL("soread"); DEBUG_CALL("soread");
DEBUG_ARG("so = %lx", (long )so); DEBUG_ARG("so = %lx", (long )so);
/* /*
* No need to check if there's enough room to read. * No need to check if there's enough room to read.
* soread wouldn't have been called if there weren't * soread wouldn't have been called if there weren't
*/ */
len = sb->sb_datalen - sb->sb_cc; len = sb->sb_datalen - sb->sb_cc;
iov[0].iov_base = sb->sb_wptr; iov[0].iov_base = sb->sb_wptr;
if (sb->sb_wptr < sb->sb_rptr) { if (sb->sb_wptr < sb->sb_rptr) {
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
@ -158,16 +154,15 @@ soread(so)
n = 1; n = 1;
} }
} }
#ifdef HAVE_READV #ifdef HAVE_READV
nn = readv(so->s, (struct iovec *)iov, n); nn = readv(so->s, (struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else #else
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif #endif
if (nn <= 0) { if (nn <= 0) {
int error = WSAGetLastError(); if (nn < 0 && (errno == EINTR || errno == EAGAIN))
if (nn < 0 && IS_EAGAIN(error))
return 0; return 0;
else { else {
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
@ -176,7 +171,7 @@ soread(so)
return -1; return -1;
} }
} }
#ifndef HAVE_READV #ifndef HAVE_READV
/* /*
* If there was no error, try and read the second time round * If there was no error, try and read the second time round
@ -193,10 +188,10 @@ soread(so)
if (ret > 0) if (ret > 0)
nn += ret; nn += ret;
} }
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#endif #endif
/* Update fields */ /* Update fields */
sb->sb_cc += nn; sb->sb_cc += nn;
sb->sb_wptr += nn; sb->sb_wptr += nn;
@ -204,10 +199,10 @@ soread(so)
sb->sb_wptr -= sb->sb_datalen; sb->sb_wptr -= sb->sb_datalen;
return nn; return nn;
} }
/* /*
* Get urgent data * Get urgent data
* *
* When the socket is created, we set it SO_OOBINLINE, * When the socket is created, we set it SO_OOBINLINE,
* so when OOB data arrives, we soread() it and everything * so when OOB data arrives, we soread() it and everything
* in the send buffer is sent as urgent data * in the send buffer is sent as urgent data
@ -220,13 +215,13 @@ sorecvoob(so)
DEBUG_CALL("sorecvoob"); DEBUG_CALL("sorecvoob");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
/* /*
* We take a guess at how much urgent data has arrived. * We take a guess at how much urgent data has arrived.
* In most situations, when urgent data arrives, the next * In most situations, when urgent data arrives, the next
* read() should get all the urgent data. This guess will * read() should get all the urgent data. This guess will
* be wrong however if more data arrives just after the * be wrong however if more data arrives just after the
* urgent data, or the read() doesn't return all the * urgent data, or the read() doesn't return all the
* urgent data. * urgent data.
*/ */
soread(so); soread(so);
@ -246,24 +241,24 @@ sosendoob(so)
{ {
struct sbuf *sb = &so->so_rcv; struct sbuf *sb = &so->so_rcv;
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
int n, len; int n, len;
DEBUG_CALL("sosendoob"); DEBUG_CALL("sosendoob");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
if (so->so_urgc > 2048) if (so->so_urgc > 2048)
so->so_urgc = 2048; /* XXXX */ so->so_urgc = 2048; /* XXXX */
if (sb->sb_rptr < sb->sb_wptr) { if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */ /* We can send it directly */
n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
so->so_urgc -= n; so->so_urgc -= n;
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
} else { } else {
/* /*
* Since there's no sendv or sendtov like writev, * Since there's no sendv or sendtov like writev,
* we must copy all data to a linear buffer then * we must copy all data to a linear buffer then
* send it all * send it all
@ -283,20 +278,20 @@ sosendoob(so)
#ifdef DEBUG #ifdef DEBUG
if (n != len) if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
#endif #endif
DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
} }
sb->sb_cc -= n; sb->sb_cc -= n;
sb->sb_rptr += n; sb->sb_rptr += n;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen; sb->sb_rptr -= sb->sb_datalen;
return n; return n;
} }
/* /*
* Write data from so_rcv to so's socket, * Write data from so_rcv to so's socket,
* updating all sbuf field as necessary * updating all sbuf field as necessary
*/ */
int int
@ -305,12 +300,12 @@ sowrite(so)
{ {
int n,nn; int n,nn;
struct sbuf *sb = &so->so_rcv; struct sbuf *sb = &so->so_rcv;
u_int len = sb->sb_cc; int len = sb->sb_cc;
struct iovec iov[2]; struct iovec iov[2];
DEBUG_CALL("sowrite"); DEBUG_CALL("sowrite");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
if (so->so_urgc) { if (so->so_urgc) {
sosendoob(so); sosendoob(so);
if (sb->sb_cc == 0) if (sb->sb_cc == 0)
@ -321,9 +316,9 @@ sowrite(so)
* No need to check if there's something to write, * No need to check if there's something to write,
* sowrite wouldn't have been called otherwise * sowrite wouldn't have been called otherwise
*/ */
len = sb->sb_cc; len = sb->sb_cc;
iov[0].iov_base = sb->sb_rptr; iov[0].iov_base = sb->sb_rptr;
if (sb->sb_rptr < sb->sb_wptr) { if (sb->sb_rptr < sb->sb_wptr) {
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
@ -346,17 +341,14 @@ sowrite(so)
#ifdef HAVE_READV #ifdef HAVE_READV
nn = writev(so->s, (const struct iovec *)iov, n); nn = writev(so->s, (const struct iovec *)iov, n);
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else #else
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif #endif
/* This should never happen, but people tell me it does *shrug* */ /* This should never happen, but people tell me it does *shrug* */
if (nn < 0) { if (nn < 0 && (errno == EAGAIN || errno == EINTR))
int error = WSAGetLastError(); return 0;
if (IS_EAGAIN(error))
return 0;
}
if (nn <= 0) { if (nn <= 0) {
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
@ -365,7 +357,7 @@ sowrite(so)
tcp_sockclosed(sototcpcb(so)); tcp_sockclosed(sototcpcb(so));
return -1; return -1;
} }
#ifndef HAVE_READV #ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) { if (n == 2 && nn == iov[0].iov_len) {
int ret; int ret;
@ -375,20 +367,20 @@ sowrite(so)
} }
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#endif #endif
/* Update sbuf */ /* Update sbuf */
sb->sb_cc -= nn; sb->sb_cc -= nn;
sb->sb_rptr += nn; sb->sb_rptr += nn;
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
sb->sb_rptr -= sb->sb_datalen; sb->sb_rptr -= sb->sb_datalen;
/* /*
* If in DRAIN mode, and there's no more data, set * If in DRAIN mode, and there's no more data, set
* it CANTSENDMORE * it CANTSENDMORE
*/ */
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
sofcantsendmore(so); sofcantsendmore(so);
return nn; return nn;
} }
@ -400,26 +392,25 @@ sorecvfrom(so)
struct socket *so; struct socket *so;
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addrlen = sizeof(struct sockaddr_in); int addrlen = sizeof(struct sockaddr_in);
DEBUG_CALL("sorecvfrom"); DEBUG_CALL("sorecvfrom");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
char buff[256]; char buff[256];
int len; int len;
len = recvfrom(so->s, buff, 256, 0, len = recvfrom(so->s, buff, 256, 0,
(struct sockaddr *)&addr, &addrlen); (struct sockaddr *)&addr, &addrlen);
/* XXX Check if reply is "correct"? */ /* XXX Check if reply is "correct"? */
if(len == -1 || len == 0) { if(len == -1 || len == 0) {
u_char code=ICMP_UNREACH_PORT; u_char code=ICMP_UNREACH_PORT;
int error = WSAGetLastError(); if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
@ -431,38 +422,36 @@ sorecvfrom(so)
udp_detach(so); udp_detach(so);
} else { /* A "normal" UDP packet */ } else { /* A "normal" UDP packet */
struct mbuf *m; struct mbuf *m;
u_int len; int len, n;
ioctlsockopt_t n;
if (!(m = m_get())) return; if (!(m = m_get())) return;
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
/* /*
* XXX Shouldn't FIONREAD packets destined for port 53, * XXX Shouldn't FIONREAD packets destined for port 53,
* but I don't know the max packet size for DNS lookups * but I don't know the max packet size for DNS lookups
*/ */
len = M_FREEROOM(m); len = M_FREEROOM(m);
/* if (so->so_fport != htons(53)) { */ /* if (so->so_fport != htons(53)) { */
ioctlsocket(so->s, FIONREAD, &n); ioctlsocket(so->s, FIONREAD, &n);
if (n > len) { if (n > len) {
n = (m->m_data - m->m_dat) + m->m_len + n + 1; n = (m->m_data - m->m_dat) + m->m_len + n + 1;
m_inc(m, n); m_inc(m, n);
len = M_FREEROOM(m); len = M_FREEROOM(m);
} }
/* } */ /* } */
m->m_len = recvfrom(so->s, m->m_data, len, 0, m->m_len = recvfrom(so->s, m->m_data, len, 0,
(struct sockaddr *)&addr, &addrlen); (struct sockaddr *)&addr, &addrlen);
DEBUG_MISC((dfd, " did recvfrom %zu, errno = %d-%s\n", DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
m->m_len, errno,strerror(errno))); m->m_len, errno,strerror(errno)));
if(m->m_len<0) { if(m->m_len<0) {
u_char code=ICMP_UNREACH_PORT; u_char code=ICMP_UNREACH_PORT;
int error = WSAGetLastError(); if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
m_free(m); m_free(m);
@ -485,8 +474,8 @@ sorecvfrom(so)
* m->m_len = 0; * m->m_len = 0;
* } * }
*/ */
/* /*
* If this packet was destined for CTL_ADDR, * If this packet was destined for CTL_ADDR,
* make it look like that's where it came from, done by udp_output * make it look like that's where it came from, done by udp_output
*/ */
@ -509,7 +498,7 @@ sosendto(so, m)
DEBUG_CALL("sosendto"); DEBUG_CALL("sosendto");
DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("so = %lx", (long)so);
DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m = %lx", (long)m);
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
/* It's an alias */ /* It's an alias */
@ -526,16 +515,14 @@ sosendto(so, m)
addr.sin_addr = so->so_faddr; addr.sin_addr = so->so_faddr;
addr.sin_port = so->so_fport; addr.sin_port = so->so_fport;
char addrstr[INET_ADDRSTRLEN]; DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n",
ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr, addrstr, sizeof(addrstr))));
/* Don't care what port we get */ /* Don't care what port we get */
ret = sendto(so->s, m->m_data, m->m_len, 0, ret = sendto(so->s, m->m_data, m->m_len, 0,
(struct sockaddr *)&addr, sizeof (struct sockaddr)); (struct sockaddr *)&addr, sizeof (struct sockaddr));
if (ret < 0) if (ret < 0)
return -1; return -1;
/* /*
* Kill the socket if there's no reply in 4 minutes, * Kill the socket if there's no reply in 4 minutes,
* but only if it's an expirable socket * but only if it's an expirable socket
@ -558,57 +545,58 @@ solisten(port, laddr, lport, flags)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
struct socket *so; struct socket *so;
int s; int s, addrlen = sizeof(addr), opt = 1;
socklen_t addrlen = sizeof(addr);
int opt = 1;
DEBUG_CALL("solisten"); DEBUG_CALL("solisten");
DEBUG_ARG("port = %d", port); DEBUG_ARG("port = %d", port);
DEBUG_ARG("laddr = %x", laddr); DEBUG_ARG("laddr = %x", laddr);
DEBUG_ARG("lport = %d", lport); DEBUG_ARG("lport = %d", lport);
DEBUG_ARG("flags = %x", flags); DEBUG_ARG("flags = %x", flags);
if ((so = socreate()) == NULL) { if ((so = socreate()) == NULL) {
/* free(so); Not sofree() ??? free(NULL) == NOP */ /* free(so); Not sofree() ??? free(NULL) == NOP */
return NULL; return NULL;
} }
/* Don't tcp_attach... we don't need so_snd nor so_rcv */ /* Don't tcp_attach... we don't need so_snd nor so_rcv */
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
free(so); free(so);
return NULL; return NULL;
} }
insque(so,&tcb); insque(so,&tcb);
/* /*
* SS_FACCEPTONCE sockets must time out. * SS_FACCEPTONCE sockets must time out.
*/ */
if (flags & SS_FACCEPTONCE) if (flags & SS_FACCEPTONCE)
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
so->so_state = (SS_FACCEPTCONN|flags); so->so_state = (SS_FACCEPTCONN|flags);
so->so_lport = lport; /* Kept in network format */ so->so_lport = lport; /* Kept in network format */
so->so_laddr.s_addr = laddr; /* Ditto */ so->so_laddr.s_addr = laddr; /* Ditto */
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = port; addr.sin_port = port;
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
(listen(s,1) < 0)) { (listen(s,1) < 0)) {
int error = WSAGetLastError(); /* Don't clobber the real reason we failed */ int tmperrno = errno; /* Don't clobber the real reason we failed */
close(s); close(s);
sofree(so); sofree(so);
/* Restore the real errno */ /* Restore the real errno */
WSASetLastError(error); #ifdef _WIN32
WSASetLastError(tmperrno);
#else
errno = tmperrno;
#endif
return NULL; return NULL;
} }
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
getsockname(s,(struct sockaddr *)&addr,&addrlen); getsockname(s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port; so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
@ -620,30 +608,32 @@ solisten(port, laddr, lport, flags)
return so; return so;
} }
/* #if 0
/*
* Data is available in so_rcv * Data is available in so_rcv
* Just write() the data to the socket * Just write() the data to the socket
* XXX not yet... * XXX not yet...
*/ */
void static void
sorwakeup(so) sorwakeup(so)
struct socket *so; struct socket *so;
{ {
/* sowrite(so); */ /* sowrite(so); */
/* FD_CLR(so->s,&writefds); */ /* FD_CLR(so->s,&writefds); */
} }
/* /*
* Data has been freed in so_snd * Data has been freed in so_snd
* We have room for a read() if we want to * We have room for a read() if we want to
* For now, don't read, it'll be done in the main loop * For now, don't read, it'll be done in the main loop
*/ */
void static void
sowwakeup(so) sowwakeup(so)
struct socket *so; struct socket *so;
{ {
/* Nothing, yet */ /* Nothing, yet */
} }
#endif
/* /*
* Various session state calls * Various session state calls
@ -668,9 +658,8 @@ soisfconnected(so)
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
} }
void static void
sofcantrcvmore(so) sofcantrcvmore(struct socket *so)
struct socket *so;
{ {
if ((so->so_state & SS_NOFDREF) == 0) { if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s,0); shutdown(so->s,0);
@ -685,9 +674,8 @@ sofcantrcvmore(so)
so->so_state |= SS_FCANTRCVMORE; so->so_state |= SS_FCANTRCVMORE;
} }
void static void
sofcantsendmore(so) sofcantsendmore(struct socket *so)
struct socket *so;
{ {
if ((so->so_state & SS_NOFDREF) == 0) { if ((so->so_state & SS_NOFDREF) == 0) {
shutdown(so->s,1); /* send FIN to fhost */ shutdown(so->s,1); /* send FIN to fhost */

View File

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -33,21 +33,21 @@ struct socket {
struct in_addr so_laddr; /* local host table entry */ struct in_addr so_laddr; /* local host table entry */
u_int16_t so_fport; /* foreign port */ u_int16_t so_fport; /* foreign port */
u_int16_t so_lport; /* local port */ u_int16_t so_lport; /* local port */
u_int8_t so_iptos; /* Type of service */ u_int8_t so_iptos; /* Type of service */
u_int8_t so_emu; /* Is the socket emulated? */ u_int8_t so_emu; /* Is the socket emulated? */
u_char so_type; /* Type of socket, UDP or TCP */ u_char so_type; /* Type of socket, UDP or TCP */
int so_state; /* internal state flags SS_*, below */ int so_state; /* internal state flags SS_*, below */
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
u_int so_expire; /* When the socket will expire */ u_int so_expire; /* When the socket will expire */
int so_queued; /* Number of packets queued from this socket */ int so_queued; /* Number of packets queued from this socket */
int so_nqueued; /* Number of packets queued in a row int so_nqueued; /* Number of packets queued in a row
* Used to determine when to "downgrade" a session * Used to determine when to "downgrade" a session
* from fastq to batchq */ * from fastq to batchq */
struct sbuf so_rcv; /* Receive buffer */ struct sbuf so_rcv; /* Receive buffer */
struct sbuf so_snd; /* Send buffer */ struct sbuf so_snd; /* Send buffer */
void * extra; /* Extra pointer */ void * extra; /* Extra pointer */
@ -81,24 +81,19 @@ struct iovec {
}; };
#endif #endif
void so_init(void); struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); struct socket * socreate _P((void));
struct socket * socreate(void); void sofree _P((struct socket *));
void sofree(struct socket *); int soread _P((struct socket *));
int soread(struct socket *); void sorecvoob _P((struct socket *));
void sorecvoob(struct socket *); int sosendoob _P((struct socket *));
int sosendoob(struct socket *); int sowrite _P((struct socket *));
int sowrite(struct socket *); void sorecvfrom _P((struct socket *));
void sorecvfrom(struct socket *); int sosendto _P((struct socket *, struct mbuf *));
int sosendto(struct socket *, struct mbuf *); struct socket * solisten _P((u_int, u_int32_t, u_int, int));
struct socket * solisten(u_int, u_int32_t, u_int, int); void soisfconnecting _P((register struct socket *));
void sorwakeup(struct socket *); void soisfconnected _P((register struct socket *));
void sowwakeup(struct socket *); void soisfdisconnected _P((struct socket *));
void soisfconnecting(register struct socket *); void sofwdrain _P((struct socket *));
void soisfconnected(register struct socket *);
void sofcantrcvmore(struct socket *);
void sofcantsendmore(struct socket *);
void soisfdisconnected(struct socket *);
void sofwdrain(struct socket *);
#endif /* _SOCKET_H_ */ #endif /* _SOCKET_H_ */

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -38,8 +42,6 @@ typedef u_int32_t tcp_seq;
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
extern size_t tcp_rcvspace;
extern size_t tcp_sndspace;
extern struct socket *tcp_last_so; extern struct socket *tcp_last_so;
#define TCP_SNDSPACE 8192 #define TCP_SNDSPACE 8192
@ -49,20 +51,16 @@ extern struct socket *tcp_last_so;
* TCP header. * TCP header.
* Per RFC 793, September, 1981. * Per RFC 793, September, 1981.
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct tcphdr { struct tcphdr {
u_int16_t th_sport; /* source port */ u_int16_t th_sport; /* source port */
u_int16_t th_dport; /* destination port */ u_int16_t th_dport; /* destination port */
tcp_seq th_seq; /* sequence number */ tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */ tcp_seq th_ack; /* acknowledgement number */
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
u_char th_off:4, /* data offset */ u_int th_off:4, /* data offset */
th_x2:4; /* (unused) */ th_x2:4; /* (unused) */
#else #else
u_char th_x2:4, /* (unused) */ u_int th_x2:4, /* (unused) */
th_off:4; /* data offset */ th_off:4; /* data offset */
#endif #endif
u_int8_t th_flags; u_int8_t th_flags;
@ -75,11 +73,7 @@ struct tcphdr {
u_int16_t th_win; /* window */ u_int16_t th_win; /* window */
u_int16_t th_sum; /* checksum */ u_int16_t th_sum; /* checksum */
u_int16_t th_urp; /* urgent pointer */ u_int16_t th_urp; /* urgent pointer */
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
#include "tcp_var.h" #include "tcp_var.h"
@ -176,6 +170,6 @@ struct tcphdr {
extern tcp_seq tcp_iss; /* tcp initial send seq # */ extern tcp_seq tcp_iss; /* tcp initial send seq # */
extern char *tcpstates[]; extern const char * const tcpstates[];
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -33,8 +37,8 @@
/* /*
* Changes and additions relating to SLiRP * Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
@ -44,16 +48,16 @@
* Since this is only used in "stats socket", we give meaning * Since this is only used in "stats socket", we give meaning
* names instead of the REAL names * names instead of the REAL names
*/ */
char *tcpstates[] = { const char * const tcpstates[] = {
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
}; };
u_char tcp_outflags[TCP_NSTATES] = { static const u_char tcp_outflags[TCP_NSTATES] = {
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
TH_FIN|TH_ACK, TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK,
}; };
@ -63,7 +67,9 @@ u_char tcp_outflags[TCP_NSTATES] = {
/* /*
* Tcp output routine: figure out what should be sent and send it. * Tcp output routine: figure out what should be sent and send it.
*/ */
int tcp_output(register struct tcpcb *tp) int
tcp_output(tp)
register struct tcpcb *tp;
{ {
register struct socket *so = tp->t_socket; register struct socket *so = tp->t_socket;
register long len, win; register long len, win;
@ -73,10 +79,10 @@ int tcp_output(register struct tcpcb *tp)
u_char opt[MAX_TCPOPTLEN]; u_char opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen; unsigned optlen, hdrlen;
int idle, sendalot; int idle, sendalot;
DEBUG_CALL("tcp_output"); DEBUG_CALL("tcp_output");
DEBUG_ARG("tp = %lx", (long )tp); DEBUG_ARG("tp = %lx", (long )tp);
/* /*
* Determine length of data that should be transmitted, * Determine length of data that should be transmitted,
* and flags that will be used. * and flags that will be used.
@ -97,9 +103,9 @@ again:
win = min(tp->snd_wnd, tp->snd_cwnd); win = min(tp->snd_wnd, tp->snd_cwnd);
flags = tcp_outflags[tp->t_state]; flags = tcp_outflags[tp->t_state];
DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags)); DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
/* /*
* If in persist timeout with window of 0, send 1 byte. * If in persist timeout with window of 0, send 1 byte.
* Otherwise, if window is small but nonzero * Otherwise, if window is small but nonzero
@ -124,7 +130,7 @@ again:
* to send then the probe will be the FIN * to send then the probe will be the FIN
* itself. * itself.
*/ */
if (off < (int)so->so_snd.sb_cc) if (off < so->so_snd.sb_cc)
flags &= ~TH_FIN; flags &= ~TH_FIN;
win = 1; win = 1;
} else { } else {
@ -152,7 +158,7 @@ again:
tp->snd_nxt = tp->snd_una; tp->snd_nxt = tp->snd_una;
} }
} }
if (len > tp->t_maxseg) { if (len > tp->t_maxseg) {
len = tp->t_maxseg; len = tp->t_maxseg;
sendalot = 1; sendalot = 1;
@ -194,17 +200,17 @@ again:
* window, then want to send a window update to peer. * window, then want to send a window update to peer.
*/ */
if (win > 0) { if (win > 0) {
/* /*
* "adv" is the amount we can increase the window, * "adv" is the amount we can increase the window,
* taking into account that we are limited by * taking into account that we are limited by
* TCP_MAXWIN << tp->rcv_scale. * TCP_MAXWIN << tp->rcv_scale.
*/ */
long adv = min(win, TCP_MAXWIN << tp->rcv_scale) - long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
(tp->rcv_adv - tp->rcv_nxt); (tp->rcv_adv - tp->rcv_nxt);
if (adv >= (long)(2 * tp->t_maxseg)) if (adv >= (long) (2 * tp->t_maxseg))
goto send; goto send;
if (2 * adv >= (long)so->so_rcv.sb_datalen) if (2 * adv >= (long) so->so_rcv.sb_datalen)
goto send; goto send;
} }
@ -257,8 +263,8 @@ again:
/* /*
* No reason to send a segment, just return. * No reason to send a segment, just return.
*/ */
tcpstat.tcps_didnuttin++; STAT(tcpstat.tcps_didnuttin++);
return (0); return (0);
send: send:
@ -296,9 +302,9 @@ send:
*/ */
} }
} }
/* /*
* Send a timestamp and echo-reply if this is a SYN and our side * Send a timestamp and echo-reply if this is a SYN and our side
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
* and our peer have sent timestamps in our SYN's. * and our peer have sent timestamps in our SYN's.
*/ */
@ -316,7 +322,7 @@ send:
* } * }
*/ */
hdrlen += optlen; hdrlen += optlen;
/* /*
* Adjust data length if insertion of options will * Adjust data length if insertion of options will
* bump the packet length beyond the t_maxseg length. * bump the packet length beyond the t_maxseg length.
@ -333,13 +339,13 @@ send:
*/ */
if (len) { if (len) {
if (tp->t_force && len == 1) if (tp->t_force && len == 1)
tcpstat.tcps_sndprobe++; STAT(tcpstat.tcps_sndprobe++);
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
tcpstat.tcps_sndrexmitpack++; STAT(tcpstat.tcps_sndrexmitpack++);
tcpstat.tcps_sndrexmitbyte += len; STAT(tcpstat.tcps_sndrexmitbyte += len);
} else { } else {
tcpstat.tcps_sndpack++; STAT(tcpstat.tcps_sndpack++);
tcpstat.tcps_sndbyte += len; STAT(tcpstat.tcps_sndbyte += len);
} }
m = m_get(); m = m_get();
@ -348,16 +354,16 @@ send:
error = 1; error = 1;
goto out; goto out;
} }
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen; m->m_len = hdrlen;
/* /*
* This will always succeed, since we make sure our mbufs * This will always succeed, since we make sure our mbufs
* are big enough to hold one MSS packet + header + ... etc. * are big enough to hold one MSS packet + header + ... etc.
*/ */
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */ /* if (len <= MHLEN - hdrlen - max_linkhdr) { */
sbcopy(&so->so_snd, off, len, mtod(m, caddr_t) + hdrlen); sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
m->m_len += len; m->m_len += len;
/* } else { /* } else {
@ -376,13 +382,13 @@ send:
flags |= TH_PUSH; flags |= TH_PUSH;
} else { } else {
if (tp->t_flags & TF_ACKNOW) if (tp->t_flags & TF_ACKNOW)
tcpstat.tcps_sndacks++; STAT(tcpstat.tcps_sndacks++);
else if (flags & (TH_SYN|TH_FIN|TH_RST)) else if (flags & (TH_SYN|TH_FIN|TH_RST))
tcpstat.tcps_sndctrl++; STAT(tcpstat.tcps_sndctrl++);
else if (SEQ_GT(tp->snd_up, tp->snd_una)) else if (SEQ_GT(tp->snd_up, tp->snd_una))
tcpstat.tcps_sndurg++; STAT(tcpstat.tcps_sndurg++);
else else
tcpstat.tcps_sndwinup++; STAT(tcpstat.tcps_sndwinup++);
m = m_get(); m = m_get();
if (m == NULL) { if (m == NULL) {
@ -390,12 +396,12 @@ send:
error = 1; error = 1;
goto out; goto out;
} }
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
m->m_len = hdrlen; m->m_len = hdrlen;
} }
ti = mtod(m, struct tcpiphdr *); ti = mtod(m, struct tcpiphdr *);
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr)); memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
/* /*
@ -403,7 +409,7 @@ send:
* window for use in delaying messages about window sizes. * window for use in delaying messages about window sizes.
* If resending a FIN, be sure not to use a new sequence number. * If resending a FIN, be sure not to use a new sequence number.
*/ */
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
tp->snd_nxt == tp->snd_max) tp->snd_nxt == tp->snd_max)
tp->snd_nxt--; tp->snd_nxt--;
/* /*
@ -433,17 +439,17 @@ send:
* Calculate receive window. Don't shrink window, * Calculate receive window. Don't shrink window,
* but avoid silly window syndrome. * but avoid silly window syndrome.
*/ */
if (win < (so->so_rcv.sb_datalen / 4) && win < tp->t_maxseg) if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
win = 0; win = 0;
if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale)) if (win > (long)TCP_MAXWIN << tp->rcv_scale)
win = (u_long) (TCP_MAXWIN << tp->rcv_scale); win = (long)TCP_MAXWIN << tp->rcv_scale;
if (win < (tp->rcv_adv - tp->rcv_nxt)) if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
win = (tp->rcv_adv - tp->rcv_nxt); win = (long)(tp->rcv_adv - tp->rcv_nxt);
ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale)); ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
if (SEQ_GT(tp->snd_up, tp->snd_una)) { if (SEQ_GT(tp->snd_up, tp->snd_una)) {
ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq))); ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
#ifdef notdef #ifdef notdef
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt)); ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
#endif #endif
@ -494,7 +500,7 @@ send:
if (tp->t_rtt == 0) { if (tp->t_rtt == 0) {
tp->t_rtt = 1; tp->t_rtt = 1;
tp->t_rtseq = startseq; tp->t_rtseq = startseq;
tcpstat.tcps_segstimed++; STAT(tcpstat.tcps_segstimed++);
} }
} }
@ -525,14 +531,14 @@ send:
* the template, but need a way to checksum without them. * the template, but need a way to checksum without them.
*/ */
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */ m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
{
((struct ip *)ti)->ip_len = (u_int16_t) m->m_len;
((struct ip *)ti)->ip_ttl = ip_defttl; {
((struct ip *)ti)->ip_len = m->m_len;
((struct ip *)ti)->ip_ttl = IPDEFTTL;
((struct ip *)ti)->ip_tos = so->so_iptos; ((struct ip *)ti)->ip_tos = so->so_iptos;
/* #if BSD >= 43 */ /* #if BSD >= 43 */
/* Don't do IP options... */ /* Don't do IP options... */
/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, /* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
@ -541,7 +547,7 @@ send:
error = ip_output(so, m); error = ip_output(so, m);
/* #else /* #else
* error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
* so->so_options & SO_DONTROUTE); * so->so_options & SO_DONTROUTE);
* #endif * #endif
*/ */
@ -561,7 +567,7 @@ out:
*/ */
return (error); return (error);
} }
tcpstat.tcps_sndtotal++; STAT(tcpstat.tcps_sndtotal++);
/* /*
* Data sent (as far as we can tell). * Data sent (as far as we can tell).
@ -579,7 +585,9 @@ out:
return (0); return (0);
} }
void tcp_setpersist(register struct tcpcb *tp) void
tcp_setpersist(tp)
register struct tcpcb *tp;
{ {
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -32,14 +36,14 @@
#include <slirp.h> #include <slirp.h>
int tcp_keepidle = TCPTV_KEEP_IDLE; #ifdef LOG_ENABLED
int tcp_keepintvl = TCPTV_KEEPINTVL;
int tcp_maxidle;
int so_options = DO_KEEPALIVE;
struct tcpstat tcpstat; /* tcp statistics */ struct tcpstat tcpstat; /* tcp statistics */
#endif
u_int32_t tcp_now; /* for RFC 1323 timestamps */ u_int32_t tcp_now; /* for RFC 1323 timestamps */
static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
/* /*
* Fast timeout routine for processing delayed acks * Fast timeout routine for processing delayed acks
*/ */
@ -50,7 +54,7 @@ tcp_fasttimo()
register struct tcpcb *tp; register struct tcpcb *tp;
DEBUG_CALL("tcp_fasttimo"); DEBUG_CALL("tcp_fasttimo");
so = tcb.so_next; so = tcb.so_next;
if (so) if (so)
for (; so != &tcb; so = so->so_next) for (; so != &tcb; so = so->so_next)
@ -58,7 +62,7 @@ tcp_fasttimo()
(tp->t_flags & TF_DELACK)) { (tp->t_flags & TF_DELACK)) {
tp->t_flags &= ~TF_DELACK; tp->t_flags &= ~TF_DELACK;
tp->t_flags |= TF_ACKNOW; tp->t_flags |= TF_ACKNOW;
tcpstat.tcps_delack++; STAT(tcpstat.tcps_delack++);
(void) tcp_output(tp); (void) tcp_output(tp);
} }
} }
@ -76,8 +80,7 @@ tcp_slowtimo()
register int i; register int i;
DEBUG_CALL("tcp_slowtimo"); DEBUG_CALL("tcp_slowtimo");
tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
/* /*
* Search through tcb's and update active timers. * Search through tcb's and update active timers.
*/ */
@ -123,21 +126,19 @@ tcp_canceltimers(tp)
tp->t_timer[i] = 0; tp->t_timer[i] = 0;
} }
int tcp_backoff[TCP_MAXRXTSHIFT + 1] = const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
/* /*
* TCP timer processing. * TCP timer processing.
*/ */
struct tcpcb * static struct tcpcb *
tcp_timers(tp, timer) tcp_timers(register struct tcpcb *tp, int timer)
register struct tcpcb *tp;
int timer;
{ {
register int rexmt; register int rexmt;
DEBUG_CALL("tcp_timers"); DEBUG_CALL("tcp_timers");
switch (timer) { switch (timer) {
/* /*
@ -148,8 +149,8 @@ tcp_timers(tp, timer)
*/ */
case TCPT_2MSL: case TCPT_2MSL:
if (tp->t_state != TCPS_TIME_WAIT && if (tp->t_state != TCPS_TIME_WAIT &&
tp->t_idle <= tcp_maxidle) tp->t_idle <= TCP_MAXIDLE)
tp->t_timer[TCPT_2MSL] = tcp_keepintvl; tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
else else
tp = tcp_close(tp); tp = tcp_close(tp);
break; break;
@ -160,12 +161,12 @@ tcp_timers(tp, timer)
* to a longer retransmit interval and retransmit one segment. * to a longer retransmit interval and retransmit one segment.
*/ */
case TCPT_REXMT: case TCPT_REXMT:
/* /*
* XXXXX If a packet has timed out, then remove all the queued * XXXXX If a packet has timed out, then remove all the queued
* packets for that session. * packets for that session.
*/ */
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
/* /*
* This is a hack to suit our terminal server here at the uni of canberra * This is a hack to suit our terminal server here at the uni of canberra
@ -174,33 +175,33 @@ tcp_timers(tp, timer)
* keep retransmitting it, it'll keep eating the zeroes, so we keep * keep retransmitting it, it'll keep eating the zeroes, so we keep
* retransmitting, and eventually the connection dies... * retransmitting, and eventually the connection dies...
* (this only happens on incoming data) * (this only happens on incoming data)
* *
* So, if we were gonna drop the connection from too many retransmits, * So, if we were gonna drop the connection from too many retransmits,
* don't... instead halve the t_maxseg, which might break up the NULLs and * don't... instead halve the t_maxseg, which might break up the NULLs and
* let them through * let them through
* *
* *sigh* * *sigh*
*/ */
tp->t_maxseg >>= 1; tp->t_maxseg >>= 1;
if (tp->t_maxseg < 32) { if (tp->t_maxseg < 32) {
/* /*
* We tried our best, now the connection must die! * We tried our best, now the connection must die!
*/ */
tp->t_rxtshift = TCP_MAXRXTSHIFT; tp->t_rxtshift = TCP_MAXRXTSHIFT;
tcpstat.tcps_timeoutdrop++; STAT(tcpstat.tcps_timeoutdrop++);
tp = tcp_drop(tp, tp->t_softerror); tp = tcp_drop(tp, tp->t_softerror);
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */ /* tp->t_softerror : ETIMEDOUT); */ /* XXX */
return (tp); /* XXX */ return (tp); /* XXX */
} }
/* /*
* Set rxtshift to 6, which is still at the maximum * Set rxtshift to 6, which is still at the maximum
* backoff time * backoff time
*/ */
tp->t_rxtshift = 6; tp->t_rxtshift = 6;
} }
tcpstat.tcps_rexmttimeo++; STAT(tcpstat.tcps_rexmttimeo++);
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
TCPT_RANGESET(tp->t_rxtcur, rexmt, TCPT_RANGESET(tp->t_rxtcur, rexmt,
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
@ -236,7 +237,7 @@ tcp_timers(tp, timer)
* size increase exponentially with time. If the * size increase exponentially with time. If the
* window is larger than the path can handle, this * window is larger than the path can handle, this
* exponential growth results in dropped packet(s) * exponential growth results in dropped packet(s)
* almost immediately. To get more time between * almost immediately. To get more time between
* drops but still "push" the network to take advantage * drops but still "push" the network to take advantage
* of improving conditions, we switch from exponential * of improving conditions, we switch from exponential
* to linear window opening at some threshold size. * to linear window opening at some threshold size.
@ -263,7 +264,7 @@ tcp_timers(tp, timer)
* Force a byte to be output, if possible. * Force a byte to be output, if possible.
*/ */
case TCPT_PERSIST: case TCPT_PERSIST:
tcpstat.tcps_persisttimeo++; STAT(tcpstat.tcps_persisttimeo++);
tcp_setpersist(tp); tcp_setpersist(tp);
tp->t_force = 1; tp->t_force = 1;
(void) tcp_output(tp); (void) tcp_output(tp);
@ -275,13 +276,13 @@ tcp_timers(tp, timer)
* or drop connection if idle for too long. * or drop connection if idle for too long.
*/ */
case TCPT_KEEP: case TCPT_KEEP:
tcpstat.tcps_keeptimeo++; STAT(tcpstat.tcps_keeptimeo++);
if (tp->t_state < TCPS_ESTABLISHED) if (tp->t_state < TCPS_ESTABLISHED)
goto dropit; goto dropit;
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */ /* if (tp->t_socket->so_options & SO_KEEPALIVE && */
if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
if (tp->t_idle >= tcp_keepidle + tcp_maxidle) if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
goto dropit; goto dropit;
/* /*
* Send a packet designed to force a response * Send a packet designed to force a response
@ -295,7 +296,7 @@ tcp_timers(tp, timer)
* by the protocol spec, this requires the * by the protocol spec, this requires the
* correspondent TCP to respond. * correspondent TCP to respond.
*/ */
tcpstat.tcps_keepprobe++; STAT(tcpstat.tcps_keepprobe++);
#ifdef TCP_COMPAT_42 #ifdef TCP_COMPAT_42
/* /*
* The keepalive packet must have nonzero length * The keepalive packet must have nonzero length
@ -307,13 +308,13 @@ tcp_timers(tp, timer)
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
tp->rcv_nxt, tp->snd_una - 1, 0); tp->rcv_nxt, tp->snd_una - 1, 0);
#endif #endif
tp->t_timer[TCPT_KEEP] = tcp_keepintvl; tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
} else } else
tp->t_timer[TCPT_KEEP] = tcp_keepidle; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
break; break;
dropit: dropit:
tcpstat.tcps_keepdrops++; STAT(tcpstat.tcps_keepdrops++);
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
break; break;
} }

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -122,17 +126,12 @@ char *tcptimers[] =
(tv) = (tvmax); \ (tv) = (tvmax); \
} }
extern int tcp_keepidle; /* time before keepalive probes begin */ extern const int tcp_backoff[];
extern int tcp_keepintvl; /* time between keepalive probes */
extern int tcp_maxidle; /* time to drop after starting probes */
extern int tcp_ttl; /* time to live for TCP segs */
extern int tcp_backoff[];
struct tcpcb; struct tcpcb;
void tcp_fasttimo(void); void tcp_fasttimo _P((void));
void tcp_slowtimo(void); void tcp_slowtimo _P((void));
void tcp_canceltimers(struct tcpcb *); void tcp_canceltimers _P((struct tcpcb *));
struct tcpcb * tcp_timers(register struct tcpcb *, int);
#endif #endif

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -181,6 +185,7 @@ typedef u_int32_t mbufp_32;
#endif #endif
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) #define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
#ifdef LOG_ENABLED
/* /*
* TCP statistics. * TCP statistics.
* Many of these should be kept per connection, * Many of these should be kept per connection,
@ -243,6 +248,8 @@ struct tcpstat {
}; };
extern struct tcpstat tcpstat; /* tcp statistics */ extern struct tcpstat tcpstat; /* tcp statistics */
#endif
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
#endif #endif

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *

View File

@ -1,8 +1,8 @@
/* /*
* tftp.c - a simple, read-only tftp server for qemu * tftp.c - a simple, read-only tftp server for qemu
* *
* Copyright (c) 2004 Magnus Damm <damm@opensource.se> * Copyright (c) 2004 Magnus Damm <damm@opensource.se>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
@ -26,15 +26,15 @@
struct tftp_session { struct tftp_session {
int in_use; int in_use;
char filename[TFTP_FILENAME_MAX]; unsigned char filename[TFTP_FILENAME_MAX];
struct in_addr client_ip; struct in_addr client_ip;
u_int16_t client_port; u_int16_t client_port;
int timestamp; int timestamp;
}; };
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
const char *tftp_prefix; const char *tftp_prefix;
@ -102,8 +102,15 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
{ {
int fd; int fd;
int bytes_read = 0; int bytes_read = 0;
char buffer[1024];
int n;
fd = open(spt->filename, O_RDONLY | O_BINARY); n = snprintf(buffer, sizeof(buffer), "%s/%s",
tftp_prefix, spt->filename);
if (n >= sizeof(buffer))
return -1;
fd = open(buffer, O_RDONLY | O_BINARY);
if (fd < 0) { if (fd < 0) {
return -1; return -1;
@ -120,13 +127,53 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
return bytes_read; return bytes_read;
} }
static int tftp_send_error(struct tftp_session *spt, static int tftp_send_oack(struct tftp_session *spt,
const char *key, uint32_t value,
struct tftp_t *recv_tp)
{
struct sockaddr_in saddr, daddr;
struct mbuf *m;
struct tftp_t *tp;
int n = 0;
m = m_get();
if (!m)
return -1;
memset(m->m_data, 0, m->m_size);
m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
tp->tp_op = htons(TFTP_OACK);
n += sprintf(tp->x.tp_buf + n, "%s", key) + 1;
n += sprintf(tp->x.tp_buf + n, "%u", value) + 1;
saddr.sin_addr = recv_tp->ip.ip_dst;
saddr.sin_port = recv_tp->udp.uh_dport;
daddr.sin_addr = spt->client_ip;
daddr.sin_port = spt->client_port;
m->m_len = sizeof(struct tftp_t) - 514 + n -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
return 0;
}
static int tftp_send_error(struct tftp_session *spt,
u_int16_t errorcode, const char *msg, u_int16_t errorcode, const char *msg,
struct tftp_t *recv_tp) struct tftp_t *recv_tp)
{ {
struct sockaddr_in saddr, daddr; struct sockaddr_in saddr, daddr;
struct mbuf *m; struct mbuf *m;
struct tftp_t *tp; struct tftp_t *tp;
int nobytes;
m = m_get(); m = m_get();
@ -136,14 +183,13 @@ static int tftp_send_error(struct tftp_session *spt,
memset(m->m_data, 0, m->m_size); memset(m->m_data, 0, m->m_size);
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data; tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr); m->m_data += sizeof(struct udpiphdr);
tp->tp_op = htons(TFTP_ERROR); tp->tp_op = htons(TFTP_ERROR);
tp->x.tp_error.tp_error_code = htons(errorcode); tp->x.tp_error.tp_error_code = htons(errorcode);
strncpy((char *)tp->x.tp_error.tp_msg, msg, sizeof(tp->x.tp_error.tp_msg)); strcpy(tp->x.tp_error.tp_msg, msg);
tp->x.tp_error.tp_msg[sizeof(tp->x.tp_error.tp_msg)-1] = 0;
saddr.sin_addr = recv_tp->ip.ip_dst; saddr.sin_addr = recv_tp->ip.ip_dst;
saddr.sin_port = recv_tp->udp.uh_dport; saddr.sin_port = recv_tp->udp.uh_dport;
@ -151,7 +197,9 @@ static int tftp_send_error(struct tftp_session *spt,
daddr.sin_addr = spt->client_ip; daddr.sin_addr = spt->client_ip;
daddr.sin_port = spt->client_port; daddr.sin_port = spt->client_port;
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - nobytes = 2;
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
sizeof(struct ip) - sizeof(struct udphdr); sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
@ -161,7 +209,7 @@ static int tftp_send_error(struct tftp_session *spt,
return 0; return 0;
} }
static int tftp_send_data(struct tftp_session *spt, static int tftp_send_data(struct tftp_session *spt,
u_int16_t block_nr, u_int16_t block_nr,
struct tftp_t *recv_tp) struct tftp_t *recv_tp)
{ {
@ -182,10 +230,10 @@ static int tftp_send_data(struct tftp_session *spt,
memset(m->m_data, 0, m->m_size); memset(m->m_data, 0, m->m_size);
m->m_data += if_maxlinkhdr; m->m_data += IF_MAXLINKHDR;
tp = (void *)m->m_data; tp = (void *)m->m_data;
m->m_data += sizeof(struct udpiphdr); m->m_data += sizeof(struct udpiphdr);
tp->tp_op = htons(TFTP_DATA); tp->tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons(block_nr); tp->x.tp_data.tp_block_nr = htons(block_nr);
@ -207,7 +255,7 @@ static int tftp_send_data(struct tftp_session *spt,
return -1; return -1;
} }
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
sizeof(struct ip) - sizeof(struct udphdr); sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
@ -237,7 +285,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
spt = &tftp_sessions[s]; spt = &tftp_sessions[s];
src = tp->x.tp_buf; src = tp->x.tp_buf;
dst = (u_int8_t *)spt->filename; dst = spt->filename;
n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
/* get name */ /* get name */
@ -249,28 +297,30 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
else { else {
return; return;
} }
if (src[k] == '\0') { if (src[k] == '\0') {
break; break;
} }
} }
if (k >= n) { if (k >= n) {
return; return;
} }
k++; k++;
/* check mode */ /* check mode */
if ((n - k) < 6) { if ((n - k) < 6) {
return; return;
} }
if (memcmp(&src[k], "octet\0", 6) != 0) { if (memcmp(&src[k], "octet\0", 6) != 0) {
tftp_send_error(spt, 4, "Unsupported transfer mode", tp); tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
return; return;
} }
k += 6; /* skipping octet */
/* do sanity checks on the filename */ /* do sanity checks on the filename */
if ((spt->filename[0] != '/') if ((spt->filename[0] != '/')
@ -282,19 +332,60 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
/* only allow exported prefixes */ /* only allow exported prefixes */
if (!tftp_prefix if (!tftp_prefix) {
|| (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) {
tftp_send_error(spt, 2, "Access violation", tp); tftp_send_error(spt, 2, "Access violation", tp);
return; return;
} }
/* check if the file exists */ /* check if the file exists */
if (tftp_read_data(spt, 0, (u_int8_t *)spt->filename, 0) < 0) { if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
tftp_send_error(spt, 1, "File not found", tp); tftp_send_error(spt, 1, "File not found", tp);
return; return;
} }
if (src[n - 1] != 0) {
tftp_send_error(spt, 2, "Access violation", tp);
return;
}
while (k < n) {
const char *key, *value;
key = src + k;
k += strlen(key) + 1;
if (k >= n) {
tftp_send_error(spt, 2, "Access violation", tp);
return;
}
value = src + k;
k += strlen(value) + 1;
if (strcmp(key, "tsize") == 0) {
int tsize = atoi(value);
struct stat stat_p;
if (tsize == 0 && tftp_prefix) {
char buffer[1024];
int len;
len = snprintf(buffer, sizeof(buffer), "%s/%s",
tftp_prefix, spt->filename);
if (stat(buffer, &stat_p) == 0)
tsize = stat_p.st_size;
else {
tftp_send_error(spt, 1, "File not found", tp);
return;
}
}
tftp_send_oack(spt, "tsize", tsize, tp);
}
}
tftp_send_data(spt, 1, tp); tftp_send_data(spt, 1, tp);
} }
@ -308,8 +399,8 @@ static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
return; return;
} }
if (tftp_send_data(&tftp_sessions[s], if (tftp_send_data(&tftp_sessions[s],
ntohs(tp->x.tp_data.tp_block_nr) + 1, ntohs(tp->x.tp_data.tp_block_nr) + 1,
tp) < 0) { tp) < 0) {
return; return;
} }

View File

@ -9,32 +9,25 @@
#define TFTP_DATA 3 #define TFTP_DATA 3
#define TFTP_ACK 4 #define TFTP_ACK 4
#define TFTP_ERROR 5 #define TFTP_ERROR 5
#define TFTP_OACK 6
#define TFTP_FILENAME_MAX 512 #define TFTP_FILENAME_MAX 512
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct tftp_t { struct tftp_t {
struct ip ip; struct ip ip;
struct udphdr udp; struct udphdr udp;
u_int16_t tp_op; u_int16_t tp_op;
union { union {
struct { struct {
u_int16_t tp_block_nr; u_int16_t tp_block_nr;
u_int8_t tp_buf[512]; u_int8_t tp_buf[512];
} tp_data; } tp_data;
struct { struct {
u_int16_t tp_error_code; u_int16_t tp_error_code;
u_int8_t tp_msg[512]; u_int8_t tp_msg[512];
} tp_error; } tp_error;
u_int8_t tp_buf[512 + 2]; u_int8_t tp_buf[512 + 2];
} x; } x;
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
void tftp_input(struct mbuf *m); void tftp_input(struct mbuf *m);

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -33,27 +37,31 @@
/* /*
* Changes and additions relating to SLiRP * Changes and additions relating to SLiRP
* Copyright (c) 1995 Danny Gasparovski. * Copyright (c) 1995 Danny Gasparovski.
* *
* Please read the file COPYRIGHT for the * Please read the file COPYRIGHT for the
* terms and conditions of the copyright. * terms and conditions of the copyright.
*/ */
#include <stdlib.h>
#include <slirp.h> #include <slirp.h>
#include "ip_icmp.h" #include "ip_icmp.h"
#ifdef LOG_ENABLED
struct udpstat udpstat; struct udpstat udpstat;
#endif
struct socket udb; struct socket udb;
static u_int8_t udp_tos(struct socket *so);
static void udp_emu(struct socket *so, struct mbuf *m);
/* /*
* UDP protocol implementation. * UDP protocol implementation.
* Per RFC 768, August, 1980. * Per RFC 768, August, 1980.
*/ */
#ifndef COMPAT_42 #ifndef COMPAT_42
int udpcksum = 1; #define UDPCKSUM 1
#else #else
int udpcksum = 0; /* XXX */ #define UDPCKSUM 0 /* XXX */
#endif #endif
struct socket *udp_last_so = &udb; struct socket *udp_last_so = &udb;
@ -63,8 +71,8 @@ udp_init()
{ {
udb.so_next = udb.so_prev = &udb; udb.so_next = udb.so_prev = &udb;
} }
/* m->m_data points at ip packet header /* m->m_data points at ip packet header
* m->m_len length ip packet * m->m_len length ip packet
* ip->ip_len length data (IPDU) * ip->ip_len length data (IPDU)
*/ */
void void
@ -76,14 +84,14 @@ udp_input(m, iphlen)
register struct udphdr *uh; register struct udphdr *uh;
/* struct mbuf *opts = 0;*/ /* struct mbuf *opts = 0;*/
int len; int len;
struct ip save_ip; struct ip save_ip;
struct socket *so; struct socket *so;
DEBUG_CALL("udp_input"); DEBUG_CALL("udp_input");
DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m = %lx", (long)m);
DEBUG_ARG("iphlen = %d", iphlen); DEBUG_ARG("iphlen = %d", iphlen);
udpstat.udps_ipackets++; STAT(udpstat.udps_ipackets++);
/* /*
* Strip IP options, if any; should skip this, * Strip IP options, if any; should skip this,
@ -110,34 +118,34 @@ udp_input(m, iphlen)
if (ip->ip_len != len) { if (ip->ip_len != len) {
if (len > ip->ip_len) { if (len > ip->ip_len) {
udpstat.udps_badlen++; STAT(udpstat.udps_badlen++);
goto bad; goto bad;
} }
m_adj(m, len - ip->ip_len); m_adj(m, len - ip->ip_len);
ip->ip_len = len; ip->ip_len = len;
} }
/* /*
* Save a copy of the IP header in case we want restore it * Save a copy of the IP header in case we want restore it
* for sending an ICMP error message in response. * for sending an ICMP error message in response.
*/ */
save_ip = *ip; save_ip = *ip;
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
/* /*
* Checksum extended UDP header and data. * Checksum extended UDP header and data.
*/ */
if (udpcksum && uh->uh_sum) { if (UDPCKSUM && uh->uh_sum) {
((struct ipovly *)ip)->ih_next = 0; ((struct ipovly *)ip)->ih_next = 0;
((struct ipovly *)ip)->ih_prev = 0; ((struct ipovly *)ip)->ih_prev = 0;
((struct ipovly *)ip)->ih_x1 = 0; ((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen; ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply /* keep uh_sum for ICMP reply
* uh->uh_sum = cksum(m, len + sizeof (struct ip)); * uh->uh_sum = cksum(m, len + sizeof (struct ip));
* if (uh->uh_sum) { * if (uh->uh_sum) {
*/ */
if(cksum(m, len + sizeof(struct ip))) { if(cksum(m, len + sizeof(struct ip))) {
udpstat.udps_badsum++; STAT(udpstat.udps_badsum++);
goto bad; goto bad;
} }
} }
@ -165,7 +173,7 @@ udp_input(m, iphlen)
if (so->so_lport != uh->uh_sport || if (so->so_lport != uh->uh_sport ||
so->so_laddr.s_addr != ip->ip_src.s_addr) { so->so_laddr.s_addr != ip->ip_src.s_addr) {
struct socket *tmp; struct socket *tmp;
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
if (tmp->so_lport == uh->uh_sport && if (tmp->so_lport == uh->uh_sport &&
tmp->so_laddr.s_addr == ip->ip_src.s_addr) { tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
@ -178,11 +186,11 @@ udp_input(m, iphlen)
if (tmp == &udb) { if (tmp == &udb) {
so = NULL; so = NULL;
} else { } else {
udpstat.udpps_pcbcachemiss++; STAT(udpstat.udpps_pcbcachemiss++);
udp_last_so = so; udp_last_so = so;
} }
} }
if (so == NULL) { if (so == NULL) {
/* /*
* If there's no socket for this packet, * If there's no socket for this packet,
@ -190,22 +198,22 @@ udp_input(m, iphlen)
*/ */
if ((so = socreate()) == NULL) goto bad; if ((so = socreate()) == NULL) goto bad;
if(udp_attach(so) == -1) { if(udp_attach(so) == -1) {
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
errno,strerror(errno))); errno,strerror(errno)));
sofree(so); sofree(so);
goto bad; goto bad;
} }
/* /*
* Setup fields * Setup fields
*/ */
/* udp_last_so = so; */ /* udp_last_so = so; */
so->so_laddr = ip->ip_src; so->so_laddr = ip->ip_src;
so->so_lport = uh->uh_sport; so->so_lport = uh->uh_sport;
if ((so->so_iptos = udp_tos(so)) == 0) if ((so->so_iptos = udp_tos(so)) == 0)
so->so_iptos = ip->ip_tos; so->so_iptos = ip->ip_tos;
/* /*
* XXXXX Here, check if it's in udpexec_list, * XXXXX Here, check if it's in udpexec_list,
* and if it is, do the fork_exec() etc. * and if it is, do the fork_exec() etc.
@ -230,7 +238,7 @@ udp_input(m, iphlen)
m->m_data -= iphlen; m->m_data -= iphlen;
*ip=save_ip; *ip=save_ip;
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
} }
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
@ -248,7 +256,7 @@ bad:
return; return;
} }
int udp_output2(struct socket *so, struct mbuf *m, int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr, struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos) int iptos)
{ {
@ -266,19 +274,16 @@ int udp_output2(struct socket *so, struct mbuf *m,
*/ */
m->m_data -= sizeof(struct udpiphdr); m->m_data -= sizeof(struct udpiphdr);
m->m_len += sizeof(struct udpiphdr); m->m_len += sizeof(struct udpiphdr);
/* /*
* Fill in mbuf with extended UDP header * Fill in mbuf with extended UDP header
* and addresses and length put into network format. * and addresses and length put into network format.
*/ */
ui = mtod(m, struct udpiphdr *); ui = mtod(m, struct udpiphdr *);
//ui->ui_next = ui->ui_prev = 0; ui->ui_next = ui->ui_prev = 0;
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ui->ui_x1 = 0; ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP; ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */ ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */ /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
ui->ui_src = saddr->sin_addr; ui->ui_src = saddr->sin_addr;
ui->ui_dst = daddr->sin_addr; ui->ui_dst = daddr->sin_addr;
@ -290,23 +295,23 @@ int udp_output2(struct socket *so, struct mbuf *m,
* Stuff checksum and output datagram. * Stuff checksum and output datagram.
*/ */
ui->ui_sum = 0; ui->ui_sum = 0;
if (udpcksum) { if (UDPCKSUM) {
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
ui->ui_sum = 0xffff; ui->ui_sum = 0xffff;
} }
((struct ip *)ui)->ip_len = (u_int16_t) m->m_len; ((struct ip *)ui)->ip_len = m->m_len;
((struct ip *)ui)->ip_ttl = ip_defttl; ((struct ip *)ui)->ip_ttl = IPDEFTTL;
((struct ip *)ui)->ip_tos = iptos; ((struct ip *)ui)->ip_tos = iptos;
udpstat.udps_opackets++; STAT(udpstat.udps_opackets++);
error = ip_output(so, m); error = ip_output(so, m);
return (error); return (error);
} }
int udp_output(struct socket *so, struct mbuf *m, int udp_output(struct socket *so, struct mbuf *m,
struct sockaddr_in *addr) struct sockaddr_in *addr)
{ {
@ -320,7 +325,7 @@ int udp_output(struct socket *so, struct mbuf *m,
} }
daddr.sin_addr = so->so_laddr; daddr.sin_addr = so->so_laddr;
daddr.sin_port = so->so_lport; daddr.sin_port = so->so_lport;
return udp_output2(so, m, &saddr, &daddr, so->so_iptos); return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
} }
@ -329,22 +334,25 @@ udp_attach(so)
struct socket *so; struct socket *so;
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
/* /*
* Here, we bind() the socket. Although not really needed * Here, we bind() the socket. Although not really needed
* (sendto() on an unbound socket will bind it), it's done * (sendto() on an unbound socket will bind it), it's done
* here so that emulation of ytalk etc. don't have to do it * here so that emulation of ytalk etc. don't have to do it
*/ */
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = 0; addr.sin_port = 0;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) { if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
int error = WSAGetLastError(); int lasterrno=errno;
closesocket(so->s); closesocket(so->s);
so->s=-1; so->s=-1;
WSASetLastError(error); #ifdef _WIN32
WSASetLastError(lasterrno);
#else
errno=lasterrno;
#endif
} else { } else {
/* success, insert in queue */ /* success, insert in queue */
so->so_expire = curtime + SO_EXPIRE; so->so_expire = curtime + SO_EXPIRE;
@ -364,7 +372,7 @@ udp_detach(so)
sofree(so); sofree(so);
} }
struct tos_t udptos[] = { static const struct tos_t udptos[] = {
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
{517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
{518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
@ -372,12 +380,11 @@ struct tos_t udptos[] = {
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
u_int8_t static u_int8_t
udp_tos(so) udp_tos(struct socket *so)
struct socket *so;
{ {
int i = 0; int i = 0;
while(udptos[i].tos) { while(udptos[i].tos) {
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
@ -386,7 +393,7 @@ udp_tos(so)
} }
i++; i++;
} }
return 0; return 0;
} }
@ -397,29 +404,27 @@ udp_tos(so)
/* /*
* Here, talk/ytalk/ntalk requests must be emulated * Here, talk/ytalk/ntalk requests must be emulated
*/ */
void static void
udp_emu(so, m) udp_emu(struct socket *so, struct mbuf *m)
struct socket *so;
struct mbuf *m;
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr); int addrlen = sizeof(addr);
#ifdef EMULATE_TALK #ifdef EMULATE_TALK
CTL_MSG_OLD *omsg; CTL_MSG_OLD *omsg;
CTL_MSG *nmsg; CTL_MSG *nmsg;
char buff[sizeof(CTL_MSG)]; char buff[sizeof(CTL_MSG)];
u_char type; u_char type;
struct talk_request { struct talk_request {
struct talk_request *next; struct talk_request *next;
struct socket *udp_so; struct socket *udp_so;
struct socket *tcp_so; struct socket *tcp_so;
} *req; } *req;
static struct talk_request *req_tbl = 0; static struct talk_request *req_tbl = 0;
#endif #endif
struct cu_header { struct cu_header {
uint16_t d_family; // destination family uint16_t d_family; // destination family
uint16_t d_port; // destination port uint16_t d_port; // destination port
@ -446,7 +451,7 @@ struct cu_header {
*/ */
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return; return;
#define IS_OLD (so->so_emu == EMU_TALK) #define IS_OLD (so->so_emu == EMU_TALK)
#define COPY_MSG(dest, src) { dest->type = src->type; \ #define COPY_MSG(dest, src) { dest->type = src->type; \
@ -469,7 +474,7 @@ struct cu_header {
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
} else { /* new talk */ } else { /* new talk */
omsg = (CTL_MSG_OLD *) buff; omsg = (CTL_MSG_OLD *) buff;
nmsg = mtod(m, CTL_MSG *); nmsg = mtod(m, CTL_MSG *);
type = nmsg->type; type = nmsg->type;
@ -477,10 +482,10 @@ struct cu_header {
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
} }
if (type == LOOK_UP) if (type == LOOK_UP)
return; /* for LOOK_UP this is enough */ return; /* for LOOK_UP this is enough */
if (IS_OLD) { /* make a copy of the message */ if (IS_OLD) { /* make a copy of the message */
COPY_MSG(nmsg, omsg); COPY_MSG(nmsg, omsg);
nmsg->vers = 1; nmsg->vers = 1;
@ -499,75 +504,75 @@ struct cu_header {
* ports, 517 and 518. This is why we have two copies * ports, 517 and 518. This is why we have two copies
* of the message, one in old talk and one in new talk * of the message, one in old talk and one in new talk
* format. * format.
*/ */
if (type == ANNOUNCE) { if (type == ANNOUNCE) {
int s; int s;
u_short temp_port; u_short temp_port;
for(req = req_tbl; req; req = req->next) for(req = req_tbl; req; req = req->next)
if (so == req->udp_so) if (so == req->udp_so)
break; /* found it */ break; /* found it */
if (!req) { /* no entry for so, create new */ if (!req) { /* no entry for so, create new */
req = (struct talk_request *) req = (struct talk_request *)
malloc(sizeof(struct talk_request)); malloc(sizeof(struct talk_request));
req->udp_so = so; req->udp_so = so;
req->tcp_so = solisten(0, req->tcp_so = solisten(0,
OTOSIN(omsg, addr)->sin_addr.s_addr, OTOSIN(omsg, addr)->sin_addr.s_addr,
OTOSIN(omsg, addr)->sin_port, OTOSIN(omsg, addr)->sin_port,
SS_FACCEPTONCE); SS_FACCEPTONCE);
req->next = req_tbl; req->next = req_tbl;
req_tbl = req; req_tbl = req;
} }
/* replace port number in addr field */ /* replace port number in addr field */
addrlen = sizeof(addr); addrlen = sizeof(addr);
getsockname(req->tcp_so->s, getsockname(req->tcp_so->s,
(struct sockaddr *) &addr, (struct sockaddr *) &addr,
&addrlen); &addrlen);
OTOSIN(omsg, addr)->sin_port = addr.sin_port; OTOSIN(omsg, addr)->sin_port = addr.sin_port;
OTOSIN(omsg, addr)->sin_addr = our_addr; OTOSIN(omsg, addr)->sin_addr = our_addr;
OTOSIN(nmsg, addr)->sin_port = addr.sin_port; OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
OTOSIN(nmsg, addr)->sin_addr = our_addr; OTOSIN(nmsg, addr)->sin_addr = our_addr;
/* send LEAVE_INVITEs */ /* send LEAVE_INVITEs */
temp_port = OTOSIN(omsg, ctl_addr)->sin_port; temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0;
omsg->type = nmsg->type = LEAVE_INVITE; omsg->type = nmsg->type = LEAVE_INVITE;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr; addr.sin_addr = our_addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(517); addr.sin_port = htons(517);
sendto(s, (char *)omsg, sizeof(*omsg), 0, sendto(s, (char *)omsg, sizeof(*omsg), 0,
(struct sockaddr *)&addr, sizeof(addr)); (struct sockaddr *)&addr, sizeof(addr));
addr.sin_port = htons(518); addr.sin_port = htons(518);
sendto(s, (char *)nmsg, sizeof(*nmsg), 0, sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *) &addr, sizeof(addr)); (struct sockaddr *) &addr, sizeof(addr));
closesocket(s) ; closesocket(s) ;
omsg->type = nmsg->type = ANNOUNCE; omsg->type = nmsg->type = ANNOUNCE;
OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
} }
/* /*
* If it is a DELETE message, we send a copy to the * If it is a DELETE message, we send a copy to the
* local daemons. Then we delete the entry corresponding * local daemons. Then we delete the entry corresponding
* to our socket from the request table. * to our socket from the request table.
*/ */
if (type == DELETE) { if (type == DELETE) {
struct talk_request *temp_req, *req_next; struct talk_request *temp_req, *req_next;
int s; int s;
u_short temp_port; u_short temp_port;
temp_port = OTOSIN(omsg, ctl_addr)->sin_port; temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(omsg, ctl_addr)->sin_port = 0;
OTOSIN(nmsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0;
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
addr.sin_addr = our_addr; addr.sin_addr = our_addr;
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
@ -578,7 +583,7 @@ struct cu_header {
sendto(s, (char *)nmsg, sizeof(*nmsg), 0, sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
(struct sockaddr *)&addr, sizeof(addr)); (struct sockaddr *)&addr, sizeof(addr));
closesocket(s); closesocket(s);
OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
@ -601,18 +606,18 @@ struct cu_header {
} }
} }
} }
return; return;
#endif #endif
case EMU_CUSEEME: case EMU_CUSEEME:
/* /*
* Cu-SeeMe emulation. * Cu-SeeMe emulation.
* Hopefully the packet is more that 16 bytes long. We don't * Hopefully the packet is more that 16 bytes long. We don't
* do any other tests, just replace the address and port * do any other tests, just replace the address and port
* fields. * fields.
*/ */
if (m->m_len >= sizeof (*cu_head)) { if (m->m_len >= sizeof (*cu_head)) {
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
return; return;
@ -620,7 +625,7 @@ struct cu_header {
cu_head->s_port = addr.sin_port; cu_head->s_port = addr.sin_port;
cu_head->so_addr = our_addr.s_addr; cu_head->so_addr = our_addr.s_addr;
} }
return; return;
} }
} }
@ -634,9 +639,8 @@ udp_listen(port, laddr, lport, flags)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
struct socket *so; struct socket *so;
socklen_t addrlen = sizeof(struct sockaddr_in); int addrlen = sizeof(struct sockaddr_in), opt = 1;
int opt = 1;
if ((so = socreate()) == NULL) { if ((so = socreate()) == NULL) {
free(so); free(so);
return NULL; return NULL;
@ -645,7 +649,6 @@ udp_listen(port, laddr, lport, flags)
so->so_expire = curtime + SO_EXPIRE; so->so_expire = curtime + SO_EXPIRE;
insque(so,&udb); insque(so,&udb);
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = port; addr.sin_port = port;
@ -656,20 +659,20 @@ udp_listen(port, laddr, lport, flags)
} }
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ /* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
getsockname(so->s,(struct sockaddr *)&addr,&addrlen); getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
so->so_fport = addr.sin_port; so->so_fport = addr.sin_port;
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
so->so_faddr = alias_addr; so->so_faddr = alias_addr;
else else
so->so_faddr = addr.sin_addr; so->so_faddr = addr.sin_addr;
so->so_lport = lport; so->so_lport = lport;
so->so_laddr.s_addr = laddr; so->so_laddr.s_addr = laddr;
if (flags != SS_FACCEPTONCE) if (flags != SS_FACCEPTONCE)
so->so_expire = 0; so->so_expire = 0;
so->so_state = SS_ISFCONNECTED; so->so_state = SS_ISFCONNECTED;
return so; return so;
} }

View File

@ -10,7 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
* *
@ -42,20 +46,12 @@ extern struct socket *udp_last_so;
* Udp protocol header. * Udp protocol header.
* Per RFC 768, September, 1981. * Per RFC 768, September, 1981.
*/ */
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(1)
#endif
struct udphdr { struct udphdr {
u_int16_t uh_sport; /* source port */ u_int16_t uh_sport; /* source port */
u_int16_t uh_dport; /* destination port */ u_int16_t uh_dport; /* destination port */
int16_t uh_ulen; /* udp length */ int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */ u_int16_t uh_sum; /* udp checksum */
} PACKED__; };
#ifdef PRAGMA_PACK_SUPPORTED
#pragma pack(PACK_RESET)
#endif
/* /*
* UDP kernel structures and variables. * UDP kernel structures and variables.
@ -76,6 +72,7 @@ struct udpiphdr {
#define ui_ulen ui_u.uh_ulen #define ui_ulen ui_u.uh_ulen
#define ui_sum ui_u.uh_sum #define ui_sum ui_u.uh_sum
#ifdef LOG_ENABLED
struct udpstat { struct udpstat {
/* input statistics: */ /* input statistics: */
u_long udps_ipackets; /* total input packets */ u_long udps_ipackets; /* total input packets */
@ -89,6 +86,7 @@ struct udpstat {
/* output statistics: */ /* output statistics: */
u_long udps_opackets; /* total output packets */ u_long udps_opackets; /* total output packets */
}; };
#endif
/* /*
* Names for UDP sysctl objects * Names for UDP sysctl objects
@ -96,19 +94,20 @@ struct udpstat {
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
#define UDPCTL_MAXID 2 #define UDPCTL_MAXID 2
#ifdef LOG_ENABLED
extern struct udpstat udpstat; extern struct udpstat udpstat;
#endif
extern struct socket udb; extern struct socket udb;
struct mbuf; struct mbuf;
void udp_init(void); void udp_init _P((void));
void udp_input(register struct mbuf *, int); void udp_input _P((register struct mbuf *, int));
int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *); int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
int udp_attach(struct socket *); int udp_attach _P((struct socket *));
void udp_detach(struct socket *); void udp_detach _P((struct socket *));
u_int8_t udp_tos(struct socket *); struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
void udp_emu(struct socket *, struct mbuf *); int udp_output2(struct socket *so, struct mbuf *m,
struct socket * udp_listen(u_int, u_int32_t, u_int, int);
int udp_output2(struct socket *so, struct mbuf *m,
struct sockaddr_in *saddr, struct sockaddr_in *daddr, struct sockaddr_in *saddr, struct sockaddr_in *daddr,
int iptos); int iptos);
#endif #endif