SLIRP 0.9.1
This commit is contained in:
parent
000ec0f135
commit
4682bb80a1
|
@ -16,7 +16,7 @@ The copyright terms and conditions:
|
|||
---BEGIN---
|
||||
|
||||
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
@ -25,6 +25,9 @@ The copyright terms and conditions:
|
|||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
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,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* QEMU BOOTP/DHCP server
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004 Fabrice Bellard
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
|
@ -38,8 +38,17 @@ typedef struct {
|
|||
|
||||
BOOTPClient bootp_clients[NB_ADDR];
|
||||
|
||||
const char *bootp_filename;
|
||||
|
||||
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)
|
||||
{
|
||||
BOOTPClient *bc;
|
||||
|
@ -80,7 +89,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
|||
const uint8_t *p, *p_end;
|
||||
int len, tag;
|
||||
|
||||
*pmsg_type = 0;
|
||||
*pmsg_type = 0;
|
||||
|
||||
p = buf;
|
||||
p_end = buf + size;
|
||||
|
@ -92,7 +101,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
|||
while (p < p_end) {
|
||||
tag = p[0];
|
||||
if (tag == RFC1533_PAD) {
|
||||
p++;
|
||||
p++;
|
||||
} else if (tag == RFC1533_END) {
|
||||
break;
|
||||
} else {
|
||||
|
@ -100,6 +109,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
|||
if (p >= p_end)
|
||||
break;
|
||||
len = *p++;
|
||||
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
|
||||
|
||||
switch(tag) {
|
||||
case RFC2132_MSG_TYPE:
|
||||
|
@ -126,19 +136,20 @@ static void bootp_reply(struct bootp_t *bp)
|
|||
|
||||
/* extract exact 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)
|
||||
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
|
||||
|
||||
if (dhcp_msg_type != DHCPDISCOVER &&
|
||||
|
||||
if (dhcp_msg_type != DHCPDISCOVER &&
|
||||
dhcp_msg_type != DHCPREQUEST)
|
||||
return;
|
||||
/* XXX: this is a hack to get the client mac address */
|
||||
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
|
||||
|
||||
|
||||
if ((m = m_get()) == NULL)
|
||||
return;
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
rbp = (struct bootp_t *)m->m_data;
|
||||
m->m_data += sizeof(struct udpiphdr);
|
||||
memset(rbp, 0, sizeof(struct bootp_t));
|
||||
|
@ -146,8 +157,10 @@ static void bootp_reply(struct bootp_t *bp)
|
|||
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||
new_addr:
|
||||
bc = get_new_addr(&daddr.sin_addr);
|
||||
if (!bc)
|
||||
if (!bc) {
|
||||
dprintf("no address left\n");
|
||||
return;
|
||||
}
|
||||
memcpy(bc->macaddr, client_ethaddr, 6);
|
||||
} else {
|
||||
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_port = htons(BOOTP_SERVER);
|
||||
|
||||
|
@ -185,7 +203,7 @@ static void bootp_reply(struct bootp_t *bp)
|
|||
*q++ = 1;
|
||||
*q++ = DHCPACK;
|
||||
}
|
||||
|
||||
|
||||
if (dhcp_msg_type == DHCPDISCOVER ||
|
||||
dhcp_msg_type == DHCPREQUEST) {
|
||||
*q++ = RFC2132_SRV_ID;
|
||||
|
@ -199,12 +217,12 @@ static void bootp_reply(struct bootp_t *bp)
|
|||
*q++ = 0xff;
|
||||
*q++ = 0xff;
|
||||
*q++ = 0x00;
|
||||
|
||||
|
||||
*q++ = RFC1533_GATEWAY;
|
||||
*q++ = 4;
|
||||
memcpy(q, &saddr.sin_addr, 4);
|
||||
q += 4;
|
||||
|
||||
|
||||
*q++ = RFC1533_DNS;
|
||||
*q++ = 4;
|
||||
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;
|
||||
|
||||
m->m_len = sizeof(struct bootp_t) -
|
||||
|
||||
m->m_len = sizeof(struct bootp_t) -
|
||||
sizeof(struct ip) - sizeof(struct udphdr);
|
||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||
}
|
||||
|
|
|
@ -90,10 +90,6 @@
|
|||
#define BOOTP_VENDOR_LEN 64
|
||||
#define DHCP_OPT_LEN 312
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct bootp_t {
|
||||
struct ip ip;
|
||||
struct udphdr udp;
|
||||
|
@ -112,10 +108,6 @@ struct bootp_t {
|
|||
uint8_t bp_sname[64];
|
||||
uint8_t bp_file[128];
|
||||
uint8_t bp_vend[DHCP_OPT_LEN];
|
||||
} PACKED__;
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(PACK_RESET)
|
||||
#endif
|
||||
};
|
||||
|
||||
void bootp_input(struct mbuf *m);
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -37,7 +41,7 @@
|
|||
*
|
||||
* This routine is very heavily used in the network
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
@ -59,13 +63,13 @@ int cksum(struct mbuf *m, int len)
|
|||
u_int16_t s[2];
|
||||
u_int32_t l;
|
||||
} l_util;
|
||||
|
||||
|
||||
if (m->m_len == 0)
|
||||
goto cont;
|
||||
w = mtod(m, u_int16_t *);
|
||||
|
||||
|
||||
mlen = m->m_len;
|
||||
|
||||
|
||||
if (len < mlen)
|
||||
mlen = len;
|
||||
len -= mlen;
|
||||
|
@ -103,7 +107,7 @@ int cksum(struct mbuf *m, int len)
|
|||
while ((mlen -= 2) >= 0) {
|
||||
sum += *w++;
|
||||
}
|
||||
|
||||
|
||||
if (byte_swapped) {
|
||||
REDUCE;
|
||||
sum <<= 8;
|
||||
|
@ -113,11 +117,11 @@ int cksum(struct mbuf *m, int len)
|
|||
sum += s_util.s;
|
||||
mlen = 0;
|
||||
} else
|
||||
|
||||
|
||||
mlen = -1;
|
||||
} else if (mlen == -1)
|
||||
s_util.c[0] = *(u_int8_t *)w;
|
||||
|
||||
|
||||
cont:
|
||||
#ifdef DEBUG
|
||||
if (len) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -16,8 +16,11 @@ int dostats = 0;
|
|||
#endif
|
||||
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 */
|
||||
#ifndef CONFIG_QEMU
|
||||
extern struct termios slirp_tty_settings;
|
||||
extern int slirp_tty_restore;
|
||||
|
||||
|
@ -30,7 +33,7 @@ debug_init(file, dbg)
|
|||
/* Close the old debugging file */
|
||||
if (dfd)
|
||||
fclose(dfd);
|
||||
|
||||
|
||||
dfd = fopen(file,"w");
|
||||
if (dfd != NULL) {
|
||||
#if 0
|
||||
|
@ -56,7 +59,7 @@ dump_packet(dat, n)
|
|||
{
|
||||
u_char *pptr = (u_char *)dat;
|
||||
int j,k;
|
||||
|
||||
|
||||
n /= 16;
|
||||
n++;
|
||||
DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
|
||||
|
@ -68,28 +71,30 @@ dump_packet(dat, n)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
#if 0
|
||||
/*
|
||||
* Statistic routines
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* the link as well.
|
||||
*/
|
||||
|
||||
void
|
||||
static void
|
||||
ttystats(ttyp)
|
||||
struct ttys *ttyp;
|
||||
{
|
||||
struct slirp_ifstats *is = &ttyp->ifstats;
|
||||
char buff[512];
|
||||
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
if (if_comp & IF_COMPRESS)
|
||||
|
||||
if (IF_COMP & IF_COMPRESS)
|
||||
strcpy(buff, "on");
|
||||
else if (if_comp & IF_NOCOMPRESS)
|
||||
else if (IF_COMP & IF_NOCOMPRESS)
|
||||
strcpy(buff, "off");
|
||||
else
|
||||
strcpy(buff, "off (for now)");
|
||||
|
@ -117,20 +122,20 @@ ttystats(ttyp)
|
|||
lprint(" %6d bad input packets\r\n", is->in_mbad);
|
||||
}
|
||||
|
||||
void
|
||||
allttystats()
|
||||
static void
|
||||
allttystats(void)
|
||||
{
|
||||
struct ttys *ttyp;
|
||||
|
||||
|
||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||
ttystats(ttyp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ipstats()
|
||||
static void
|
||||
ipstats(void)
|
||||
{
|
||||
lprint(" \r\n");
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("IP stats:\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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
vjstats()
|
||||
#ifndef CONFIG_QEMU
|
||||
static void
|
||||
vjstats(void)
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
|
||||
lprint("VJ compression stats:\r\n");
|
||||
|
||||
|
||||
lprint(" %6d outbound packets (%d compressed)\r\n",
|
||||
comp_s.sls_packets, comp_s.sls_compressed);
|
||||
lprint(" %6d searches for connection stats (%d misses)\r\n",
|
||||
|
@ -170,13 +175,13 @@ vjstats()
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
tcpstats()
|
||||
static void
|
||||
tcpstats(void)
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
lprint("TCP stats:\r\n");
|
||||
|
||||
|
||||
lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
|
||||
lprint(" %6d data packets (%d bytes)\r\n",
|
||||
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
|
||||
|
@ -189,8 +194,8 @@ tcpstats()
|
|||
lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
|
||||
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 packets received\r\n", tcpstat.tcps_rcvtotal);
|
||||
|
||||
lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
|
||||
lprint(" %6d acks (for %d bytes)\r\n",
|
||||
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
|
||||
lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
|
||||
|
@ -199,7 +204,7 @@ tcpstats()
|
|||
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
|
||||
lprint(" %6d completely duplicate packets (%d bytes)\r\n",
|
||||
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
|
||||
|
||||
|
||||
lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
|
||||
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
|
||||
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 header offset fields\r\n",
|
||||
tcpstat.tcps_rcvbadoff);
|
||||
|
||||
|
||||
lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
|
||||
lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
|
||||
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 data packet header predictions\n", tcpstat.tcps_preddat);
|
||||
lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
|
||||
|
||||
|
||||
|
||||
|
||||
/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
|
||||
/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
udpstats()
|
||||
static void
|
||||
udpstats(void)
|
||||
{
|
||||
lprint(" \r\n");
|
||||
|
||||
|
@ -252,8 +257,8 @@ udpstats()
|
|||
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
|
||||
}
|
||||
|
||||
void
|
||||
icmpstats()
|
||||
static void
|
||||
icmpstats(void)
|
||||
{
|
||||
lprint(" \r\n");
|
||||
lprint("ICMP stats:\r\n");
|
||||
|
@ -265,23 +270,23 @@ icmpstats()
|
|||
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
|
||||
}
|
||||
|
||||
void
|
||||
mbufstats()
|
||||
static void
|
||||
mbufstats(void)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int i;
|
||||
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
|
||||
lprint("Mbuf stats:\r\n");
|
||||
|
||||
lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
|
||||
|
||||
|
||||
i = 0;
|
||||
for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
|
||||
i++;
|
||||
lprint(" %6d mbufs on free list\r\n", i);
|
||||
|
||||
|
||||
i = 0;
|
||||
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
|
||||
i++;
|
||||
|
@ -289,59 +294,55 @@ mbufstats()
|
|||
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
|
||||
}
|
||||
|
||||
void
|
||||
sockstats()
|
||||
static void
|
||||
sockstats(void)
|
||||
{
|
||||
char addr[INET_ADDRSTRLEN];
|
||||
char buff[256];
|
||||
int n;
|
||||
struct socket *so;
|
||||
|
||||
lprint(" \r\n");
|
||||
|
||||
|
||||
lprint(
|
||||
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n");
|
||||
|
||||
|
||||
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");
|
||||
while (n < 17)
|
||||
buff[n++] = ' ';
|
||||
buff[17] = 0;
|
||||
lprint("%s %3d %15s %5d ",
|
||||
buff, so->s,
|
||||
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)),
|
||||
ntohs(so->so_lport));
|
||||
inet_ntoa(so->so_laddr), ntohs(so->so_lport));
|
||||
lprint("%15s %5d %5d %5d\r\n",
|
||||
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)),
|
||||
ntohs(so->so_fport),
|
||||
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
|
||||
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
||||
}
|
||||
|
||||
|
||||
for (so = udb.so_next; so != &udb; so = so->so_next) {
|
||||
|
||||
|
||||
n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
|
||||
while (n < 17)
|
||||
buff[n++] = ' ';
|
||||
buff[17] = 0;
|
||||
lprint("%s %3d %15s %5d ",
|
||||
buff, so->s,
|
||||
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)),
|
||||
ntohs(so->so_lport));
|
||||
inet_ntoa(so->so_laddr), ntohs(so->so_lport));
|
||||
lprint("%15s %5d %5d %5d\r\n",
|
||||
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)),
|
||||
ntohs(so->so_fport),
|
||||
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
|
||||
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifndef CONFIG_QEMU
|
||||
void
|
||||
slirp_exit(exit_status)
|
||||
int exit_status;
|
||||
{
|
||||
struct ttys *ttyp;
|
||||
|
||||
|
||||
DEBUG_CALL("slirp_exit");
|
||||
DEBUG_ARG("exit_status = %d", exit_status);
|
||||
|
||||
|
@ -350,7 +351,7 @@ slirp_exit(exit_status)
|
|||
if (!dfd)
|
||||
debug_init("slirp_stats", 0xf);
|
||||
lprint_arg = (char **)&dfd;
|
||||
|
||||
|
||||
ipstats();
|
||||
tcpstats();
|
||||
udpstats();
|
||||
|
@ -360,20 +361,35 @@ slirp_exit(exit_status)
|
|||
allttystats();
|
||||
vjstats();
|
||||
}
|
||||
|
||||
|
||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||
tty_detached(ttyp, 1);
|
||||
|
||||
|
||||
if (slirp_forked) {
|
||||
/* Menendez time */
|
||||
if (kill(getppid(), SIGQUIT) < 0)
|
||||
lprint("Couldn't kill parent process %ld!\n",
|
||||
(long) getppid());
|
||||
}
|
||||
|
||||
|
||||
/* Restore the terminal if we gotta */
|
||||
if(slirp_tty_restore)
|
||||
tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
|
||||
exit(exit_status);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
slirp_stats(void)
|
||||
{
|
||||
#ifdef LOG_ENABLED
|
||||
ipstats();
|
||||
tcpstats();
|
||||
udpstats();
|
||||
icmpstats();
|
||||
mbufstats();
|
||||
sockstats();
|
||||
#else
|
||||
lprint("SLIRP statistics code not compiled.\n");
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -36,15 +36,5 @@ extern int slirp_debug;
|
|||
|
||||
#endif
|
||||
|
||||
void debug_init(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);
|
||||
void debug_init _P((char *, int));
|
||||
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -60,6 +64,8 @@ struct icmpstat {
|
|||
{ "stats", CTLTYPE_STRUCT }, \
|
||||
}
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
extern struct icmpstat icmpstat;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,12 +7,7 @@
|
|||
|
||||
#include <slirp.h>
|
||||
|
||||
size_t if_mtu, if_mru;
|
||||
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) */
|
||||
int if_queued = 0; /* Number of packets queued so far */
|
||||
|
||||
struct mbuf if_fastq; /* fast queue (for interactive data) */
|
||||
struct mbuf if_batchq; /* queue for non-interactive data */
|
||||
|
@ -41,23 +36,6 @@ ifs_remque(ifm)
|
|||
void
|
||||
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_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
|
||||
// sl_compress_init(&comp_s);
|
||||
|
@ -77,12 +55,12 @@ writen(fd, bptr, n)
|
|||
{
|
||||
int ret;
|
||||
int total;
|
||||
|
||||
|
||||
/* This should succeed most of the time */
|
||||
ret = send(fd, bptr, n,0);
|
||||
if (ret == n || ret <= 0)
|
||||
return ret;
|
||||
|
||||
|
||||
/* Didn't write everything, go into the loop */
|
||||
total = ret;
|
||||
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),
|
||||
* and pass onto (*ttyp->if_input)
|
||||
*
|
||||
*
|
||||
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
|
||||
*/
|
||||
#define INBUFF_SIZE 2048 /* XXX */
|
||||
|
@ -107,17 +85,16 @@ if_input(ttyp)
|
|||
{
|
||||
u_char if_inbuff[INBUFF_SIZE];
|
||||
int if_n;
|
||||
|
||||
|
||||
DEBUG_CALL("if_input");
|
||||
DEBUG_ARG("ttyp = %lx", (long)ttyp);
|
||||
|
||||
|
||||
if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
|
||||
|
||||
|
||||
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
|
||||
|
||||
|
||||
if (if_n <= 0) {
|
||||
int error = WSAGetLastError();
|
||||
if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) {
|
||||
if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
|
||||
if (ttyp->up)
|
||||
link_up--;
|
||||
tty_detached(ttyp, 0);
|
||||
|
@ -139,19 +116,19 @@ if_input(ttyp)
|
|||
}
|
||||
}
|
||||
ttyp->ones = ttyp->zeros = 0;
|
||||
|
||||
|
||||
(*ttyp->if_input)(ttyp, if_inbuff, if_n);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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
|
||||
* of mbufs, each list belonging to one "session" (socket). This
|
||||
* way, we can output packets fairly by sending one packet from each
|
||||
* 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"
|
||||
* 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,
|
||||
|
@ -164,11 +141,11 @@ if_output(so, ifm)
|
|||
{
|
||||
struct mbuf *ifq;
|
||||
int on_fastq = 1;
|
||||
|
||||
|
||||
DEBUG_CALL("if_output");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("ifm = %lx", (long)ifm);
|
||||
|
||||
|
||||
/*
|
||||
* First remove the mbuf from m_usedlist,
|
||||
* since we're gonna use m_next and m_prev ourselves
|
||||
|
@ -178,9 +155,9 @@ if_output(so, ifm)
|
|||
remque(ifm);
|
||||
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,
|
||||
* 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)
|
||||
|
@ -194,7 +171,7 @@ if_output(so, ifm)
|
|||
goto diddit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* No match, check which queue to put it on */
|
||||
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
|
||||
ifq = if_fastq.ifq_prev;
|
||||
|
@ -210,15 +187,15 @@ if_output(so, ifm)
|
|||
}
|
||||
} else
|
||||
ifq = if_batchq.ifq_prev;
|
||||
|
||||
|
||||
/* Create a new doubly linked list for this session */
|
||||
ifm->ifq_so = so;
|
||||
ifs_init(ifm);
|
||||
insque(ifm, ifq);
|
||||
|
||||
|
||||
diddit:
|
||||
++if_queued;
|
||||
|
||||
|
||||
if (so) {
|
||||
/* Update *_queued */
|
||||
so->so_queued++;
|
||||
|
@ -230,12 +207,12 @@ diddit:
|
|||
* have been sent over the link
|
||||
* (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)) {
|
||||
|
||||
|
||||
/* Remove from current queue... */
|
||||
remque(ifm->ifs_next);
|
||||
|
||||
|
||||
/* ...And insert in the new. That'll teach ya! */
|
||||
insque(ifm->ifs_next, &if_batchq);
|
||||
}
|
||||
|
@ -268,16 +245,16 @@ void
|
|||
if_start(void)
|
||||
{
|
||||
struct mbuf *ifm, *ifqt;
|
||||
|
||||
|
||||
DEBUG_CALL("if_start");
|
||||
|
||||
|
||||
if (if_queued == 0)
|
||||
return; /* Nothing to do */
|
||||
|
||||
|
||||
again:
|
||||
/* check if we can really output */
|
||||
if (!slirp_can_output())
|
||||
return;
|
||||
/* check if we can really output */
|
||||
if (!slirp_can_output())
|
||||
return;
|
||||
|
||||
/*
|
||||
* See which queue to get next packet from
|
||||
|
@ -291,7 +268,7 @@ if_start(void)
|
|||
ifm = next_m;
|
||||
else
|
||||
ifm = if_batchq.ifq_next;
|
||||
|
||||
|
||||
/* Set which packet to send on next iteration */
|
||||
next_m = ifm->ifq_next;
|
||||
}
|
||||
|
@ -299,24 +276,24 @@ if_start(void)
|
|||
ifqt = ifm->ifq_prev;
|
||||
remque(ifm);
|
||||
--if_queued;
|
||||
|
||||
|
||||
/* If there are more packets for this session, re-queue them */
|
||||
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
|
||||
insque(ifm->ifs_next, ifqt);
|
||||
ifs_remque(ifm);
|
||||
}
|
||||
|
||||
|
||||
/* Update so_queued */
|
||||
if (ifm->ifq_so) {
|
||||
if (--ifm->ifq_so->so_queued == 0)
|
||||
/* If there's no more queued, reset nqueued */
|
||||
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)
|
||||
goto again;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -13,15 +13,26 @@
|
|||
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
||||
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
||||
|
||||
/* Needed for FreeBSD */
|
||||
#undef if_mtu
|
||||
extern size_t if_mtu;
|
||||
extern size_t if_mru; /* MTU and MRU */
|
||||
extern int if_comp; /* Flags for compression */
|
||||
extern int if_maxlinkhdr;
|
||||
#define IF_MTU 1500
|
||||
#define IF_MRU 1500
|
||||
#define IF_COMP IF_AUTOCOMP /* Flags for compression */
|
||||
|
||||
#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
|
||||
#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_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_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))
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
/* Interface statistics */
|
||||
struct slirp_ifstats {
|
||||
u_int out_pkts; /* Output packets */
|
||||
|
@ -39,12 +51,13 @@ struct slirp_ifstats {
|
|||
u_int in_bytes; /* Input bytes */
|
||||
u_int in_errpkts; /* Input Error Packets */
|
||||
u_int in_errbytes; /* Input Error Bytes */
|
||||
|
||||
|
||||
u_int bytes_saved; /* Number of bytes that compression "saved" */
|
||||
/* ie: number of bytes that didn't need to be sent over the link
|
||||
* because of compression */
|
||||
|
||||
|
||||
u_int in_mbad; /* Bad incoming packets */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct ip {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_char ip_v:4, /* version */
|
||||
u_int ip_v:4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
u_char ip_hl:4, /* header length */
|
||||
u_int ip_hl:4, /* header length */
|
||||
ip_v:4; /* version */
|
||||
#endif
|
||||
u_int8_t ip_tos; /* type of service */
|
||||
|
@ -95,11 +95,7 @@ struct ip {
|
|||
u_int8_t ip_p; /* protocol */
|
||||
u_int16_t ip_sum; /* checksum */
|
||||
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 */
|
||||
|
||||
|
@ -143,19 +139,15 @@ struct ip {
|
|||
/*
|
||||
* Time stamp option structure.
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct ip_timestamp {
|
||||
u_int8_t ipt_code; /* IPOPT_TS */
|
||||
u_int8_t ipt_len; /* size of structure (variable) */
|
||||
u_int8_t ipt_ptr; /* index of current entry */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_char ipt_oflw:4, /* overflow counter */
|
||||
u_int ipt_oflw:4, /* overflow counter */
|
||||
ipt_flg:4; /* flags, see below */
|
||||
#else
|
||||
u_char ipt_flg:4, /* flags, see below */
|
||||
u_int ipt_flg:4, /* flags, see below */
|
||||
ipt_oflw:4; /* overflow counter */
|
||||
#endif
|
||||
union ipt_timestamp {
|
||||
|
@ -165,11 +157,7 @@ struct ip_timestamp {
|
|||
n_long ipt_time;
|
||||
} ipt_ta[1];
|
||||
} ipt_timestamp;
|
||||
} PACKED__;
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(PACK_RESET)
|
||||
#endif
|
||||
};
|
||||
|
||||
/* flag bits for ipt_flg */
|
||||
#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).
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct ipovly {
|
||||
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
|
||||
u_int8_t ih_x1; /* (unused) */
|
||||
|
@ -227,11 +211,7 @@ struct ipovly {
|
|||
u_int16_t ih_len; /* protocol length */
|
||||
struct in_addr ih_src; /* source 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
|
||||
|
@ -257,10 +237,10 @@ struct ipq {
|
|||
*/
|
||||
struct ipasfrag {
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_char ip_v:4,
|
||||
u_int ip_v:4,
|
||||
ip_hl:4;
|
||||
#else
|
||||
u_char ip_hl:4,
|
||||
u_int ip_hl:4,
|
||||
ip_v:4;
|
||||
#endif
|
||||
/* BUG : u_int changed to u_int8_t.
|
||||
|
@ -292,6 +272,7 @@ struct ipoption {
|
|||
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
|
||||
};
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
/*
|
||||
* Structure attached to inpcb.ip_moptions and
|
||||
* passed to ip_output when IP multicast options are in use.
|
||||
|
@ -326,8 +307,9 @@ struct ipstat {
|
|||
};
|
||||
|
||||
extern struct ipstat ipstat;
|
||||
#endif
|
||||
|
||||
extern struct ipq ipq; /* ip reass. queue */
|
||||
extern u_int16_t ip_id; /* ip packet ctr, for ids */
|
||||
extern int ip_defttl; /* default IP ttl */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -33,14 +37,16 @@
|
|||
#include "slirp.h"
|
||||
#include "ip_icmp.h"
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
struct icmpstat icmpstat;
|
||||
#endif
|
||||
|
||||
/* The message sent when emulating PING */
|
||||
/* Be nice and tell them it's just a psuedo-ping packet */
|
||||
char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
|
||||
/* Be nice and tell them it's just a pseudo-ping packet */
|
||||
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 */
|
||||
static int icmp_flush[19] = {
|
||||
static const int icmp_flush[19] = {
|
||||
/* ECHO REPLY (0) */ 0,
|
||||
1,
|
||||
1,
|
||||
|
@ -59,7 +65,7 @@ static int icmp_flush[19] = {
|
|||
/* INFO (15) */ 0,
|
||||
/* INFO REPLY (16) */ 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 *);
|
||||
int icmplen=ip->ip_len;
|
||||
/* int code; */
|
||||
|
||||
|
||||
DEBUG_CALL("icmp_input");
|
||||
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
|
||||
* that its not corrupted and of at least minimum length.
|
||||
*/
|
||||
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
|
||||
icmpstat.icps_tooshort++;
|
||||
STAT(icmpstat.icps_tooshort++);
|
||||
freeit:
|
||||
m_freem(m);
|
||||
goto end_error;
|
||||
|
@ -96,12 +102,12 @@ icmp_input(m, hlen)
|
|||
m->m_data += hlen;
|
||||
icp = mtod(m, struct icmp *);
|
||||
if (cksum(m, icmplen)) {
|
||||
icmpstat.icps_checksum++;
|
||||
STAT(icmpstat.icps_checksum++);
|
||||
goto freeit;
|
||||
}
|
||||
m->m_len += hlen;
|
||||
m->m_data -= hlen;
|
||||
|
||||
|
||||
/* icmpstat.icps_inhist[icp->icmp_type]++; */
|
||||
/* code = icp->icmp_code; */
|
||||
|
||||
|
@ -117,7 +123,7 @@ icmp_input(m, hlen)
|
|||
struct sockaddr_in addr;
|
||||
if ((so = socreate()) == NULL) goto freeit;
|
||||
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)));
|
||||
sofree(so);
|
||||
m_free(m);
|
||||
|
@ -131,7 +137,7 @@ icmp_input(m, hlen)
|
|||
so->so_iptos = ip->ip_tos;
|
||||
so->so_type = IPPROTO_ICMP;
|
||||
so->so_state = SS_ISFCONNECTED;
|
||||
|
||||
|
||||
/* Send the packet */
|
||||
addr.sin_family = AF_INET;
|
||||
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) {
|
||||
DEBUG_MISC((dfd,"icmp_input udp sendto 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));
|
||||
udp_detach(so);
|
||||
}
|
||||
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
|
||||
|
@ -166,12 +172,12 @@ icmp_input(m, hlen)
|
|||
case ICMP_TSTAMP:
|
||||
case ICMP_MASKREQ:
|
||||
case ICMP_REDIRECT:
|
||||
icmpstat.icps_notsupp++;
|
||||
STAT(icmpstat.icps_notsupp++);
|
||||
m_freem(m);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
icmpstat.icps_badtype++;
|
||||
STAT(icmpstat.icps_badtype++);
|
||||
m_freem(m);
|
||||
} /* swith */
|
||||
|
||||
|
@ -195,18 +201,18 @@ end_error:
|
|||
* mbuf *msrc is used as a template, but is NOT m_free()'d.
|
||||
* It is reported as the bad ip packet. The header should
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define ICMP_MAXDATALEN (IP_MSS-28)
|
||||
void
|
||||
icmp_error(
|
||||
struct mbuf *msrc,
|
||||
u_char type,
|
||||
u_char code,
|
||||
int minsize,
|
||||
char *message)
|
||||
icmp_error(msrc, type, code, minsize, message)
|
||||
struct mbuf *msrc;
|
||||
u_char type;
|
||||
u_char code;
|
||||
int minsize;
|
||||
char *message;
|
||||
{
|
||||
unsigned hlen, shlen, s_ip_len;
|
||||
register struct ip *ip;
|
||||
|
@ -215,17 +221,17 @@ icmp_error(
|
|||
|
||||
DEBUG_CALL("icmp_error");
|
||||
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;
|
||||
|
||||
/* check msrc */
|
||||
if(!msrc) goto end_error;
|
||||
ip = mtod(msrc, struct ip *);
|
||||
#if DEBUG
|
||||
{ char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa));
|
||||
inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb));
|
||||
#if DEBUG
|
||||
{ char bufa[20], bufb[20];
|
||||
strcpy(bufa, inet_ntoa(ip->ip_src));
|
||||
strcpy(bufb, inet_ntoa(ip->ip_dst));
|
||||
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
|
||||
}
|
||||
#endif
|
||||
|
@ -244,7 +250,7 @@ icmp_error(
|
|||
|
||||
/* make a copy */
|
||||
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;
|
||||
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 */
|
||||
ip = mtod(m, struct ip *);
|
||||
hlen= sizeof(struct ip ); /* no options in reply */
|
||||
|
||||
|
||||
/* fill in icmp */
|
||||
m->m_data += hlen;
|
||||
m->m_data += hlen;
|
||||
m->m_len -= hlen;
|
||||
|
||||
icp = mtod(m, struct icmp *);
|
||||
|
@ -265,7 +271,7 @@ icmp_error(
|
|||
else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
|
||||
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 */
|
||||
|
||||
|
@ -299,8 +305,8 @@ icmp_error(
|
|||
|
||||
/* fill in ip */
|
||||
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_ttl = MAXTTL;
|
||||
|
@ -309,8 +315,8 @@ icmp_error(
|
|||
ip->ip_src = alias_addr;
|
||||
|
||||
(void ) ip_output((struct socket *)NULL, m);
|
||||
|
||||
icmpstat.icps_reflect++;
|
||||
|
||||
STAT(icmpstat.icps_reflect++);
|
||||
|
||||
end_error:
|
||||
return;
|
||||
|
@ -367,5 +373,5 @@ icmp_reflect(m)
|
|||
|
||||
(void ) ip_output((struct socket *)NULL, m);
|
||||
|
||||
icmpstat.icps_reflect++;
|
||||
STAT(icmpstat.icps_reflect++);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -43,10 +47,6 @@ typedef u_int32_t n_time;
|
|||
/*
|
||||
* Structure of an icmp header.
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct icmp {
|
||||
u_char icmp_type; /* type of message, see below */
|
||||
u_char icmp_code; /* type sub code */
|
||||
|
@ -92,11 +92,7 @@ struct icmp {
|
|||
#define icmp_ip icmp_dun.id_ip.idi_ip
|
||||
#define icmp_mask icmp_dun.id_mask
|
||||
#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.
|
||||
|
@ -161,8 +157,8 @@ struct icmp {
|
|||
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
|
||||
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
||||
|
||||
void icmp_input(struct mbuf *, int);
|
||||
void icmp_error(struct mbuf *, u_char, u_char, int, char *);
|
||||
void icmp_reflect(struct mbuf *);
|
||||
void icmp_input _P((struct mbuf *, int));
|
||||
void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
|
||||
void icmp_reflect _P((struct mbuf *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -33,7 +37,7 @@
|
|||
/*
|
||||
* Changes and additions relating to SLiRP are
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
@ -41,10 +45,19 @@
|
|||
#include <slirp.h>
|
||||
#include "ip_icmp.h"
|
||||
|
||||
int ip_defttl;
|
||||
#ifdef LOG_ENABLED
|
||||
struct ipstat ipstat;
|
||||
#endif
|
||||
|
||||
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.
|
||||
* All protocols not implemented in kernel go to raw IP protocol handler.
|
||||
|
@ -56,7 +69,6 @@ ip_init()
|
|||
ip_id = tt.tv_sec & 0xffff;
|
||||
udp_init();
|
||||
tcp_init();
|
||||
ip_defttl = IPDEFTTL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -68,38 +80,38 @@ ip_input(m)
|
|||
struct mbuf *m;
|
||||
{
|
||||
register struct ip *ip;
|
||||
u_int hlen;
|
||||
|
||||
int hlen;
|
||||
|
||||
DEBUG_CALL("ip_input");
|
||||
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)) {
|
||||
ipstat.ips_toosmall++;
|
||||
STAT(ipstat.ips_toosmall++);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ip = mtod(m, struct ip *);
|
||||
|
||||
|
||||
if (ip->ip_v != IPVERSION) {
|
||||
ipstat.ips_badvers++;
|
||||
STAT(ipstat.ips_badvers++);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
hlen = ip->ip_hl << 2;
|
||||
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;
|
||||
}
|
||||
|
||||
/* keep ip header intact for ICMP reply
|
||||
* ip->ip_sum = cksum(m, hlen);
|
||||
* if (ip->ip_sum) {
|
||||
* ip->ip_sum = cksum(m, hlen);
|
||||
* if (ip->ip_sum) {
|
||||
*/
|
||||
if(cksum(m,hlen)) {
|
||||
ipstat.ips_badsum++;
|
||||
STAT(ipstat.ips_badsum++);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -108,7 +120,7 @@ ip_input(m)
|
|||
*/
|
||||
NTOHS(ip->ip_len);
|
||||
if (ip->ip_len < hlen) {
|
||||
ipstat.ips_badlen++;
|
||||
STAT(ipstat.ips_badlen++);
|
||||
goto bad;
|
||||
}
|
||||
NTOHS(ip->ip_id);
|
||||
|
@ -121,7 +133,7 @@ ip_input(m)
|
|||
* Drop packet if shorter than we expect.
|
||||
*/
|
||||
if (m->m_len < ip->ip_len) {
|
||||
ipstat.ips_tooshort++;
|
||||
STAT(ipstat.ips_tooshort++);
|
||||
goto bad;
|
||||
}
|
||||
/* Should drop packet if mbuf too long? hmmm... */
|
||||
|
@ -150,7 +162,7 @@ ip_input(m)
|
|||
* (We could look in the reassembly queue to see
|
||||
* if the packet was previously fragmented,
|
||||
* but it's not worth the time; just let them time out.)
|
||||
*
|
||||
*
|
||||
* XXX This should fail, don't fragment yet
|
||||
*/
|
||||
if (ip->ip_off &~ IP_DF) {
|
||||
|
@ -177,7 +189,7 @@ ip_input(m)
|
|||
ip->ip_len -= hlen;
|
||||
if (ip->ip_off & IP_MF)
|
||||
((struct ipasfrag *)ip)->ipf_mff |= 1;
|
||||
else
|
||||
else
|
||||
((struct ipasfrag *)ip)->ipf_mff &= ~1;
|
||||
|
||||
ip->ip_off <<= 3;
|
||||
|
@ -188,11 +200,11 @@ ip_input(m)
|
|||
* attempt reassembly; if it succeeds, proceed.
|
||||
*/
|
||||
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
|
||||
ipstat.ips_fragments++;
|
||||
STAT(ipstat.ips_fragments++);
|
||||
ip = ip_reass((struct ipasfrag *)ip, fp);
|
||||
if (ip == 0)
|
||||
return;
|
||||
ipstat.ips_reassembled++;
|
||||
STAT(ipstat.ips_reassembled++);
|
||||
m = dtom(ip);
|
||||
} else
|
||||
if (fp)
|
||||
|
@ -204,7 +216,7 @@ ip_input(m)
|
|||
/*
|
||||
* Switch out to protocol's input routine.
|
||||
*/
|
||||
ipstat.ips_delivered++;
|
||||
STAT(ipstat.ips_delivered++);
|
||||
switch (ip->ip_p) {
|
||||
case IPPROTO_TCP:
|
||||
tcp_input(m, hlen, (struct socket *)NULL);
|
||||
|
@ -216,7 +228,7 @@ ip_input(m)
|
|||
icmp_input(m, hlen);
|
||||
break;
|
||||
default:
|
||||
ipstat.ips_noproto++;
|
||||
STAT(ipstat.ips_noproto++);
|
||||
m_free(m);
|
||||
}
|
||||
return;
|
||||
|
@ -231,16 +243,14 @@ bad:
|
|||
* reassembly of this datagram already exists, then it
|
||||
* is given as fp; otherwise have to make a chain.
|
||||
*/
|
||||
struct ip *
|
||||
ip_reass(ip, fp)
|
||||
register struct ipasfrag *ip;
|
||||
register struct ipq *fp;
|
||||
static struct ip *
|
||||
ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
|
||||
{
|
||||
register struct mbuf *m = dtom(ip);
|
||||
register struct ipasfrag *q;
|
||||
int hlen = ip->ip_hl << 2;
|
||||
int i, next;
|
||||
|
||||
|
||||
DEBUG_CALL("ip_reass");
|
||||
DEBUG_ARG("ip = %lx", (long)ip);
|
||||
DEBUG_ARG("fp = %lx", (long)fp);
|
||||
|
@ -271,7 +281,7 @@ ip_reass(ip, fp)
|
|||
q = (struct ipasfrag *)fp;
|
||||
goto insert;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a segment which begins after this one does.
|
||||
*/
|
||||
|
@ -365,7 +375,7 @@ insert:
|
|||
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->ip_len = next;
|
||||
|
@ -381,7 +391,7 @@ insert:
|
|||
return ((struct ip *)ip);
|
||||
|
||||
dropfrag:
|
||||
ipstat.ips_fragdropped++;
|
||||
STAT(ipstat.ips_fragdropped++);
|
||||
m_freem(m);
|
||||
return (0);
|
||||
}
|
||||
|
@ -390,9 +400,8 @@ dropfrag:
|
|||
* Free a fragment reassembly header and all
|
||||
* associated datagrams.
|
||||
*/
|
||||
void
|
||||
ip_freef(fp)
|
||||
struct ipq *fp;
|
||||
static void
|
||||
ip_freef(struct ipq *fp)
|
||||
{
|
||||
register struct ipasfrag *q, *p;
|
||||
|
||||
|
@ -410,9 +419,8 @@ ip_freef(fp)
|
|||
* Put an ip fragment on a reassembly chain.
|
||||
* Like insque, but pointers in middle of structure.
|
||||
*/
|
||||
void
|
||||
ip_enq(p, prev)
|
||||
register struct ipasfrag *p, *prev;
|
||||
static void
|
||||
ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
||||
{
|
||||
DEBUG_CALL("ip_enq");
|
||||
DEBUG_ARG("prev = %lx", (long)prev);
|
||||
|
@ -425,9 +433,8 @@ ip_enq(p, prev)
|
|||
/*
|
||||
* To ip_enq as remque is to insque.
|
||||
*/
|
||||
void
|
||||
ip_deq(p)
|
||||
register struct ipasfrag *p;
|
||||
static void
|
||||
ip_deq(register struct ipasfrag *p)
|
||||
{
|
||||
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
|
||||
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
|
||||
|
@ -442,9 +449,9 @@ void
|
|||
ip_slowtimo()
|
||||
{
|
||||
register struct ipq *fp;
|
||||
|
||||
|
||||
DEBUG_CALL("ip_slowtimo");
|
||||
|
||||
|
||||
fp = (struct ipq *) ipq.next;
|
||||
if (fp == 0)
|
||||
return;
|
||||
|
@ -453,7 +460,7 @@ ip_slowtimo()
|
|||
--fp->ipq_ttl;
|
||||
fp = (struct ipq *) fp->next;
|
||||
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
|
||||
ipstat.ips_fragtimeout++;
|
||||
STAT(ipstat.ips_fragtimeout++);
|
||||
ip_freef((struct ipq *) fp->prev);
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +667,7 @@ bad:
|
|||
/* Not yet */
|
||||
icmp_error(m, type, code, 0, 0);
|
||||
|
||||
ipstat.ips_badoptions++;
|
||||
STAT(ipstat.ips_badoptions++);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -688,6 +695,6 @@ ip_stripoptions(m, mopt)
|
|||
i = m->m_len - (sizeof (struct ip) + olen);
|
||||
memcpy(opts, opts + olen, (unsigned)i);
|
||||
m->m_len -= olen;
|
||||
|
||||
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -42,6 +46,10 @@
|
|||
|
||||
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
|
||||
* header (with len, off, ttl, proto, tos, src, dst).
|
||||
|
@ -55,14 +63,13 @@ ip_output(so, m0)
|
|||
{
|
||||
register struct ip *ip;
|
||||
register struct mbuf *m = m0;
|
||||
register u_int hlen = sizeof(struct ip);
|
||||
u_int len, off;
|
||||
int error = 0;
|
||||
register int hlen = sizeof(struct ip );
|
||||
int len, off, error = 0;
|
||||
|
||||
DEBUG_CALL("ip_output");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("m0 = %lx", (long)m0);
|
||||
|
||||
|
||||
/* We do no options */
|
||||
/* if (opt) {
|
||||
* m = ip_insertoptions(m, opt, &len);
|
||||
|
@ -77,23 +84,23 @@ ip_output(so, m0)
|
|||
ip->ip_off &= IP_DF;
|
||||
ip->ip_id = htons(ip_id++);
|
||||
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
|
||||
* the packet or packet fragments
|
||||
*/
|
||||
/* XXX Hmmm... */
|
||||
/* if (if_queued > if_thresh && towrite <= 0) {
|
||||
/* if (if_queued > IF_THRESH && towrite <= 0) {
|
||||
* error = ENOBUFS;
|
||||
* goto bad;
|
||||
* }
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 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_off = htons((u_int16_t)ip->ip_off);
|
||||
ip->ip_sum = 0;
|
||||
|
@ -109,11 +116,11 @@ ip_output(so, m0)
|
|||
*/
|
||||
if (ip->ip_off & IP_DF) {
|
||||
error = -1;
|
||||
ipstat.ips_cantfrag++;
|
||||
STAT(ipstat.ips_cantfrag++);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
|
||||
|
||||
len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
|
||||
if (len < 8) {
|
||||
error = -1;
|
||||
goto bad;
|
||||
|
@ -129,18 +136,18 @@ ip_output(so, m0)
|
|||
*/
|
||||
m0 = m;
|
||||
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;
|
||||
m = m_get();
|
||||
if (m == 0) {
|
||||
error = -1;
|
||||
ipstat.ips_odropped++;
|
||||
STAT(ipstat.ips_odropped++);
|
||||
goto sendorfree;
|
||||
}
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
mhip = mtod(m, struct ip *);
|
||||
*mhip = *ip;
|
||||
|
||||
|
||||
/* No options */
|
||||
/* if (hlen > sizeof (struct ip)) {
|
||||
* mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
||||
|
@ -153,28 +160,28 @@ ip_output(so, m0)
|
|||
mhip->ip_off |= IP_MF;
|
||||
if (off + len >= (u_int16_t)ip->ip_len)
|
||||
len = (u_int16_t)ip->ip_len - off;
|
||||
else
|
||||
else
|
||||
mhip->ip_off |= IP_MF;
|
||||
mhip->ip_len = htons((u_int16_t)(len + mhlen));
|
||||
|
||||
|
||||
if (m_copy(m, m0, off, len) < 0) {
|
||||
error = -1;
|
||||
goto sendorfree;
|
||||
}
|
||||
|
||||
|
||||
mhip->ip_off = htons((u_int16_t)mhip->ip_off);
|
||||
mhip->ip_sum = 0;
|
||||
mhip->ip_sum = cksum(m, mhlen);
|
||||
*mnext = m;
|
||||
mnext = &m->m_nextpkt;
|
||||
ipstat.ips_ofragments++;
|
||||
STAT(ipstat.ips_ofragments++);
|
||||
}
|
||||
/*
|
||||
* Update first fragment by trimming what's been copied out
|
||||
* and updating header, then send each fragment (in order).
|
||||
*/
|
||||
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_off = htons((u_int16_t)(ip->ip_off | IP_MF));
|
||||
ip->ip_sum = 0;
|
||||
|
@ -190,7 +197,7 @@ sendorfree:
|
|||
}
|
||||
|
||||
if (error == 0)
|
||||
ipstat.ips_fragmented++;
|
||||
STAT(ipstat.ips_fragmented++);
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
|
@ -1,39 +1,33 @@
|
|||
#ifndef _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
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int slirp_init(void);
|
||||
void slirp_init(void);
|
||||
|
||||
int slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||
void slirp_select_fill(int *pnfds,
|
||||
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: */
|
||||
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);
|
||||
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);
|
||||
|
||||
extern const char *tftp_prefix;
|
||||
extern char slirp_hostname[33];
|
||||
|
||||
void slirp_stats(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -42,7 +42,6 @@ extern char *username;
|
|||
extern char *socket_path;
|
||||
extern int towrite_max;
|
||||
extern int ppp_exit;
|
||||
extern int so_options;
|
||||
extern int tcp_keepintvl;
|
||||
extern uint8_t client_ethaddr[6];
|
||||
|
||||
|
|
|
@ -15,54 +15,49 @@
|
|||
* the flags
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <slirp.h>
|
||||
|
||||
struct mbuf *mbutl;
|
||||
char *mclrefcnt;
|
||||
int mbuf_alloced = 0;
|
||||
struct mbuf m_freelist, m_usedlist;
|
||||
int mbuf_thresh = 30;
|
||||
#define MBUF_THRESH 30
|
||||
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_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
|
||||
* malloc one
|
||||
*
|
||||
*
|
||||
* Because fragmentation can occur if we alloc new mbufs and
|
||||
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
|
||||
* which tells m_free to actually free() it
|
||||
*/
|
||||
struct mbuf *m_get()
|
||||
struct mbuf *
|
||||
m_get()
|
||||
{
|
||||
register struct mbuf *m;
|
||||
int flags = 0;
|
||||
|
||||
|
||||
DEBUG_CALL("m_get");
|
||||
|
||||
|
||||
if (m_freelist.m_next == &m_freelist) {
|
||||
m = (struct mbuf *)malloc(msize);
|
||||
m = (struct mbuf *)malloc(MSIZE);
|
||||
if (m == NULL) goto end_error;
|
||||
mbuf_alloced++;
|
||||
if (mbuf_alloced > mbuf_thresh)
|
||||
if (mbuf_alloced > MBUF_THRESH)
|
||||
flags = M_DOFREE;
|
||||
if (mbuf_alloced > mbuf_max)
|
||||
mbuf_max = mbuf_alloced;
|
||||
|
@ -70,13 +65,13 @@ struct mbuf *m_get()
|
|||
m = m_freelist.m_next;
|
||||
remque(m);
|
||||
}
|
||||
|
||||
|
||||
/* Insert it in the used list */
|
||||
insque(m,&m_usedlist);
|
||||
m->m_flags = (flags | M_USEDLIST);
|
||||
|
||||
|
||||
/* 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_len = 0;
|
||||
m->m_nextpkt = 0;
|
||||
|
@ -86,17 +81,19 @@ end_error:
|
|||
return m;
|
||||
}
|
||||
|
||||
void m_free(struct mbuf *m)
|
||||
void
|
||||
m_free(m)
|
||||
struct mbuf *m;
|
||||
{
|
||||
|
||||
|
||||
DEBUG_CALL("m_free");
|
||||
DEBUG_ARG("m = %lx", (long )m);
|
||||
|
||||
|
||||
if(m) {
|
||||
/* Remove from m_usedlist */
|
||||
if (m->m_flags & M_USEDLIST)
|
||||
remque(m);
|
||||
|
||||
|
||||
/* If it's M_EXT, free() it */
|
||||
if (m->m_flags & 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()
|
||||
* 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 (M_FREEROOM(m) < n->m_len)
|
||||
m_inc(m,m->m_size+MINCSIZE);
|
||||
|
||||
|
||||
memcpy(m->m_data+m->m_len, n->m_data, 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 */
|
||||
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. */
|
||||
if(m->m_size>size) return;
|
||||
|
||||
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);
|
||||
/* if (m->m_ext == NULL)
|
||||
* return (struct mbuf *)NULL;
|
||||
*/
|
||||
m->m_data = m->m_ext + datasize;
|
||||
*/
|
||||
m->m_data = m->m_ext + datasize;
|
||||
} else {
|
||||
char *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;
|
||||
*/
|
||||
memcpy(dat, m->m_dat, m->m_size);
|
||||
|
||||
|
||||
m->m_ext = dat;
|
||||
m->m_data = m->m_ext + datasize;
|
||||
m->m_flags |= M_EXT;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
return;
|
||||
|
@ -189,7 +194,9 @@ void m_adj(struct mbuf *m, int len)
|
|||
* Copy len bytes from m, starting off bytes into n
|
||||
*/
|
||||
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))
|
||||
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
|
||||
* Fortunately, it's not used often
|
||||
*/
|
||||
struct mbuf *dtom(void *dat)
|
||||
struct mbuf *
|
||||
dtom(dat)
|
||||
void *dat;
|
||||
{
|
||||
struct mbuf *m;
|
||||
|
||||
|
||||
DEBUG_CALL("dtom");
|
||||
DEBUG_ARG("dat = %lx", (long )dat);
|
||||
|
||||
|
@ -222,9 +231,9 @@ struct mbuf *dtom(void *dat)
|
|||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEBUG_ERROR((dfd, "dtom failed"));
|
||||
|
||||
|
||||
return (struct mbuf *)0;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -63,14 +67,14 @@ struct m_hdr {
|
|||
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
|
||||
int mh_flags; /* Misc flags */
|
||||
|
||||
size_t mh_size; /* Size of data */
|
||||
int mh_size; /* Size of data */
|
||||
struct socket *mh_so;
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
#define M_ROOM(m) ((m->m_flags & M_EXT)? \
|
||||
|
@ -122,7 +126,7 @@ struct mbuf {
|
|||
|
||||
struct mbstat {
|
||||
int mbs_alloced; /* Number of mbufs allocated */
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern struct mbstat mbstat;
|
||||
|
@ -130,14 +134,13 @@ extern int mbuf_alloced;
|
|||
extern struct mbuf m_freelist, m_usedlist;
|
||||
extern int mbuf_max;
|
||||
|
||||
void m_init(void);
|
||||
void msize_init(void);
|
||||
struct mbuf * m_get(void);
|
||||
void m_free(struct mbuf *);
|
||||
void m_cat(register struct mbuf *, register struct mbuf *);
|
||||
void m_inc(struct mbuf *, u_int);
|
||||
void m_adj(struct mbuf *, int);
|
||||
int m_copy(struct mbuf *, struct mbuf *, u_int, u_int);
|
||||
struct mbuf * dtom(void *);
|
||||
void m_init _P((void));
|
||||
struct mbuf * m_get _P((void));
|
||||
void m_free _P((struct mbuf *));
|
||||
void m_cat _P((register struct mbuf *, register struct mbuf *));
|
||||
void m_inc _P((struct mbuf *, int));
|
||||
void m_adj _P((struct mbuf *, int));
|
||||
int m_copy _P((struct mbuf *, struct mbuf *, int, int));
|
||||
struct mbuf * dtom _P((void *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 1995 Danny Gasparovski.
|
||||
*
|
||||
*
|
||||
* Please read the file COPYRIGHT for the
|
||||
* terms and conditions of the copyright.
|
||||
*/
|
||||
|
||||
#define WANT_SYS_IOCTL_H
|
||||
#include <stdlib.h>
|
||||
#include <slirp.h>
|
||||
|
||||
u_int curtime, time_fasttimo, last_slowtimo, detach_time;
|
||||
u_int detach_wait = 600000; /* 10 minutes */
|
||||
u_int curtime, time_fasttimo, last_slowtimo;
|
||||
|
||||
#if 0
|
||||
int x_port = -1;
|
||||
int x_display = 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) {
|
||||
lprint("X Redir: X not being redirected.\r\n");
|
||||
|
@ -29,7 +30,7 @@ int show_x(char *buff, struct socket *inso)
|
|||
if (x_display)
|
||||
lprint("X Redir: Redirecting to display %d\r\n", x_display);
|
||||
}
|
||||
|
||||
|
||||
return CFG_OK;
|
||||
}
|
||||
|
||||
|
@ -37,10 +38,15 @@ int show_x(char *buff, struct socket *inso)
|
|||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
if (x_port >= 0) {
|
||||
lprint("X Redir: X already being redirected.\r\n");
|
||||
show_x(0, 0);
|
||||
|
@ -61,33 +67,34 @@ void redir_x(u_int32_t inaddr, int start_port, int display, int screen)
|
|||
#endif
|
||||
|
||||
#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
|
||||
|
||||
/*
|
||||
* Get our IP address and put it in our_addr
|
||||
*/
|
||||
void getouraddr()
|
||||
void
|
||||
getouraddr()
|
||||
{
|
||||
char buff[256];
|
||||
struct hostent *he = NULL;
|
||||
|
||||
if (gethostname(buff, sizeof(buff)) == 0)
|
||||
{
|
||||
struct addrinfo hints = { 0 };
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
hints.ai_family = AF_INET;
|
||||
struct addrinfo* ai;
|
||||
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 (gethostname(buff,256) == 0)
|
||||
he = gethostbyname(buff);
|
||||
if (he)
|
||||
our_addr = *(struct in_addr *)he->h_addr;
|
||||
if (our_addr.s_addr == 0)
|
||||
our_addr.s_addr = loopback_addr.s_addr;
|
||||
}
|
||||
|
||||
#if SIZEOF_CHAR_P == 8
|
||||
|
@ -97,7 +104,10 @@ struct quehead_32 {
|
|||
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 *head = (struct quehead_32 *) b;
|
||||
|
@ -108,7 +118,9 @@ inline void insque_32(void *a, void *b)
|
|||
= (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;
|
||||
((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
||||
|
@ -123,7 +135,9 @@ struct quehead {
|
|||
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 *head = (struct quehead *) b;
|
||||
|
@ -134,7 +148,9 @@ void insque(void *a, void *b)
|
|||
= (struct quehead *)element;
|
||||
}
|
||||
|
||||
void remque(void *a)
|
||||
inline void
|
||||
remque(a)
|
||||
void *a;
|
||||
{
|
||||
register struct quehead *element = (struct quehead *) a;
|
||||
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
||||
|
@ -146,16 +162,22 @@ void remque(void *a)
|
|||
/* #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;
|
||||
|
||||
|
||||
/* First, check if the port is "bound" */
|
||||
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
||||
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
tmp_ptr = *ex_ptr;
|
||||
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
|
||||
(*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 char *sys_errlist[];
|
||||
|
||||
char *strerror(int error)
|
||||
char *
|
||||
strerror(error)
|
||||
int error;
|
||||
{
|
||||
if (error < sys_nerr)
|
||||
return sys_errlist[error];
|
||||
|
@ -188,7 +212,8 @@ char *strerror(int error)
|
|||
|
||||
#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 */
|
||||
return 0;
|
||||
|
@ -196,13 +221,16 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
|
|||
|
||||
#else
|
||||
|
||||
int slirp_openpty(int *amaster, int *aslave)
|
||||
#ifndef CONFIG_QEMU
|
||||
int
|
||||
slirp_openpty(amaster, aslave)
|
||||
int *amaster, *aslave;
|
||||
{
|
||||
register int master, slave;
|
||||
|
||||
#ifdef HAVE_GRANTPT
|
||||
char *ptr;
|
||||
|
||||
|
||||
if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
|
||||
grantpt(master) < 0 ||
|
||||
unlockpt(master) < 0 ||
|
||||
|
@ -210,7 +238,7 @@ int slirp_openpty(int *amaster, int *aslave)
|
|||
close(master);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if ((slave = open(ptr, O_RDWR)) < 0 ||
|
||||
ioctl(slave, I_PUSH, "ptem") < 0 ||
|
||||
ioctl(slave, I_PUSH, "ldterm") < 0 ||
|
||||
|
@ -219,16 +247,16 @@ int slirp_openpty(int *amaster, int *aslave)
|
|||
close(slave);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
*amaster = master;
|
||||
*aslave = slave;
|
||||
return 0;
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
static char line[] = "/dev/ptyXX";
|
||||
register const char *cp1, *cp2;
|
||||
|
||||
|
||||
for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
|
||||
line[8] = *cp1;
|
||||
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
|
||||
|
@ -258,6 +286,7 @@ int slirp_openpty(int *amaster, int *aslave)
|
|||
return (-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX This is ugly
|
||||
|
@ -265,53 +294,57 @@ int slirp_openpty(int *amaster, int *aslave)
|
|||
* process, which connects to this socket, after which we
|
||||
* exec the wanted program. If something (strange) happens,
|
||||
* the accept() call could block us forever.
|
||||
*
|
||||
*
|
||||
* do_pty = 0 Fork/exec inetd style
|
||||
* do_pty = 1 Fork/exec using slirp.telnetd
|
||||
* 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;
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int addrlen = sizeof(addr);
|
||||
int opt;
|
||||
int master;
|
||||
int master = -1;
|
||||
char *argv[256];
|
||||
#if 0
|
||||
char buff[256];
|
||||
#endif
|
||||
/* don't want to clobber the original */
|
||||
char *bptr;
|
||||
char *curarg;
|
||||
const char *curarg;
|
||||
int c, i, ret;
|
||||
|
||||
|
||||
DEBUG_CALL("fork_exec");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("ex = %lx", (long)ex);
|
||||
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
||||
|
||||
|
||||
if (do_pty == 2) {
|
||||
#if 0
|
||||
if (slirp_openpty(&master, &s) == -1) {
|
||||
lprint("Error: openpty failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
} else {
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
||||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
||||
listen(s, 1) < 0) {
|
||||
lprint("Error: inet socket: %s\n", strerror(errno));
|
||||
closesocket(s);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch(fork()) {
|
||||
case -1:
|
||||
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)
|
||||
close(master);
|
||||
return 0;
|
||||
|
||||
|
||||
case 0:
|
||||
/* Set the DISPLAY */
|
||||
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);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if (x_port >= 0) {
|
||||
#ifdef HAVE_SETENV
|
||||
|
@ -352,13 +385,13 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
|
|||
putenv(buff);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
dup2(s, 0);
|
||||
dup2(s, 1);
|
||||
dup2(s, 2);
|
||||
for (s = 3; s <= 255; s++)
|
||||
for (s = getdtablesize() - 1; s >= 3; s--)
|
||||
close(s);
|
||||
|
||||
|
||||
i = 0;
|
||||
bptr = strdup(ex); /* No need to free() this */
|
||||
if (do_pty == 1) {
|
||||
|
@ -376,21 +409,21 @@ int fork_exec(struct socket *so, char *ex, int do_pty)
|
|||
*bptr++ = (char)0;
|
||||
argv[i++] = strdup(curarg);
|
||||
} while (c);
|
||||
|
||||
|
||||
argv[i] = 0;
|
||||
execvp(argv[0], argv);
|
||||
|
||||
|
||||
/* Ooops, failed, let's tell the user why */
|
||||
{
|
||||
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));
|
||||
write(2, buff, strlen(buff)+1);
|
||||
}
|
||||
close(0); close(1); close(2); /* XXX */
|
||||
exit(1);
|
||||
|
||||
|
||||
default:
|
||||
if (do_pty == 2) {
|
||||
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));
|
||||
}
|
||||
fd_nonblock(so->s);
|
||||
|
||||
|
||||
/* Append the telnet options now */
|
||||
if (so->so_m != 0 && do_pty == 1) {
|
||||
sbappend(so, so->so_m);
|
||||
so->so_m = 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(const char *str)
|
||||
char *
|
||||
strdup(str)
|
||||
const char *str;
|
||||
{
|
||||
char *bptr;
|
||||
|
||||
|
||||
bptr = (char *)malloc(strlen(str)+1);
|
||||
strcpy(bptr, str);
|
||||
|
||||
|
||||
return bptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void snooze_hup(int num)
|
||||
void
|
||||
snooze_hup(num)
|
||||
int num;
|
||||
{
|
||||
int s, ret;
|
||||
#ifndef NO_UNIX_SOCKETS
|
||||
|
@ -446,7 +483,7 @@ void snooze_hup(int num)
|
|||
#endif
|
||||
struct sockaddr_in sock_in;
|
||||
char buff[256];
|
||||
|
||||
|
||||
ret = -1;
|
||||
if (slirp_socket_passwd) {
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -476,48 +513,51 @@ void snooze_hup(int num)
|
|||
#endif
|
||||
slirp_exit(0);
|
||||
}
|
||||
|
||||
|
||||
void snooze()
|
||||
|
||||
|
||||
void
|
||||
snooze()
|
||||
{
|
||||
sigset_t s;
|
||||
int i;
|
||||
|
||||
|
||||
/* Don't need our data anymore */
|
||||
/* XXX This makes SunOS barf */
|
||||
/* brk(0); */
|
||||
|
||||
|
||||
/* Close all fd's */
|
||||
for (i = 255; i >= 0; i--)
|
||||
close(i);
|
||||
|
||||
|
||||
signal(SIGQUIT, slirp_exit);
|
||||
signal(SIGHUP, snooze_hup);
|
||||
sigemptyset(&s);
|
||||
|
||||
|
||||
/* Wait for any signal */
|
||||
sigsuspend(&s);
|
||||
|
||||
|
||||
/* Just in case ... */
|
||||
exit(255);
|
||||
}
|
||||
|
||||
void relay(int s)
|
||||
void
|
||||
relay(s)
|
||||
int s;
|
||||
{
|
||||
char buf[8192];
|
||||
int n;
|
||||
fd_set readfds;
|
||||
struct ttys *ttyp;
|
||||
|
||||
|
||||
/* Don't need our data anymore */
|
||||
/* XXX This makes SunOS barf */
|
||||
/* brk(0); */
|
||||
|
||||
|
||||
signal(SIGQUIT, slirp_exit);
|
||||
signal(SIGHUP, slirp_exit);
|
||||
signal(SIGINT, slirp_exit);
|
||||
signal(SIGTERM, slirp_exit);
|
||||
|
||||
|
||||
/* Fudge to get term_raw and term_restore to work */
|
||||
if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
|
||||
lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
|
||||
|
@ -526,18 +566,18 @@ void relay(int s)
|
|||
ttyp->fd = 0;
|
||||
ttyp->flags |= TTY_CTTY;
|
||||
term_raw(ttyp);
|
||||
|
||||
|
||||
while (1) {
|
||||
FD_ZERO(&readfds);
|
||||
|
||||
|
||||
FD_SET(0, &readfds);
|
||||
FD_SET(s, &readfds);
|
||||
|
||||
|
||||
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
|
||||
|
||||
|
||||
if (n <= 0)
|
||||
slirp_exit(0);
|
||||
|
||||
|
||||
if (FD_ISSET(0, &readfds)) {
|
||||
n = read(0, buf, 8192);
|
||||
if (n <= 0)
|
||||
|
@ -546,7 +586,7 @@ void relay(int s)
|
|||
if (n <= 0)
|
||||
slirp_exit(0);
|
||||
}
|
||||
|
||||
|
||||
if (FD_ISSET(s, &readfds)) {
|
||||
n = read(s, buf, 8192);
|
||||
if (n <= 0)
|
||||
|
@ -556,20 +596,43 @@ void relay(int s)
|
|||
slirp_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Just in case.... */
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int (*lprint_print)(void *, const char *, va_list);
|
||||
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
|
||||
#ifdef CONFIG_QEMU
|
||||
extern void term_vprintf(const char *fmt, va_list ap);
|
||||
|
||||
void lprint(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_list args;
|
||||
|
||||
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 we're printing to an sbuf, make sure there's enough room */
|
||||
/* XXX +100? */
|
||||
|
@ -579,33 +642,33 @@ void lprint(const char *format, ...)
|
|||
int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
|
||||
int deltar = lprint_sb->sb_rptr - 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_datalen + TCP_SNDSPACE);
|
||||
|
||||
|
||||
/* Adjust all values */
|
||||
lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
|
||||
lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
|
||||
lprint_ptr = lprint_sb->sb_data + deltap;
|
||||
|
||||
|
||||
lprint_sb->sb_datalen += TCP_SNDSPACE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (lprint_print)
|
||||
lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
|
||||
|
||||
|
||||
/* Check if they want output to be logged to file as well */
|
||||
if (lfd) {
|
||||
/*
|
||||
/*
|
||||
* Remove \r's
|
||||
* otherwise you'll get ^M all over the file
|
||||
*/
|
||||
int len = strlen(format);
|
||||
char *bptr1, *bptr2;
|
||||
|
||||
|
||||
bptr1 = bptr2 = strdup(format);
|
||||
|
||||
|
||||
while (len--) {
|
||||
if (*bptr1 == '\r')
|
||||
memcpy(bptr1, bptr1+1, len+1);
|
||||
|
@ -618,7 +681,9 @@ void lprint(const char *format, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
void add_emu(char *buff)
|
||||
void
|
||||
add_emu(buff)
|
||||
char *buff;
|
||||
{
|
||||
u_int lport, fport;
|
||||
u_int8_t tos = 0, emu = 0;
|
||||
|
@ -626,12 +691,12 @@ void add_emu(char *buff)
|
|||
char *buff3 = buff4;
|
||||
struct emu_t *emup;
|
||||
struct socket *so;
|
||||
|
||||
|
||||
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
|
||||
lprint("Error: Bad arguments\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
|
||||
lport = 0;
|
||||
if (sscanf(buff1, "%d", &fport) != 1) {
|
||||
|
@ -639,7 +704,7 @@ void add_emu(char *buff)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
|
||||
buff3 = 0;
|
||||
if (sscanf(buff2, "%256s", buff1) != 1) {
|
||||
|
@ -647,7 +712,7 @@ void add_emu(char *buff)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (buff3) {
|
||||
if (strcmp(buff3, "lowdelay") == 0)
|
||||
tos = IPTOS_LOWDELAY;
|
||||
|
@ -658,7 +723,7 @@ void add_emu(char *buff)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (strcmp(buff1, "ftp") == 0)
|
||||
emu = EMU_FTP;
|
||||
else if (strcmp(buff1, "irc") == 0)
|
||||
|
@ -669,7 +734,7 @@ void add_emu(char *buff)
|
|||
lprint("Error: Unknown service\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* First, check that it isn't already emulated */
|
||||
for (emup = tcpemu; emup; emup = emup->next) {
|
||||
if (emup->lport == lport && emup->fport == fport) {
|
||||
|
@ -677,7 +742,7 @@ void add_emu(char *buff)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* link it */
|
||||
emup = (struct emu_t *)malloc(sizeof (struct emu_t));
|
||||
emup->lport = (u_int16_t)lport;
|
||||
|
@ -686,7 +751,7 @@ void add_emu(char *buff)
|
|||
emup->emu = emu;
|
||||
emup->next = tcpemu;
|
||||
tcpemu = emup;
|
||||
|
||||
|
||||
/* And finally, mark all current sessions, if any, as being emulated */
|
||||
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
|
||||
if ((lport && lport == ntohs(so->so_lport)) ||
|
||||
|
@ -697,9 +762,10 @@ void add_emu(char *buff)
|
|||
so->so_iptos = tos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BAD_SPRINTF
|
||||
|
||||
|
@ -710,33 +776,51 @@ void add_emu(char *buff)
|
|||
* 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);
|
||||
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;
|
||||
#ifdef __STDC__
|
||||
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);
|
||||
va_end(args);
|
||||
return strlen(string);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void u_sleep(int usec)
|
||||
void
|
||||
u_sleep(usec)
|
||||
int usec;
|
||||
{
|
||||
struct timeval t;
|
||||
fd_set fdset;
|
||||
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
|
||||
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = usec * 1000;
|
||||
|
||||
|
||||
select(0, &fdset, &fdset, &fdset, &t);
|
||||
}
|
||||
|
||||
|
@ -744,30 +828,34 @@ void u_sleep(int usec)
|
|||
* Set fd blocking and non-blocking
|
||||
*/
|
||||
|
||||
void fd_nonblock(int fd)
|
||||
void
|
||||
fd_nonblock(fd)
|
||||
int fd;
|
||||
{
|
||||
#if defined USE_FIONBIO && defined FIONBIO
|
||||
ioctlsockopt_t opt = 1;
|
||||
|
||||
#ifdef FIONBIO
|
||||
int opt = 1;
|
||||
|
||||
ioctlsocket(fd, FIONBIO, &opt);
|
||||
#else
|
||||
int opt;
|
||||
|
||||
|
||||
opt = fcntl(fd, F_GETFL, 0);
|
||||
opt |= O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, opt);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fd_block(int fd)
|
||||
void
|
||||
fd_block(fd)
|
||||
int fd;
|
||||
{
|
||||
#if defined USE_FIONBIO && defined FIONBIO
|
||||
ioctlsockopt_t opt = 0;
|
||||
|
||||
#ifdef FIONBIO
|
||||
int opt = 0;
|
||||
|
||||
ioctlsocket(fd, FIONBIO, &opt);
|
||||
#else
|
||||
int opt;
|
||||
|
||||
|
||||
opt = fcntl(fd, F_GETFL, 0);
|
||||
opt &= ~O_NONBLOCK;
|
||||
fcntl(fd, F_SETFL, opt);
|
||||
|
@ -779,17 +867,22 @@ void fd_block(int fd)
|
|||
/*
|
||||
* invoke RSH
|
||||
*/
|
||||
int rsh_exec(struct socket *so, struct socket *ns,
|
||||
char *user, char *host, char *args)
|
||||
int
|
||||
rsh_exec(so,ns, user, host, args)
|
||||
struct socket *so;
|
||||
struct socket *ns;
|
||||
char *user;
|
||||
char *host;
|
||||
char *args;
|
||||
{
|
||||
int fd[2];
|
||||
int fd0[2];
|
||||
int s;
|
||||
char buff[256];
|
||||
|
||||
|
||||
DEBUG_CALL("rsh_exec");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
|
||||
|
||||
if (pipe(fd)<0) {
|
||||
lprint("Error: pipe failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
|
@ -810,7 +903,7 @@ int rsh_exec(struct socket *so, struct socket *ns,
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
switch(fork()) {
|
||||
case -1:
|
||||
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[1]);
|
||||
return 0;
|
||||
|
||||
|
||||
case 0:
|
||||
close(fd[0]);
|
||||
close(fd0[0]);
|
||||
|
||||
|
||||
/* Set the DISPLAY */
|
||||
if (x_port >= 0) {
|
||||
#ifdef HAVE_SETENV
|
||||
|
@ -834,29 +927,29 @@ int rsh_exec(struct socket *so, struct socket *ns,
|
|||
putenv(buff);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
dup2(fd0[1], 0);
|
||||
dup2(fd0[1], 1);
|
||||
dup2(fd[1], 2);
|
||||
for (s = 3; s <= 255; s++)
|
||||
close(s);
|
||||
|
||||
|
||||
execlp("rsh","rsh","-l", user, host, args, NULL);
|
||||
|
||||
|
||||
/* 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));
|
||||
write(2, buff, strlen(buff)+1);
|
||||
close(0); close(1); close(2); /* XXX */
|
||||
exit(1);
|
||||
|
||||
|
||||
default:
|
||||
close(fd[1]);
|
||||
close(fd0[1]);
|
||||
ns->s=fd[0];
|
||||
so->s=fd0[0];
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -12,22 +12,22 @@ struct ex_list {
|
|||
int ex_pty; /* Do we want a pty? */
|
||||
int ex_addr; /* The last byte of the address */
|
||||
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;
|
||||
};
|
||||
|
||||
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 struct sbuf *lprint_sb;
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(const char *);
|
||||
char *strdup _P((const char *));
|
||||
#endif
|
||||
|
||||
void do_wait(int);
|
||||
void do_wait _P((int));
|
||||
|
||||
#define EMU_NONE 0x0
|
||||
|
||||
|
@ -63,25 +63,27 @@ struct emu_t {
|
|||
struct emu_t *next;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_QEMU
|
||||
extern struct emu_t *tcpemu;
|
||||
#endif
|
||||
|
||||
extern int x_port, x_server, x_display;
|
||||
|
||||
int show_x(char *, struct socket *);
|
||||
void redir_x(u_int32_t, int, int, int);
|
||||
void getouraddr(void);
|
||||
void slirp_insque(void *, void *);
|
||||
void slirp_remque(void *);
|
||||
int add_exec(struct ex_list **, int, char *, int, int);
|
||||
int slirp_openpty(int *, int *);
|
||||
int fork_exec(struct socket *, char *, int);
|
||||
void snooze_hup(int);
|
||||
void snooze(void);
|
||||
void relay(int);
|
||||
void add_emu(char *);
|
||||
void u_sleep(int);
|
||||
void fd_nonblock(int);
|
||||
void fd_block(int);
|
||||
int rsh_exec(struct socket *, struct socket *, char *, char *, char *);
|
||||
int show_x _P((char *, struct socket *));
|
||||
void redir_x _P((u_int32_t, int, int, int));
|
||||
void getouraddr _P((void));
|
||||
inline void slirp_insque _P((void *, void *));
|
||||
inline void slirp_remque _P((void *));
|
||||
int add_exec _P((struct ex_list **, int, char *, int, int));
|
||||
int slirp_openpty _P((int *, int *));
|
||||
int fork_exec(struct socket *so, const char *ex, int do_pty);
|
||||
void snooze_hup _P((int));
|
||||
void snooze _P((void));
|
||||
void relay _P((int));
|
||||
void add_emu _P((char *));
|
||||
void u_sleep _P((int));
|
||||
void fd_nonblock _P((int));
|
||||
void fd_block _P((int));
|
||||
int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,31 +1,37 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <slirp.h>
|
||||
|
||||
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
|
||||
|
||||
/* Done as a macro in socket.h */
|
||||
/* int
|
||||
* sbspace(struct sockbuff *sb)
|
||||
* sbspace(struct sockbuff *sb)
|
||||
* {
|
||||
* return SB_DATALEN - sb->sb_cc;
|
||||
* }
|
||||
*/
|
||||
|
||||
void sbfree(struct sbuf *sb)
|
||||
void
|
||||
sbfree(sb)
|
||||
struct sbuf *sb;
|
||||
{
|
||||
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
|
||||
* This should never succeed
|
||||
* This should never succeed
|
||||
*/
|
||||
if(num > sb->sb_cc)
|
||||
num = sb->sb_cc;
|
||||
|
@ -33,10 +39,13 @@ void sbdrop(struct sbuf *sb, u_int num)
|
|||
sb->sb_rptr += num;
|
||||
if(sb->sb_rptr >= sb->sb_data + 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) {
|
||||
/* 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
|
||||
* (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;
|
||||
|
||||
|
||||
DEBUG_CALL("sbappend");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
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 */
|
||||
if (m->m_len <= 0) {
|
||||
m_free(m);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If there is urgent data, call sosendoob
|
||||
* 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);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We only write if there's nothing in the buffer,
|
||||
* ottherwise it'll arrive out of order, and hence corrupt
|
||||
*/
|
||||
if (!so->so_rcv.sb_cc)
|
||||
ret = send(so->s, m->m_data, m->m_len, 0);
|
||||
|
||||
|
||||
if (ret <= 0) {
|
||||
/*
|
||||
/*
|
||||
* Nothing was written
|
||||
* It's possible that the socket has closed, but
|
||||
* 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
|
||||
* 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;
|
||||
|
||||
|
||||
len = m->m_len;
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
|
||||
from = sb->sb_rptr + off;
|
||||
if (from >= sb->sb_data + 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _SBUF_H_
|
||||
#define _SBUF_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
|
||||
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
||||
|
||||
|
@ -23,11 +21,10 @@ struct sbuf {
|
|||
char *sb_data; /* Actual data */
|
||||
};
|
||||
|
||||
void sbfree(struct sbuf *);
|
||||
void sbdrop(struct sbuf *, u_int);
|
||||
void sbreserve(struct sbuf *, size_t);
|
||||
void sbappend(struct socket *, struct mbuf *);
|
||||
void sbappendsb(struct sbuf *, struct mbuf *);
|
||||
void sbcopy(struct sbuf *, u_int, u_int, char *);
|
||||
void sbfree _P((struct sbuf *));
|
||||
void sbdrop _P((struct sbuf *, int));
|
||||
void sbreserve _P((struct sbuf *, int));
|
||||
void sbappend _P((struct socket *, struct mbuf *));
|
||||
void sbcopy _P((struct sbuf *, int, int, char *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@ struct in_addr special_addr;
|
|||
/* virtual address alias for host */
|
||||
struct in_addr alias_addr;
|
||||
|
||||
const uint8_t special_ethaddr[6] = {
|
||||
static const uint8_t special_ethaddr[6] = {
|
||||
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
|
||||
};
|
||||
|
||||
|
@ -38,10 +38,10 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
|||
DWORD ret;
|
||||
IP_ADDR_STRING *pIPAddr;
|
||||
struct in_addr tmp_addr;
|
||||
|
||||
|
||||
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
|
||||
BufLen = sizeof(FIXED_INFO);
|
||||
|
||||
|
||||
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
|
||||
if (FixedInfo) {
|
||||
GlobalFree(FixedInfo);
|
||||
|
@ -49,7 +49,7 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
|||
}
|
||||
FixedInfo = GlobalAlloc(GPTR, BufLen);
|
||||
}
|
||||
|
||||
|
||||
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
|
||||
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
|
||||
if (FixedInfo) {
|
||||
|
@ -58,14 +58,14 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
pIPAddr = &(FixedInfo->DnsServerList);
|
||||
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
|
||||
*pdns_addr = tmp_addr;
|
||||
#if 0
|
||||
printf( "DNS Servers:\n" );
|
||||
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
|
||||
|
||||
|
||||
pIPAddr = FixedInfo -> DnsServerList.Next;
|
||||
while ( pIPAddr ) {
|
||||
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)
|
||||
{
|
||||
char buff[512];
|
||||
char buff2[256+1];
|
||||
char buff2[256];
|
||||
FILE *f;
|
||||
int found = 0;
|
||||
struct in_addr tmp_addr;
|
||||
|
||||
|
||||
f = fopen("/etc/resolv.conf", "r");
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
lprint("IP address of your DNS(s): ");
|
||||
#endif
|
||||
while (fgets(buff, 512, f) != NULL) {
|
||||
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
|
||||
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 (!found)
|
||||
*pdns_addr = tmp_addr;
|
||||
#ifdef DEBUG
|
||||
else
|
||||
lprint(", ");
|
||||
#endif
|
||||
if (++found > 3) {
|
||||
#ifdef DEBUG
|
||||
lprint("(more)");
|
||||
#endif
|
||||
break;
|
||||
} else
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else
|
||||
lprint("%s", inet_ntoa(tmp_addr));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
@ -121,16 +130,16 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
|||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
void slirp_cleanup(void)
|
||||
static void slirp_cleanup(void)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
#endif
|
||||
|
||||
int slirp_init(void)
|
||||
void slirp_init(void)
|
||||
{
|
||||
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
{
|
||||
WSADATA Data;
|
||||
|
@ -150,13 +159,14 @@ int slirp_init(void)
|
|||
/* set default addresses */
|
||||
inet_aton("127.0.0.1", &loopback_addr);
|
||||
|
||||
if (get_dns_addr(&dns_addr) < 0)
|
||||
return -1;
|
||||
if (get_dns_addr(&dns_addr) < 0) {
|
||||
dns_addr = loopback_addr;
|
||||
fprintf (stderr, "Warning: No DNS servers found\n");
|
||||
}
|
||||
|
||||
inet_aton(CTL_SPECIAL, &special_addr);
|
||||
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
|
||||
getouraddr();
|
||||
return 0;
|
||||
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
|
||||
getouraddr();
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
gettimeofday(&tt, 0);
|
||||
|
||||
|
||||
curtime = (u_int)tt.tv_sec * (u_int)1000;
|
||||
curtime += (u_int)tt.tv_usec / (u_int)1000;
|
||||
|
||||
|
||||
if ((tt.tv_usec % 1000) >= 500)
|
||||
curtime++;
|
||||
}
|
||||
#endif
|
||||
|
||||
int slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||
void slirp_select_fill(int *pnfds,
|
||||
fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||
{
|
||||
struct socket *so, *so_next;
|
||||
struct timeval timeout;
|
||||
int nfds;
|
||||
int timeout, tmp_time;
|
||||
int tmp_time;
|
||||
|
||||
/* fail safe */
|
||||
global_readfds = NULL;
|
||||
global_writefds = NULL;
|
||||
global_xfds = NULL;
|
||||
|
||||
|
||||
nfds = *pnfds;
|
||||
/*
|
||||
* First, TCP sockets
|
||||
*/
|
||||
do_slowtimo = 0;
|
||||
if (link_up) {
|
||||
/*
|
||||
/*
|
||||
* *_slowtimo needs calling if there are IP fragments
|
||||
* in the fragment queue, or there are TCP connections active
|
||||
*/
|
||||
do_slowtimo = ((tcb.so_next != &tcb) ||
|
||||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
|
||||
|
||||
|
||||
for (so = tcb.so_next; so != &tcb; so = so_next) {
|
||||
so_next = so->so_next;
|
||||
|
||||
|
||||
/*
|
||||
* See if we need a tcp_fasttimo
|
||||
*/
|
||||
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,
|
||||
* newly socreated() sockets etc. Don't want to select these.
|
||||
*/
|
||||
if (so->so_state & SS_NOFDREF || so->s == -1)
|
||||
continue;
|
||||
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Set for reading sockets which are accepting
|
||||
*/
|
||||
|
@ -237,7 +248,7 @@ int slirp_select_fill(int *pnfds,
|
|||
UPD_NFDS(so->s);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set for writing sockets which are connecting
|
||||
*/
|
||||
|
@ -246,7 +257,7 @@ int slirp_select_fill(int *pnfds,
|
|||
UPD_NFDS(so->s);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set for writing if we are connected, can send more, and
|
||||
* we have something to send
|
||||
|
@ -255,7 +266,7 @@ int slirp_select_fill(int *pnfds,
|
|||
FD_SET(so->s, writefds);
|
||||
UPD_NFDS(so->s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set for reading (and urgent data) if we are connected, can
|
||||
* receive more, and we have room for it XXX /2 ?
|
||||
|
@ -266,13 +277,13 @@ int slirp_select_fill(int *pnfds,
|
|||
UPD_NFDS(so->s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* UDP sockets
|
||||
*/
|
||||
for (so = udb.so_next; so != &udb; so = so_next) {
|
||||
so_next = so->so_next;
|
||||
|
||||
|
||||
/*
|
||||
* See if it's timed out
|
||||
*/
|
||||
|
@ -283,7 +294,7 @@ int slirp_select_fill(int *pnfds,
|
|||
} else
|
||||
do_slowtimo = 1; /* Let socket expire */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When UDP packets are received from over the
|
||||
* 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
|
||||
*/
|
||||
|
||||
timeout = -1;
|
||||
|
||||
/*
|
||||
* If a slowtimo is needed, set timeout to 5ms from the last
|
||||
* slow timeout. If a fast timeout is needed, set timeout within
|
||||
* 2ms of when it was requested.
|
||||
* First, see the timeout needed by *timo
|
||||
*/
|
||||
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) {
|
||||
timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000;
|
||||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
else if (timeout > (SLOW_TIMO * 1000))
|
||||
timeout = SLOW_TIMO * 1000;
|
||||
|
||||
/* XXX + 10000 because some select()'s aren't that accurate */
|
||||
timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
|
||||
if (timeout.tv_usec < 0)
|
||||
timeout.tv_usec = 0;
|
||||
else if (timeout.tv_usec > 510000)
|
||||
timeout.tv_usec = 510000;
|
||||
|
||||
/* Can only fasttimo if we also slowtimo */
|
||||
if (time_fasttimo) {
|
||||
tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000;
|
||||
tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
|
||||
if (tmp_time < 0)
|
||||
tmp_time = 0;
|
||||
|
||||
tmp_time = 0;
|
||||
|
||||
/* Choose the smallest of the 2 */
|
||||
if (tmp_time < timeout)
|
||||
timeout = tmp_time;
|
||||
if (tmp_time < timeout.tv_usec)
|
||||
timeout.tv_usec = (u_int)tmp_time;
|
||||
}
|
||||
}
|
||||
*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;
|
||||
}
|
||||
*pnfds = nfds;
|
||||
}
|
||||
|
||||
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||
{
|
||||
struct socket *so, *so_next;
|
||||
int ret;
|
||||
struct socket *so, *so_next;
|
||||
int ret;
|
||||
|
||||
global_readfds = readfds;
|
||||
global_writefds = writefds;
|
||||
global_xfds = xfds;
|
||||
global_readfds = readfds;
|
||||
global_writefds = writefds;
|
||||
global_xfds = xfds;
|
||||
|
||||
/* Update time */
|
||||
updtime();
|
||||
|
@ -360,11 +364,11 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
|||
* See if anything has timed out
|
||||
*/
|
||||
if (link_up) {
|
||||
if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
|
||||
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
|
||||
tcp_fasttimo();
|
||||
time_fasttimo = 0;
|
||||
}
|
||||
if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
|
||||
if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
|
||||
ip_slowtimo();
|
||||
tcp_slowtimo();
|
||||
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)
|
||||
*/
|
||||
if (so->so_state & SS_NOFDREF || so->s == -1)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
if (FD_ISSET(so->s, xfds))
|
||||
sorecvoob(so);
|
||||
sorecvoob(so);
|
||||
/*
|
||||
* 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 */
|
||||
if (ret > 0)
|
||||
tcp_output(sototcpcb(so));
|
||||
tcp_output(sototcpcb(so));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check sockets for writing
|
||||
*/
|
||||
if (FD_ISSET(so->s, writefds)) {
|
||||
/*
|
||||
* Check for non-blocking, still-connecting sockets
|
||||
*/
|
||||
if (so->so_state & SS_ISFCONNECTING) {
|
||||
/* Connected */
|
||||
so->so_state &= ~SS_ISFCONNECTING;
|
||||
/*
|
||||
* Check for non-blocking, still-connecting sockets
|
||||
*/
|
||||
if (so->so_state & SS_ISFCONNECTING) {
|
||||
/* Connected */
|
||||
so->so_state &= ~SS_ISFCONNECTING;
|
||||
|
||||
ret = send(so->s, (char*)&ret, 0, 0);
|
||||
if (ret < 0) {
|
||||
/* XXXXX Must fix, zero bytes is a NOP */
|
||||
int error = WSAGetLastError();
|
||||
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||
continue;
|
||||
ret = send(so->s, &ret, 0, 0);
|
||||
if (ret < 0) {
|
||||
/* XXXXX Must fix, zero bytes is a NOP */
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINPROGRESS || errno == ENOTCONN)
|
||||
continue;
|
||||
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
}
|
||||
/* else so->so_state &= ~SS_ISFCONNECTING; */
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
}
|
||||
/* else so->so_state &= ~SS_ISFCONNECTING; */
|
||||
|
||||
/*
|
||||
* Continue tcp_input
|
||||
*/
|
||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
||||
/* continue; */
|
||||
}
|
||||
else
|
||||
ret = sowrite(so);
|
||||
/*
|
||||
* XXXXX If we wrote something (a lot), there
|
||||
* could be a need for a window update.
|
||||
* In the worst case, the remote will send
|
||||
* a window probe to get things going again
|
||||
*/
|
||||
/*
|
||||
* Continue tcp_input
|
||||
*/
|
||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
||||
/* continue; */
|
||||
} else
|
||||
ret = sowrite(so);
|
||||
/*
|
||||
* XXXXX If we wrote something (a lot), there
|
||||
* could be a need for a window update.
|
||||
* In the worst case, the remote will send
|
||||
* a window probe to get things going again
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Probe a still-connecting, non-blocking socket
|
||||
* to check if it's still alive
|
||||
*/
|
||||
*/
|
||||
#ifdef PROBE_CONN
|
||||
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) {
|
||||
/* XXX */
|
||||
int error = WSAGetLastError();
|
||||
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||
continue; /* Still connecting, continue */
|
||||
if (ret < 0) {
|
||||
/* XXX */
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINPROGRESS || errno == ENOTCONN)
|
||||
continue; /* Still connecting, continue */
|
||||
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
|
||||
/* tcp_input will take care of it */
|
||||
}
|
||||
else {
|
||||
ret = send(so->s, &ret, 0, 0);
|
||||
if (ret < 0) {
|
||||
/* XXX */
|
||||
int error = WSAGetLastError();
|
||||
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||
continue;
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
}
|
||||
else
|
||||
so->so_state &= ~SS_ISFCONNECTING;
|
||||
/* tcp_input will take care of it */
|
||||
} else {
|
||||
ret = send(so->s, &ret, 0,0);
|
||||
if (ret < 0) {
|
||||
/* XXX */
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
||||
errno == EINPROGRESS || errno == ENOTCONN)
|
||||
continue;
|
||||
/* else failed */
|
||||
so->so_state = SS_NOFDREF;
|
||||
} else
|
||||
so->so_state &= ~SS_ISFCONNECTING;
|
||||
|
||||
}
|
||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
||||
} /* SS_ISFCONNECTING */
|
||||
}
|
||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
|
||||
} /* SS_ISFCONNECTING */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
|
||||
sorecvfrom(so);
|
||||
}
|
||||
sorecvfrom(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can start outputting
|
||||
*/
|
||||
if (if_queued && link_up)
|
||||
if_start();
|
||||
if_start();
|
||||
|
||||
/* clear global file descriptor sets.
|
||||
* these reside on the stack in vl.c
|
||||
* so they're unusable if we're not in
|
||||
* slirp_select_fill or slirp_select_poll.
|
||||
*/
|
||||
global_readfds = NULL;
|
||||
global_writefds = NULL;
|
||||
global_xfds = NULL;
|
||||
global_readfds = NULL;
|
||||
global_writefds = NULL;
|
||||
global_xfds = NULL;
|
||||
}
|
||||
|
||||
#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_REPLY 2 /* ARP reply */
|
||||
|
||||
struct ethhdr
|
||||
struct ethhdr
|
||||
{
|
||||
unsigned char h_dest[ETH_ALEN]; /* destination eth 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) {
|
||||
case ARPOP_REQUEST:
|
||||
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;
|
||||
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
|
||||
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)
|
||||
return;
|
||||
|
||||
proto = (pkt[12] << 8) | pkt[13];
|
||||
|
||||
proto = ntohs(*(uint16_t *)(pkt + 12));
|
||||
switch(proto) {
|
||||
case ETH_P_ARP:
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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))
|
||||
return -1;
|
||||
} else {
|
||||
if (!solisten(htons(host_port), guest_addr.s_addr,
|
||||
if (!solisten(htons(host_port), guest_addr.s_addr,
|
||||
htons(guest_port), 0))
|
||||
return -1;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return add_exec(&exec_list, do_pty, (char *)args,
|
||||
return add_exec(&exec_list, do_pty, (char *)args,
|
||||
addr_low_byte, htons(guest_port));
|
||||
}
|
||||
|
|
|
@ -3,12 +3,21 @@
|
|||
|
||||
#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
|
||||
#include "version.h"
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "config-host.h"
|
||||
#include "slirp_config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -19,31 +28,20 @@ typedef uint16_t u_int16_t;
|
|||
typedef uint32_t u_int32_t;
|
||||
typedef uint64_t u_int64_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 <WS2tcpip.h>
|
||||
# include <sys/timeb.h>
|
||||
# include <iphlpapi.h>
|
||||
|
||||
# define USE_FIONBIO 1
|
||||
|
||||
/* Basilisk II Router defines those */
|
||||
# define udp_read_completion slirp_udp_read_completion
|
||||
# define write_udp slirp_write_udp
|
||||
# define init_udp slirp_init_udp
|
||||
# define final_udp slirp_final_udp
|
||||
# define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
# define EINPROGRESS WSAEINPROGRESS
|
||||
# define ENOTCONN WSAENOTCONN
|
||||
# define EHOSTUNREACH WSAEHOSTUNREACH
|
||||
# define ENETUNREACH WSAENETUNREACH
|
||||
# define ECONNREFUSED WSAECONNREFUSED
|
||||
#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 closesocket(s) close(s)
|
||||
# define O_BINARY 0
|
||||
|
@ -53,13 +51,8 @@ typedef int ioctlsockopt_t;
|
|||
#ifdef HAVE_SYS_BITYPES_H
|
||||
# include <sys/bitypes.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#ifdef NEED_TYPEDEFS
|
||||
typedef char int8_t;
|
||||
|
@ -90,11 +83,6 @@ typedef unsigned char u_int8_t;
|
|||
# endif
|
||||
#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
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
@ -129,6 +117,17 @@ typedef u_int32_t uint32;
|
|||
|
||||
#ifndef _WIN32
|
||||
#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 <arpa/inet.h>
|
||||
#endif
|
||||
|
@ -139,23 +138,20 @@ typedef u_int32_t uint32;
|
|||
|
||||
/* Systems lacking strdup() definition in <string.h>. */
|
||||
#if defined(ultrix)
|
||||
char *strdup(const char *);
|
||||
char *strdup _P((const char *));
|
||||
#endif
|
||||
|
||||
/* Systems lacking malloc() definition in <stdlib.h>. */
|
||||
#if defined(ultrix) || defined(hcx)
|
||||
void *malloc(size_t arg);
|
||||
void free(void *ptr);
|
||||
void *malloc _P((size_t arg));
|
||||
void free _P((void *ptr));
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifndef NO_UNIX_SOCKETS
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
@ -187,7 +183,11 @@ int inet_aton(const char *cp, struct in_addr *ia);
|
|||
#include <ppp/slirppp.h>
|
||||
#endif
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -202,20 +202,6 @@ int inet_aton(const char *cp, struct in_addr *ia);
|
|||
|
||||
#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 "tcp.h"
|
||||
#include "tcp_timer.h"
|
||||
|
@ -246,47 +232,45 @@ extern struct ttys *ttys_unit[MAX_INTERFACES];
|
|||
#endif
|
||||
|
||||
#ifndef FULL_BOLT
|
||||
void if_start(void);
|
||||
void if_start _P((void));
|
||||
#else
|
||||
void if_start(struct ttys *);
|
||||
void if_start _P((struct ttys *));
|
||||
#endif
|
||||
|
||||
#ifdef BAD_SPRINTF
|
||||
# define vsprintf vsprintf_len
|
||||
# define sprintf sprintf_len
|
||||
extern int vsprintf_len(char *, const char *, va_list);
|
||||
extern int sprintf_len(char *, const char *, ...);
|
||||
extern int vsprintf_len _P((char *, const char *, va_list));
|
||||
extern int sprintf_len _P((char *, const char *, ...));
|
||||
#endif
|
||||
|
||||
#ifdef DECLARE_SPRINTF
|
||||
# ifndef BAD_SPRINTF
|
||||
extern int vsprintf(char *, const char *, va_list);
|
||||
extern int vsprintf _P((char *, const char *, va_list));
|
||||
# endif
|
||||
extern int vfprintf(FILE *, const char *, va_list);
|
||||
extern int vfprintf _P((FILE *, const char *, va_list));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
extern char *strerror(int error);
|
||||
extern char *strerror _P((int error));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INDEX
|
||||
char *index(const char *, int);
|
||||
char *index _P((const char *, int));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GETHOSTID
|
||||
long gethostid(void);
|
||||
long gethostid _P((void));
|
||||
#endif
|
||||
|
||||
void lprint(const char *, ...);
|
||||
|
||||
extern int do_echo;
|
||||
void lprint _P((const char *, ...));
|
||||
|
||||
#if SIZEOF_CHAR_P == 4
|
||||
# define insque_32 insque
|
||||
# define remque_32 remque
|
||||
#else
|
||||
extern inline void insque_32(void *, void *);
|
||||
extern inline void remque_32(void *);
|
||||
inline void insque_32 _P((void *, void *));
|
||||
inline void remque_32 _P((void *));
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -295,51 +279,46 @@ extern int do_echo;
|
|||
|
||||
#define DEFAULT_BAUD 115200
|
||||
|
||||
#define SO_OPTIONS DO_KEEPALIVE
|
||||
#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
|
||||
|
||||
/* cksum.c */
|
||||
int cksum(struct mbuf *m, int len);
|
||||
|
||||
/* if.c */
|
||||
void if_init(void);
|
||||
void if_output(struct socket *, struct mbuf *);
|
||||
void if_init _P((void));
|
||||
void if_output _P((struct socket *, struct mbuf *));
|
||||
|
||||
/* ip_input.c */
|
||||
void ip_init(void);
|
||||
void ip_input(struct mbuf *);
|
||||
struct ip * ip_reass(register struct ipasfrag *, register struct ipq *);
|
||||
void ip_freef(struct ipq *);
|
||||
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 *);
|
||||
void ip_init _P((void));
|
||||
void ip_input _P((struct mbuf *));
|
||||
void ip_slowtimo _P((void));
|
||||
void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
|
||||
|
||||
/* ip_output.c */
|
||||
int ip_output(struct socket *, struct mbuf *);
|
||||
int ip_output _P((struct socket *, struct mbuf *));
|
||||
|
||||
/* tcp_input.c */
|
||||
int tcp_reass(register struct tcpcb *, register struct tcpiphdr *, struct mbuf *);
|
||||
void tcp_input(register struct mbuf *, int, struct socket *);
|
||||
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);
|
||||
void tcp_input _P((register struct mbuf *, int, struct socket *));
|
||||
int tcp_mss _P((register struct tcpcb *, u_int));
|
||||
|
||||
/* tcp_output.c */
|
||||
int tcp_output(register struct tcpcb *);
|
||||
void tcp_setpersist(register struct tcpcb *);
|
||||
int tcp_output _P((register struct tcpcb *));
|
||||
void tcp_setpersist _P((register struct tcpcb *));
|
||||
|
||||
/* tcp_subr.c */
|
||||
void tcp_init(void);
|
||||
void tcp_template(struct tcpcb *);
|
||||
void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int);
|
||||
struct tcpcb * tcp_newtcpcb(struct socket *);
|
||||
struct tcpcb * tcp_close(register struct tcpcb *);
|
||||
void tcp_drain(void);
|
||||
void tcp_sockclosed(struct tcpcb *);
|
||||
int tcp_fconnect(struct socket *);
|
||||
void tcp_connect(struct socket *);
|
||||
int tcp_attach(struct socket *);
|
||||
u_int8_t tcp_tos(struct socket *);
|
||||
int tcp_emu(struct socket *, struct mbuf *);
|
||||
int tcp_ctl(struct socket *);
|
||||
void tcp_init _P((void));
|
||||
void tcp_template _P((struct tcpcb *));
|
||||
void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
|
||||
struct tcpcb * tcp_newtcpcb _P((struct socket *));
|
||||
struct tcpcb * tcp_close _P((register struct tcpcb *));
|
||||
void tcp_sockclosed _P((struct tcpcb *));
|
||||
int tcp_fconnect _P((struct socket *));
|
||||
void tcp_connect _P((struct socket *));
|
||||
int tcp_attach _P((struct socket *));
|
||||
u_int8_t tcp_tos _P((struct socket *));
|
||||
int tcp_emu _P((struct socket *, struct mbuf *));
|
||||
int tcp_ctl _P((struct socket *));
|
||||
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
||||
|
||||
#ifdef USE_PPP
|
||||
|
@ -355,4 +334,9 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
|||
#define max(x,y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef errno
|
||||
#define errno (WSAGetLastError())
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
*/
|
||||
#undef USE_LOWCPU
|
||||
|
||||
/* Define this if your compiler doesn't like prototypes */
|
||||
#ifndef __STDC__
|
||||
#define NO_PROTOTYPES
|
||||
#endif
|
||||
|
||||
/*********************************************************/
|
||||
/*
|
||||
* Autoconf defined configuration options
|
||||
|
@ -49,11 +54,40 @@
|
|||
/* Ignore this */
|
||||
#undef DUMMY_PPP
|
||||
|
||||
/* XXX: Define according to how time.h should be included */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
/* Define if you have unistd.h */
|
||||
#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
|
||||
#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 */
|
||||
#undef BAD_SPRINTF
|
||||
|
||||
|
@ -69,17 +103,56 @@
|
|||
/* Define if a declaration of sprintf/fprintf is needed */
|
||||
#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 */
|
||||
#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 */
|
||||
#undef NEED_TYPEDEFS
|
||||
#ifdef __sun__
|
||||
#define NEED_TYPEDEFS
|
||||
#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 SIZEOF_CHAR_P SIZEOF_VOID_P
|
||||
#define SIZEOF_CHAR_P (HOST_LONG_BITS / 8)
|
||||
|
||||
/* Define if you have random() */
|
||||
#undef HAVE_RANDOM
|
||||
|
@ -87,6 +160,12 @@
|
|||
/* Define if you 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 */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define WANT_SYS_IOCTL_H
|
||||
#include <stdlib.h>
|
||||
#include <slirp.h>
|
||||
#include "ip_icmp.h"
|
||||
#include "main.h"
|
||||
|
@ -14,18 +13,16 @@
|
|||
#include <sys/filio.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN)
|
||||
#else
|
||||
#define IS_EAGAIN(e) ((e) == EAGAIN)
|
||||
#endif
|
||||
static void sofcantrcvmore(struct socket *so);
|
||||
static void sofcantsendmore(struct socket *so);
|
||||
|
||||
void
|
||||
#if 0
|
||||
static void
|
||||
so_init()
|
||||
{
|
||||
/* Nothing yet */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct socket *
|
||||
solookup(head, laddr, lport, faddr, fport)
|
||||
|
@ -36,19 +33,19 @@ solookup(head, laddr, lport, faddr, fport)
|
|||
u_int fport;
|
||||
{
|
||||
struct socket *so;
|
||||
|
||||
|
||||
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_faddr.s_addr == faddr.s_addr &&
|
||||
so->so_fport == fport)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (so == head)
|
||||
return (struct socket *)NULL;
|
||||
return so;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -60,7 +57,7 @@ struct socket *
|
|||
socreate()
|
||||
{
|
||||
struct socket *so;
|
||||
|
||||
|
||||
so = (struct socket *)malloc(sizeof(struct socket));
|
||||
if(so) {
|
||||
memset(so, 0, sizeof(struct socket));
|
||||
|
@ -85,10 +82,10 @@ sofree(so)
|
|||
tcp_last_so = &tcb;
|
||||
else if (so == udp_last_so)
|
||||
udp_last_so = &udb;
|
||||
|
||||
|
||||
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 */
|
||||
|
||||
free(so);
|
||||
|
@ -103,23 +100,22 @@ int
|
|||
soread(so)
|
||||
struct socket *so;
|
||||
{
|
||||
int n, nn;
|
||||
u_int lss, total;
|
||||
int n, nn, lss, total;
|
||||
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];
|
||||
u_int mss = so->so_tcpcb->t_maxseg;
|
||||
|
||||
int mss = so->so_tcpcb->t_maxseg;
|
||||
|
||||
DEBUG_CALL("soread");
|
||||
DEBUG_ARG("so = %lx", (long )so);
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* No need to check if there's enough room to read.
|
||||
* soread wouldn't have been called if there weren't
|
||||
*/
|
||||
|
||||
|
||||
len = sb->sb_datalen - sb->sb_cc;
|
||||
|
||||
|
||||
iov[0].iov_base = sb->sb_wptr;
|
||||
if (sb->sb_wptr < sb->sb_rptr) {
|
||||
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
|
||||
|
@ -158,16 +154,15 @@ soread(so)
|
|||
n = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_READV
|
||||
nn = readv(so->s, (struct iovec *)iov, n);
|
||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||
#else
|
||||
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
#endif
|
||||
#endif
|
||||
if (nn <= 0) {
|
||||
int error = WSAGetLastError();
|
||||
if (nn < 0 && IS_EAGAIN(error))
|
||||
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
|
||||
return 0;
|
||||
else {
|
||||
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
|
||||
|
@ -176,7 +171,7 @@ soread(so)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAVE_READV
|
||||
/*
|
||||
* If there was no error, try and read the second time round
|
||||
|
@ -193,10 +188,10 @@ soread(so)
|
|||
if (ret > 0)
|
||||
nn += ret;
|
||||
}
|
||||
|
||||
|
||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||
#endif
|
||||
|
||||
|
||||
/* Update fields */
|
||||
sb->sb_cc += nn;
|
||||
sb->sb_wptr += nn;
|
||||
|
@ -204,10 +199,10 @@ soread(so)
|
|||
sb->sb_wptr -= sb->sb_datalen;
|
||||
return nn;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get urgent data
|
||||
*
|
||||
*
|
||||
* When the socket is created, we set it SO_OOBINLINE,
|
||||
* so when OOB data arrives, we soread() it and everything
|
||||
* in the send buffer is sent as urgent data
|
||||
|
@ -220,13 +215,13 @@ sorecvoob(so)
|
|||
|
||||
DEBUG_CALL("sorecvoob");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
|
||||
|
||||
/*
|
||||
* We take a guess at how much urgent data has arrived.
|
||||
* In most situations, when urgent data arrives, the next
|
||||
* read() should get all the urgent data. This guess will
|
||||
* 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.
|
||||
*/
|
||||
soread(so);
|
||||
|
@ -246,24 +241,24 @@ sosendoob(so)
|
|||
{
|
||||
struct sbuf *sb = &so->so_rcv;
|
||||
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
|
||||
|
||||
|
||||
int n, len;
|
||||
|
||||
|
||||
DEBUG_CALL("sosendoob");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
|
||||
|
||||
|
||||
if (so->so_urgc > 2048)
|
||||
so->so_urgc = 2048; /* XXXX */
|
||||
|
||||
|
||||
if (sb->sb_rptr < sb->sb_wptr) {
|
||||
/* We can send it directly */
|
||||
n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
|
||||
so->so_urgc -= n;
|
||||
|
||||
|
||||
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
|
||||
} else {
|
||||
/*
|
||||
/*
|
||||
* Since there's no sendv or sendtov like writev,
|
||||
* we must copy all data to a linear buffer then
|
||||
* send it all
|
||||
|
@ -283,20 +278,20 @@ sosendoob(so)
|
|||
#ifdef DEBUG
|
||||
if (n != len)
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
sb->sb_cc -= n;
|
||||
sb->sb_rptr += n;
|
||||
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
||||
sb->sb_rptr -= sb->sb_datalen;
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
int
|
||||
|
@ -305,12 +300,12 @@ sowrite(so)
|
|||
{
|
||||
int n,nn;
|
||||
struct sbuf *sb = &so->so_rcv;
|
||||
u_int len = sb->sb_cc;
|
||||
int len = sb->sb_cc;
|
||||
struct iovec iov[2];
|
||||
|
||||
|
||||
DEBUG_CALL("sowrite");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
|
||||
|
||||
if (so->so_urgc) {
|
||||
sosendoob(so);
|
||||
if (sb->sb_cc == 0)
|
||||
|
@ -321,9 +316,9 @@ sowrite(so)
|
|||
* No need to check if there's something to write,
|
||||
* sowrite wouldn't have been called otherwise
|
||||
*/
|
||||
|
||||
|
||||
len = sb->sb_cc;
|
||||
|
||||
|
||||
iov[0].iov_base = sb->sb_rptr;
|
||||
if (sb->sb_rptr < sb->sb_wptr) {
|
||||
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
|
||||
|
@ -346,17 +341,14 @@ sowrite(so)
|
|||
|
||||
#ifdef HAVE_READV
|
||||
nn = writev(so->s, (const struct iovec *)iov, n);
|
||||
|
||||
|
||||
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
||||
#else
|
||||
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||
#endif
|
||||
/* This should never happen, but people tell me it does *shrug* */
|
||||
if (nn < 0) {
|
||||
int error = WSAGetLastError();
|
||||
if (IS_EAGAIN(error))
|
||||
return 0;
|
||||
}
|
||||
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
|
||||
return 0;
|
||||
|
||||
if (nn <= 0) {
|
||||
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
|
||||
|
@ -365,7 +357,7 @@ sowrite(so)
|
|||
tcp_sockclosed(sototcpcb(so));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAVE_READV
|
||||
if (n == 2 && nn == iov[0].iov_len) {
|
||||
int ret;
|
||||
|
@ -375,20 +367,20 @@ sowrite(so)
|
|||
}
|
||||
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
||||
#endif
|
||||
|
||||
|
||||
/* Update sbuf */
|
||||
sb->sb_cc -= nn;
|
||||
sb->sb_rptr += nn;
|
||||
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
||||
sb->sb_rptr -= sb->sb_datalen;
|
||||
|
||||
|
||||
/*
|
||||
* If in DRAIN mode, and there's no more data, set
|
||||
* it CANTSENDMORE
|
||||
*/
|
||||
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
|
||||
sofcantsendmore(so);
|
||||
|
||||
|
||||
return nn;
|
||||
}
|
||||
|
||||
|
@ -400,26 +392,25 @@ sorecvfrom(so)
|
|||
struct socket *so;
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
|
||||
int addrlen = sizeof(struct sockaddr_in);
|
||||
|
||||
DEBUG_CALL("sorecvfrom");
|
||||
DEBUG_ARG("so = %lx", (long)so);
|
||||
|
||||
|
||||
if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
|
||||
char buff[256];
|
||||
int len;
|
||||
|
||||
len = recvfrom(so->s, buff, 256, 0,
|
||||
|
||||
len = recvfrom(so->s, buff, 256, 0,
|
||||
(struct sockaddr *)&addr, &addrlen);
|
||||
/* XXX Check if reply is "correct"? */
|
||||
|
||||
|
||||
if(len == -1 || len == 0) {
|
||||
u_char code=ICMP_UNREACH_PORT;
|
||||
|
||||
int error = WSAGetLastError();
|
||||
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
|
||||
|
||||
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
|
||||
|
||||
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
|
||||
errno,strerror(errno)));
|
||||
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
||||
|
@ -431,38 +422,36 @@ sorecvfrom(so)
|
|||
udp_detach(so);
|
||||
} else { /* A "normal" UDP packet */
|
||||
struct mbuf *m;
|
||||
u_int len;
|
||||
ioctlsockopt_t n;
|
||||
int len, n;
|
||||
|
||||
if (!(m = m_get())) return;
|
||||
m->m_data += if_maxlinkhdr;
|
||||
|
||||
/*
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
|
||||
/*
|
||||
* XXX Shouldn't FIONREAD packets destined for port 53,
|
||||
* but I don't know the max packet size for DNS lookups
|
||||
*/
|
||||
len = M_FREEROOM(m);
|
||||
/* if (so->so_fport != htons(53)) { */
|
||||
ioctlsocket(so->s, FIONREAD, &n);
|
||||
|
||||
|
||||
if (n > len) {
|
||||
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
|
||||
m_inc(m, n);
|
||||
len = M_FREEROOM(m);
|
||||
}
|
||||
/* } */
|
||||
|
||||
|
||||
m->m_len = recvfrom(so->s, m->m_data, len, 0,
|
||||
(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)));
|
||||
if(m->m_len<0) {
|
||||
u_char code=ICMP_UNREACH_PORT;
|
||||
|
||||
int error = WSAGetLastError();
|
||||
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
|
||||
|
||||
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
|
||||
|
||||
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
|
||||
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
||||
m_free(m);
|
||||
|
@ -485,8 +474,8 @@ sorecvfrom(so)
|
|||
* m->m_len = 0;
|
||||
* }
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* If this packet was destined for CTL_ADDR,
|
||||
* 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_ARG("so = %lx", (long)so);
|
||||
DEBUG_ARG("m = %lx", (long)m);
|
||||
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
|
||||
/* It's an alias */
|
||||
|
@ -526,16 +515,14 @@ sosendto(so, m)
|
|||
addr.sin_addr = so->so_faddr;
|
||||
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_ntop(AF_INET, &addr.sin_addr, addrstr, sizeof(addrstr))));
|
||||
|
||||
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)));
|
||||
|
||||
/* Don't care what port we get */
|
||||
ret = sendto(so->s, m->m_data, m->m_len, 0,
|
||||
(struct sockaddr *)&addr, sizeof (struct sockaddr));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
/*
|
||||
* Kill the socket if there's no reply in 4 minutes,
|
||||
* but only if it's an expirable socket
|
||||
|
@ -558,57 +545,58 @@ solisten(port, laddr, lport, flags)
|
|||
{
|
||||
struct sockaddr_in addr;
|
||||
struct socket *so;
|
||||
int s;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int opt = 1;
|
||||
int s, addrlen = sizeof(addr), opt = 1;
|
||||
|
||||
DEBUG_CALL("solisten");
|
||||
DEBUG_ARG("port = %d", port);
|
||||
DEBUG_ARG("laddr = %x", laddr);
|
||||
DEBUG_ARG("lport = %d", lport);
|
||||
DEBUG_ARG("flags = %x", flags);
|
||||
|
||||
|
||||
if ((so = socreate()) == NULL) {
|
||||
/* free(so); Not sofree() ??? free(NULL) == NOP */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
|
||||
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
|
||||
free(so);
|
||||
return NULL;
|
||||
}
|
||||
insque(so,&tcb);
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* SS_FACCEPTONCE sockets must time out.
|
||||
*/
|
||||
if (flags & SS_FACCEPTONCE)
|
||||
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
|
||||
|
||||
|
||||
so->so_state = (SS_FACCEPTCONN|flags);
|
||||
so->so_lport = lport; /* Kept in network format */
|
||||
so->so_laddr.s_addr = laddr; /* Ditto */
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = port;
|
||||
|
||||
|
||||
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
||||
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
|
||||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 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);
|
||||
sofree(so);
|
||||
/* Restore the real errno */
|
||||
WSASetLastError(error);
|
||||
#ifdef _WIN32
|
||||
WSASetLastError(tmperrno);
|
||||
#else
|
||||
errno = tmperrno;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||
|
||||
|
||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
||||
so->so_fport = addr.sin_port;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
#if 0
|
||||
/*
|
||||
* Data is available in so_rcv
|
||||
* Just write() the data to the socket
|
||||
* XXX not yet...
|
||||
*/
|
||||
void
|
||||
static void
|
||||
sorwakeup(so)
|
||||
struct socket *so;
|
||||
{
|
||||
/* sowrite(so); */
|
||||
/* FD_CLR(so->s,&writefds); */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Data has been freed in so_snd
|
||||
* We have room for a read() if we want to
|
||||
* For now, don't read, it'll be done in the main loop
|
||||
*/
|
||||
void
|
||||
static void
|
||||
sowwakeup(so)
|
||||
struct socket *so;
|
||||
{
|
||||
/* Nothing, yet */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Various session state calls
|
||||
|
@ -668,9 +658,8 @@ soisfconnected(so)
|
|||
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
|
||||
}
|
||||
|
||||
void
|
||||
sofcantrcvmore(so)
|
||||
struct socket *so;
|
||||
static void
|
||||
sofcantrcvmore(struct socket *so)
|
||||
{
|
||||
if ((so->so_state & SS_NOFDREF) == 0) {
|
||||
shutdown(so->s,0);
|
||||
|
@ -685,9 +674,8 @@ sofcantrcvmore(so)
|
|||
so->so_state |= SS_FCANTRCVMORE;
|
||||
}
|
||||
|
||||
void
|
||||
sofcantsendmore(so)
|
||||
struct socket *so;
|
||||
static void
|
||||
sofcantsendmore(struct socket *so)
|
||||
{
|
||||
if ((so->so_state & SS_NOFDREF) == 0) {
|
||||
shutdown(so->s,1); /* send FIN to fhost */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -33,21 +33,21 @@ struct socket {
|
|||
struct in_addr so_laddr; /* local host table entry */
|
||||
u_int16_t so_fport; /* foreign port */
|
||||
u_int16_t so_lport; /* local port */
|
||||
|
||||
|
||||
u_int8_t so_iptos; /* Type of service */
|
||||
u_int8_t so_emu; /* Is the socket emulated? */
|
||||
|
||||
|
||||
u_char so_type; /* Type of socket, UDP or TCP */
|
||||
int so_state; /* internal state flags SS_*, below */
|
||||
|
||||
|
||||
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
||||
u_int so_expire; /* When the socket will expire */
|
||||
|
||||
|
||||
int so_queued; /* Number of packets queued from this socket */
|
||||
int so_nqueued; /* Number of packets queued in a row
|
||||
* Used to determine when to "downgrade" a session
|
||||
* from fastq to batchq */
|
||||
|
||||
|
||||
struct sbuf so_rcv; /* Receive buffer */
|
||||
struct sbuf so_snd; /* Send buffer */
|
||||
void * extra; /* Extra pointer */
|
||||
|
@ -81,24 +81,19 @@ struct iovec {
|
|||
};
|
||||
#endif
|
||||
|
||||
void so_init(void);
|
||||
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
||||
struct socket * socreate(void);
|
||||
void sofree(struct socket *);
|
||||
int soread(struct socket *);
|
||||
void sorecvoob(struct socket *);
|
||||
int sosendoob(struct socket *);
|
||||
int sowrite(struct socket *);
|
||||
void sorecvfrom(struct socket *);
|
||||
int sosendto(struct socket *, struct mbuf *);
|
||||
struct socket * solisten(u_int, u_int32_t, u_int, int);
|
||||
void sorwakeup(struct socket *);
|
||||
void sowwakeup(struct socket *);
|
||||
void soisfconnecting(register struct socket *);
|
||||
void soisfconnected(register struct socket *);
|
||||
void sofcantrcvmore(struct socket *);
|
||||
void sofcantsendmore(struct socket *);
|
||||
void soisfdisconnected(struct socket *);
|
||||
void sofwdrain(struct socket *);
|
||||
struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
|
||||
struct socket * socreate _P((void));
|
||||
void sofree _P((struct socket *));
|
||||
int soread _P((struct socket *));
|
||||
void sorecvoob _P((struct socket *));
|
||||
int sosendoob _P((struct socket *));
|
||||
int sowrite _P((struct socket *));
|
||||
void sorecvfrom _P((struct socket *));
|
||||
int sosendto _P((struct socket *, struct mbuf *));
|
||||
struct socket * solisten _P((u_int, u_int32_t, u_int, int));
|
||||
void soisfconnecting _P((register struct socket *));
|
||||
void soisfconnected _P((register struct socket *));
|
||||
void soisfdisconnected _P((struct socket *));
|
||||
void sofwdrain _P((struct socket *));
|
||||
|
||||
#endif /* _SOCKET_H_ */
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* 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_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;
|
||||
|
||||
#define TCP_SNDSPACE 8192
|
||||
|
@ -49,20 +51,16 @@ extern struct socket *tcp_last_so;
|
|||
* TCP header.
|
||||
* Per RFC 793, September, 1981.
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct tcphdr {
|
||||
u_int16_t th_sport; /* source port */
|
||||
u_int16_t th_dport; /* destination port */
|
||||
tcp_seq th_seq; /* sequence number */
|
||||
tcp_seq th_ack; /* acknowledgement number */
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
u_char th_off:4, /* data offset */
|
||||
u_int th_off:4, /* data offset */
|
||||
th_x2:4; /* (unused) */
|
||||
#else
|
||||
u_char th_x2:4, /* (unused) */
|
||||
u_int th_x2:4, /* (unused) */
|
||||
th_off:4; /* data offset */
|
||||
#endif
|
||||
u_int8_t th_flags;
|
||||
|
@ -75,11 +73,7 @@ struct tcphdr {
|
|||
u_int16_t th_win; /* window */
|
||||
u_int16_t th_sum; /* checksum */
|
||||
u_int16_t th_urp; /* urgent pointer */
|
||||
} PACKED__;
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(PACK_RESET)
|
||||
#endif
|
||||
};
|
||||
|
||||
#include "tcp_var.h"
|
||||
|
||||
|
@ -176,6 +170,6 @@ struct tcphdr {
|
|||
|
||||
extern tcp_seq tcp_iss; /* tcp initial send seq # */
|
||||
|
||||
extern char *tcpstates[];
|
||||
extern const char * const tcpstates[];
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -33,8 +37,8 @@
|
|||
/*
|
||||
* Changes and additions relating to SLiRP
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
@ -44,16 +48,16 @@
|
|||
* Since this is only used in "stats socket", we give meaning
|
||||
* names instead of the REAL names
|
||||
*/
|
||||
char *tcpstates[] = {
|
||||
const char * const tcpstates[] = {
|
||||
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
|
||||
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
|
||||
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
|
||||
"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_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,
|
||||
};
|
||||
|
||||
|
@ -63,7 +67,9 @@ u_char tcp_outflags[TCP_NSTATES] = {
|
|||
/*
|
||||
* 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 long len, win;
|
||||
|
@ -73,10 +79,10 @@ int tcp_output(register struct tcpcb *tp)
|
|||
u_char opt[MAX_TCPOPTLEN];
|
||||
unsigned optlen, hdrlen;
|
||||
int idle, sendalot;
|
||||
|
||||
|
||||
DEBUG_CALL("tcp_output");
|
||||
DEBUG_ARG("tp = %lx", (long )tp);
|
||||
|
||||
|
||||
/*
|
||||
* Determine length of data that should be transmitted,
|
||||
* and flags that will be used.
|
||||
|
@ -97,9 +103,9 @@ again:
|
|||
win = min(tp->snd_wnd, tp->snd_cwnd);
|
||||
|
||||
flags = tcp_outflags[tp->t_state];
|
||||
|
||||
|
||||
DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
|
||||
|
||||
|
||||
/*
|
||||
* If in persist timeout with window of 0, send 1 byte.
|
||||
* Otherwise, if window is small but nonzero
|
||||
|
@ -124,7 +130,7 @@ again:
|
|||
* to send then the probe will be the FIN
|
||||
* itself.
|
||||
*/
|
||||
if (off < (int)so->so_snd.sb_cc)
|
||||
if (off < so->so_snd.sb_cc)
|
||||
flags &= ~TH_FIN;
|
||||
win = 1;
|
||||
} else {
|
||||
|
@ -152,7 +158,7 @@ again:
|
|||
tp->snd_nxt = tp->snd_una;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (len > tp->t_maxseg) {
|
||||
len = tp->t_maxseg;
|
||||
sendalot = 1;
|
||||
|
@ -194,17 +200,17 @@ again:
|
|||
* window, then want to send a window update to peer.
|
||||
*/
|
||||
if (win > 0) {
|
||||
/*
|
||||
/*
|
||||
* "adv" is the amount we can increase the window,
|
||||
* taking into account that we are limited by
|
||||
* 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);
|
||||
|
||||
if (adv >= (long)(2 * tp->t_maxseg))
|
||||
if (adv >= (long) (2 * tp->t_maxseg))
|
||||
goto send;
|
||||
if (2 * adv >= (long)so->so_rcv.sb_datalen)
|
||||
if (2 * adv >= (long) so->so_rcv.sb_datalen)
|
||||
goto send;
|
||||
}
|
||||
|
||||
|
@ -257,8 +263,8 @@ again:
|
|||
/*
|
||||
* No reason to send a segment, just return.
|
||||
*/
|
||||
tcpstat.tcps_didnuttin++;
|
||||
|
||||
STAT(tcpstat.tcps_didnuttin++);
|
||||
|
||||
return (0);
|
||||
|
||||
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
|
||||
* and our peer have sent timestamps in our SYN's.
|
||||
*/
|
||||
|
@ -316,7 +322,7 @@ send:
|
|||
* }
|
||||
*/
|
||||
hdrlen += optlen;
|
||||
|
||||
|
||||
/*
|
||||
* Adjust data length if insertion of options will
|
||||
* bump the packet length beyond the t_maxseg length.
|
||||
|
@ -333,13 +339,13 @@ send:
|
|||
*/
|
||||
if (len) {
|
||||
if (tp->t_force && len == 1)
|
||||
tcpstat.tcps_sndprobe++;
|
||||
STAT(tcpstat.tcps_sndprobe++);
|
||||
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
|
||||
tcpstat.tcps_sndrexmitpack++;
|
||||
tcpstat.tcps_sndrexmitbyte += len;
|
||||
STAT(tcpstat.tcps_sndrexmitpack++);
|
||||
STAT(tcpstat.tcps_sndrexmitbyte += len);
|
||||
} else {
|
||||
tcpstat.tcps_sndpack++;
|
||||
tcpstat.tcps_sndbyte += len;
|
||||
STAT(tcpstat.tcps_sndpack++);
|
||||
STAT(tcpstat.tcps_sndbyte += len);
|
||||
}
|
||||
|
||||
m = m_get();
|
||||
|
@ -348,16 +354,16 @@ send:
|
|||
error = 1;
|
||||
goto out;
|
||||
}
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
m->m_len = hdrlen;
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* This will always succeed, since we make sure our mbufs
|
||||
* are big enough to hold one MSS packet + header + ... etc.
|
||||
*/
|
||||
/* 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;
|
||||
|
||||
/* } else {
|
||||
|
@ -376,13 +382,13 @@ send:
|
|||
flags |= TH_PUSH;
|
||||
} else {
|
||||
if (tp->t_flags & TF_ACKNOW)
|
||||
tcpstat.tcps_sndacks++;
|
||||
STAT(tcpstat.tcps_sndacks++);
|
||||
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))
|
||||
tcpstat.tcps_sndurg++;
|
||||
STAT(tcpstat.tcps_sndurg++);
|
||||
else
|
||||
tcpstat.tcps_sndwinup++;
|
||||
STAT(tcpstat.tcps_sndwinup++);
|
||||
|
||||
m = m_get();
|
||||
if (m == NULL) {
|
||||
|
@ -390,12 +396,12 @@ send:
|
|||
error = 1;
|
||||
goto out;
|
||||
}
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
m->m_len = hdrlen;
|
||||
}
|
||||
|
||||
ti = mtod(m, 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.
|
||||
* 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--;
|
||||
/*
|
||||
|
@ -433,17 +439,17 @@ send:
|
|||
* Calculate receive window. Don't shrink window,
|
||||
* 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;
|
||||
if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale))
|
||||
win = (u_long) (TCP_MAXWIN << tp->rcv_scale);
|
||||
if (win < (tp->rcv_adv - tp->rcv_nxt))
|
||||
win = (tp->rcv_adv - tp->rcv_nxt);
|
||||
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
|
||||
win = (long)TCP_MAXWIN << tp->rcv_scale;
|
||||
if (win < (long)(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));
|
||||
|
||||
|
||||
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
||||
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)) {
|
||||
ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
|
||||
#endif
|
||||
|
@ -494,7 +500,7 @@ send:
|
|||
if (tp->t_rtt == 0) {
|
||||
tp->t_rtt = 1;
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
||||
/* #if BSD >= 43 */
|
||||
/* Don't do IP options... */
|
||||
/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
|
||||
|
@ -541,7 +547,7 @@ send:
|
|||
error = ip_output(so, m);
|
||||
|
||||
/* #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);
|
||||
* #endif
|
||||
*/
|
||||
|
@ -561,7 +567,7 @@ out:
|
|||
*/
|
||||
return (error);
|
||||
}
|
||||
tcpstat.tcps_sndtotal++;
|
||||
STAT(tcpstat.tcps_sndtotal++);
|
||||
|
||||
/*
|
||||
* Data sent (as far as we can tell).
|
||||
|
@ -579,7 +585,9 @@ out:
|
|||
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;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -32,14 +36,14 @@
|
|||
|
||||
#include <slirp.h>
|
||||
|
||||
int tcp_keepidle = TCPTV_KEEP_IDLE;
|
||||
int tcp_keepintvl = TCPTV_KEEPINTVL;
|
||||
int tcp_maxidle;
|
||||
int so_options = DO_KEEPALIVE;
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
struct tcpstat tcpstat; /* tcp statistics */
|
||||
#endif
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -50,7 +54,7 @@ tcp_fasttimo()
|
|||
register struct tcpcb *tp;
|
||||
|
||||
DEBUG_CALL("tcp_fasttimo");
|
||||
|
||||
|
||||
so = tcb.so_next;
|
||||
if (so)
|
||||
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_ACKNOW;
|
||||
tcpstat.tcps_delack++;
|
||||
STAT(tcpstat.tcps_delack++);
|
||||
(void) tcp_output(tp);
|
||||
}
|
||||
}
|
||||
|
@ -76,8 +80,7 @@ tcp_slowtimo()
|
|||
register int i;
|
||||
|
||||
DEBUG_CALL("tcp_slowtimo");
|
||||
|
||||
tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
|
||||
|
||||
/*
|
||||
* Search through tcb's and update active timers.
|
||||
*/
|
||||
|
@ -123,21 +126,19 @@ tcp_canceltimers(tp)
|
|||
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 };
|
||||
|
||||
/*
|
||||
* TCP timer processing.
|
||||
*/
|
||||
struct tcpcb *
|
||||
tcp_timers(tp, timer)
|
||||
register struct tcpcb *tp;
|
||||
int timer;
|
||||
static struct tcpcb *
|
||||
tcp_timers(register struct tcpcb *tp, int timer)
|
||||
{
|
||||
register int rexmt;
|
||||
|
||||
|
||||
DEBUG_CALL("tcp_timers");
|
||||
|
||||
|
||||
switch (timer) {
|
||||
|
||||
/*
|
||||
|
@ -148,8 +149,8 @@ tcp_timers(tp, timer)
|
|||
*/
|
||||
case TCPT_2MSL:
|
||||
if (tp->t_state != TCPS_TIME_WAIT &&
|
||||
tp->t_idle <= tcp_maxidle)
|
||||
tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
|
||||
tp->t_idle <= TCP_MAXIDLE)
|
||||
tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
|
||||
else
|
||||
tp = tcp_close(tp);
|
||||
break;
|
||||
|
@ -160,12 +161,12 @@ tcp_timers(tp, timer)
|
|||
* to a longer retransmit interval and retransmit one segment.
|
||||
*/
|
||||
case TCPT_REXMT:
|
||||
|
||||
|
||||
/*
|
||||
* XXXXX If a packet has timed out, then remove all the queued
|
||||
* packets for that session.
|
||||
*/
|
||||
|
||||
|
||||
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
|
||||
/*
|
||||
* 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
|
||||
* retransmitting, and eventually the connection dies...
|
||||
* (this only happens on incoming data)
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* let them through
|
||||
*
|
||||
*
|
||||
* *sigh*
|
||||
*/
|
||||
|
||||
|
||||
tp->t_maxseg >>= 1;
|
||||
if (tp->t_maxseg < 32) {
|
||||
/*
|
||||
* We tried our best, now the connection must die!
|
||||
*/
|
||||
tp->t_rxtshift = TCP_MAXRXTSHIFT;
|
||||
tcpstat.tcps_timeoutdrop++;
|
||||
STAT(tcpstat.tcps_timeoutdrop++);
|
||||
tp = tcp_drop(tp, tp->t_softerror);
|
||||
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
|
||||
return (tp); /* XXX */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set rxtshift to 6, which is still at the maximum
|
||||
* backoff time
|
||||
*/
|
||||
tp->t_rxtshift = 6;
|
||||
}
|
||||
tcpstat.tcps_rexmttimeo++;
|
||||
STAT(tcpstat.tcps_rexmttimeo++);
|
||||
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
||||
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
||||
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
|
||||
|
@ -236,7 +237,7 @@ tcp_timers(tp, timer)
|
|||
* size increase exponentially with time. If the
|
||||
* window is larger than the path can handle, this
|
||||
* 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
|
||||
* of improving conditions, we switch from exponential
|
||||
* to linear window opening at some threshold size.
|
||||
|
@ -263,7 +264,7 @@ tcp_timers(tp, timer)
|
|||
* Force a byte to be output, if possible.
|
||||
*/
|
||||
case TCPT_PERSIST:
|
||||
tcpstat.tcps_persisttimeo++;
|
||||
STAT(tcpstat.tcps_persisttimeo++);
|
||||
tcp_setpersist(tp);
|
||||
tp->t_force = 1;
|
||||
(void) tcp_output(tp);
|
||||
|
@ -275,13 +276,13 @@ tcp_timers(tp, timer)
|
|||
* or drop connection if idle for too long.
|
||||
*/
|
||||
case TCPT_KEEP:
|
||||
tcpstat.tcps_keeptimeo++;
|
||||
STAT(tcpstat.tcps_keeptimeo++);
|
||||
if (tp->t_state < TCPS_ESTABLISHED)
|
||||
goto dropit;
|
||||
|
||||
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */
|
||||
if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
||||
if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
|
||||
if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
||||
if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
|
||||
goto dropit;
|
||||
/*
|
||||
* Send a packet designed to force a response
|
||||
|
@ -295,7 +296,7 @@ tcp_timers(tp, timer)
|
|||
* by the protocol spec, this requires the
|
||||
* correspondent TCP to respond.
|
||||
*/
|
||||
tcpstat.tcps_keepprobe++;
|
||||
STAT(tcpstat.tcps_keepprobe++);
|
||||
#ifdef TCP_COMPAT_42
|
||||
/*
|
||||
* The keepalive packet must have nonzero length
|
||||
|
@ -307,13 +308,13 @@ tcp_timers(tp, timer)
|
|||
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
|
||||
tp->rcv_nxt, tp->snd_una - 1, 0);
|
||||
#endif
|
||||
tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
|
||||
} else
|
||||
tp->t_timer[TCPT_KEEP] = tcp_keepidle;
|
||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
|
||||
break;
|
||||
|
||||
dropit:
|
||||
tcpstat.tcps_keepdrops++;
|
||||
STAT(tcpstat.tcps_keepdrops++);
|
||||
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -122,17 +126,12 @@ char *tcptimers[] =
|
|||
(tv) = (tvmax); \
|
||||
}
|
||||
|
||||
extern int tcp_keepidle; /* time before keepalive probes begin */
|
||||
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[];
|
||||
extern const int tcp_backoff[];
|
||||
|
||||
struct tcpcb;
|
||||
|
||||
void tcp_fasttimo(void);
|
||||
void tcp_slowtimo(void);
|
||||
void tcp_canceltimers(struct tcpcb *);
|
||||
struct tcpcb * tcp_timers(register struct tcpcb *, int);
|
||||
void tcp_fasttimo _P((void));
|
||||
void tcp_slowtimo _P((void));
|
||||
void tcp_canceltimers _P((struct tcpcb *));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -181,6 +185,7 @@ typedef u_int32_t mbufp_32;
|
|||
#endif
|
||||
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
/*
|
||||
* TCP statistics.
|
||||
* Many of these should be kept per connection,
|
||||
|
@ -243,6 +248,8 @@ struct tcpstat {
|
|||
};
|
||||
|
||||
extern struct tcpstat tcpstat; /* tcp statistics */
|
||||
#endif
|
||||
|
||||
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* tftp.c - a simple, read-only tftp server for qemu
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004 Magnus Damm <damm@opensource.se>
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
|
@ -26,15 +26,15 @@
|
|||
|
||||
struct tftp_session {
|
||||
int in_use;
|
||||
char filename[TFTP_FILENAME_MAX];
|
||||
|
||||
unsigned char filename[TFTP_FILENAME_MAX];
|
||||
|
||||
struct in_addr client_ip;
|
||||
u_int16_t client_port;
|
||||
|
||||
|
||||
int timestamp;
|
||||
};
|
||||
|
||||
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
|
||||
static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
|
||||
|
||||
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 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) {
|
||||
return -1;
|
||||
|
@ -120,13 +127,53 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
|
|||
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,
|
||||
struct tftp_t *recv_tp)
|
||||
{
|
||||
struct sockaddr_in saddr, daddr;
|
||||
struct mbuf *m;
|
||||
struct tftp_t *tp;
|
||||
int nobytes;
|
||||
|
||||
m = m_get();
|
||||
|
||||
|
@ -136,14 +183,13 @@ static int tftp_send_error(struct tftp_session *spt,
|
|||
|
||||
memset(m->m_data, 0, m->m_size);
|
||||
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
tp = (void *)m->m_data;
|
||||
m->m_data += sizeof(struct udpiphdr);
|
||||
|
||||
|
||||
tp->tp_op = htons(TFTP_ERROR);
|
||||
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));
|
||||
tp->x.tp_error.tp_msg[sizeof(tp->x.tp_error.tp_msg)-1] = 0;
|
||||
strcpy(tp->x.tp_error.tp_msg, msg);
|
||||
|
||||
saddr.sin_addr = recv_tp->ip.ip_dst;
|
||||
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_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);
|
||||
|
||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||
|
@ -161,7 +209,7 @@ static int tftp_send_error(struct tftp_session *spt,
|
|||
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,
|
||||
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);
|
||||
|
||||
m->m_data += if_maxlinkhdr;
|
||||
m->m_data += IF_MAXLINKHDR;
|
||||
tp = (void *)m->m_data;
|
||||
m->m_data += sizeof(struct udpiphdr);
|
||||
|
||||
|
||||
tp->tp_op = htons(TFTP_DATA);
|
||||
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;
|
||||
}
|
||||
|
||||
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
|
||||
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
|
||||
sizeof(struct ip) - sizeof(struct udphdr);
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
|
||||
/* get name */
|
||||
|
@ -249,28 +297,30 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
|||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (src[k] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (k >= n) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
k++;
|
||||
|
||||
|
||||
/* check mode */
|
||||
if ((n - k) < 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (memcmp(&src[k], "octet\0", 6) != 0) {
|
||||
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
|
||||
return;
|
||||
}
|
||||
|
||||
k += 6; /* skipping octet */
|
||||
|
||||
/* do sanity checks on the filename */
|
||||
|
||||
if ((spt->filename[0] != '/')
|
||||
|
@ -282,19 +332,60 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
|||
|
||||
/* only allow exported prefixes */
|
||||
|
||||
if (!tftp_prefix
|
||||
|| (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) {
|
||||
if (!tftp_prefix) {
|
||||
tftp_send_error(spt, 2, "Access violation", tp);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -308,8 +399,8 @@ static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
|
|||
return;
|
||||
}
|
||||
|
||||
if (tftp_send_data(&tftp_sessions[s],
|
||||
ntohs(tp->x.tp_data.tp_block_nr) + 1,
|
||||
if (tftp_send_data(&tftp_sessions[s],
|
||||
ntohs(tp->x.tp_data.tp_block_nr) + 1,
|
||||
tp) < 0) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -9,32 +9,25 @@
|
|||
#define TFTP_DATA 3
|
||||
#define TFTP_ACK 4
|
||||
#define TFTP_ERROR 5
|
||||
#define TFTP_OACK 6
|
||||
|
||||
#define TFTP_FILENAME_MAX 512
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct tftp_t {
|
||||
struct ip ip;
|
||||
struct udphdr udp;
|
||||
u_int16_t tp_op;
|
||||
union {
|
||||
struct {
|
||||
struct {
|
||||
u_int16_t tp_block_nr;
|
||||
u_int8_t tp_buf[512];
|
||||
} tp_data;
|
||||
struct {
|
||||
struct {
|
||||
u_int16_t tp_error_code;
|
||||
u_int8_t tp_msg[512];
|
||||
} tp_error;
|
||||
u_int8_t tp_buf[512 + 2];
|
||||
} x;
|
||||
} PACKED__;
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(PACK_RESET)
|
||||
#endif
|
||||
};
|
||||
|
||||
void tftp_input(struct mbuf *m);
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -33,27 +37,31 @@
|
|||
/*
|
||||
* Changes and additions relating to SLiRP
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <slirp.h>
|
||||
#include "ip_icmp.h"
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
struct udpstat udpstat;
|
||||
#endif
|
||||
|
||||
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.
|
||||
* Per RFC 768, August, 1980.
|
||||
*/
|
||||
#ifndef COMPAT_42
|
||||
int udpcksum = 1;
|
||||
#define UDPCKSUM 1
|
||||
#else
|
||||
int udpcksum = 0; /* XXX */
|
||||
#define UDPCKSUM 0 /* XXX */
|
||||
#endif
|
||||
|
||||
struct socket *udp_last_so = &udb;
|
||||
|
@ -63,8 +71,8 @@ udp_init()
|
|||
{
|
||||
udb.so_next = udb.so_prev = &udb;
|
||||
}
|
||||
/* m->m_data points at ip packet header
|
||||
* m->m_len length ip packet
|
||||
/* m->m_data points at ip packet header
|
||||
* m->m_len length ip packet
|
||||
* ip->ip_len length data (IPDU)
|
||||
*/
|
||||
void
|
||||
|
@ -76,14 +84,14 @@ udp_input(m, iphlen)
|
|||
register struct udphdr *uh;
|
||||
/* struct mbuf *opts = 0;*/
|
||||
int len;
|
||||
struct ip save_ip;
|
||||
struct ip save_ip;
|
||||
struct socket *so;
|
||||
|
||||
|
||||
DEBUG_CALL("udp_input");
|
||||
DEBUG_ARG("m = %lx", (long)m);
|
||||
DEBUG_ARG("iphlen = %d", iphlen);
|
||||
|
||||
udpstat.udps_ipackets++;
|
||||
|
||||
STAT(udpstat.udps_ipackets++);
|
||||
|
||||
/*
|
||||
* Strip IP options, if any; should skip this,
|
||||
|
@ -110,34 +118,34 @@ udp_input(m, iphlen)
|
|||
|
||||
if (ip->ip_len != len) {
|
||||
if (len > ip->ip_len) {
|
||||
udpstat.udps_badlen++;
|
||||
STAT(udpstat.udps_badlen++);
|
||||
goto bad;
|
||||
}
|
||||
m_adj(m, len - ip->ip_len);
|
||||
ip->ip_len = len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Save a copy of the IP header in case we want restore it
|
||||
* for sending an ICMP error message in response.
|
||||
*/
|
||||
save_ip = *ip;
|
||||
save_ip = *ip;
|
||||
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
|
||||
|
||||
/*
|
||||
* 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_prev = 0;
|
||||
((struct ipovly *)ip)->ih_x1 = 0;
|
||||
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
|
||||
/* keep uh_sum for ICMP reply
|
||||
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
|
||||
* if (uh->uh_sum) {
|
||||
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
|
||||
* if (uh->uh_sum) {
|
||||
*/
|
||||
if(cksum(m, len + sizeof(struct ip))) {
|
||||
udpstat.udps_badsum++;
|
||||
STAT(udpstat.udps_badsum++);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +173,7 @@ udp_input(m, iphlen)
|
|||
if (so->so_lport != uh->uh_sport ||
|
||||
so->so_laddr.s_addr != ip->ip_src.s_addr) {
|
||||
struct socket *tmp;
|
||||
|
||||
|
||||
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
|
||||
if (tmp->so_lport == uh->uh_sport &&
|
||||
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
|
||||
|
@ -178,11 +186,11 @@ udp_input(m, iphlen)
|
|||
if (tmp == &udb) {
|
||||
so = NULL;
|
||||
} else {
|
||||
udpstat.udpps_pcbcachemiss++;
|
||||
STAT(udpstat.udpps_pcbcachemiss++);
|
||||
udp_last_so = so;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (so == NULL) {
|
||||
/*
|
||||
* If there's no socket for this packet,
|
||||
|
@ -190,22 +198,22 @@ udp_input(m, iphlen)
|
|||
*/
|
||||
if ((so = socreate()) == NULL) goto bad;
|
||||
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)));
|
||||
sofree(so);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup fields
|
||||
*/
|
||||
/* udp_last_so = so; */
|
||||
so->so_laddr = ip->ip_src;
|
||||
so->so_lport = uh->uh_sport;
|
||||
|
||||
|
||||
if ((so->so_iptos = udp_tos(so)) == 0)
|
||||
so->so_iptos = ip->ip_tos;
|
||||
|
||||
|
||||
/*
|
||||
* XXXXX Here, check if it's in udpexec_list,
|
||||
* and if it is, do the fork_exec() etc.
|
||||
|
@ -230,7 +238,7 @@ udp_input(m, iphlen)
|
|||
m->m_data -= iphlen;
|
||||
*ip=save_ip;
|
||||
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 */
|
||||
|
@ -248,7 +256,7 @@ bad:
|
|||
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,
|
||||
int iptos)
|
||||
{
|
||||
|
@ -266,19 +274,16 @@ int udp_output2(struct socket *so, struct mbuf *m,
|
|||
*/
|
||||
m->m_data -= sizeof(struct udpiphdr);
|
||||
m->m_len += sizeof(struct udpiphdr);
|
||||
|
||||
|
||||
/*
|
||||
* Fill in mbuf with extended UDP header
|
||||
* and addresses and length put into network format.
|
||||
*/
|
||||
ui = mtod(m, struct udpiphdr *);
|
||||
//ui->ui_next = ui->ui_prev = 0;
|
||||
|
||||
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
|
||||
|
||||
ui->ui_next = ui->ui_prev = 0;
|
||||
ui->ui_x1 = 0;
|
||||
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 */
|
||||
ui->ui_src = saddr->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.
|
||||
*/
|
||||
ui->ui_sum = 0;
|
||||
if (udpcksum) {
|
||||
if (UDPCKSUM) {
|
||||
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
|
||||
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;
|
||||
|
||||
udpstat.udps_opackets++;
|
||||
|
||||
|
||||
STAT(udpstat.udps_opackets++);
|
||||
|
||||
error = ip_output(so, m);
|
||||
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int udp_output(struct socket *so, struct mbuf *m,
|
||||
int udp_output(struct socket *so, struct mbuf *m,
|
||||
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_port = so->so_lport;
|
||||
|
||||
|
||||
return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
|
||||
}
|
||||
|
||||
|
@ -329,22 +334,25 @@ udp_attach(so)
|
|||
struct socket *so;
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
|
||||
|
||||
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
|
||||
/*
|
||||
* Here, we bind() the socket. Although not really needed
|
||||
* (sendto() on an unbound socket will bind it), it's done
|
||||
* 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_port = 0;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
|
||||
int error = WSAGetLastError();
|
||||
int lasterrno=errno;
|
||||
closesocket(so->s);
|
||||
so->s=-1;
|
||||
WSASetLastError(error);
|
||||
#ifdef _WIN32
|
||||
WSASetLastError(lasterrno);
|
||||
#else
|
||||
errno=lasterrno;
|
||||
#endif
|
||||
} else {
|
||||
/* success, insert in queue */
|
||||
so->so_expire = curtime + SO_EXPIRE;
|
||||
|
@ -364,7 +372,7 @@ udp_detach(so)
|
|||
sofree(so);
|
||||
}
|
||||
|
||||
struct tos_t udptos[] = {
|
||||
static const struct tos_t udptos[] = {
|
||||
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
|
||||
{517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
|
||||
{518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
|
||||
|
@ -372,12 +380,11 @@ struct tos_t udptos[] = {
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
u_int8_t
|
||||
udp_tos(so)
|
||||
struct socket *so;
|
||||
static u_int8_t
|
||||
udp_tos(struct socket *so)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
||||
while(udptos[i].tos) {
|
||||
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
|
||||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
|
||||
|
@ -386,7 +393,7 @@ udp_tos(so)
|
|||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -397,29 +404,27 @@ udp_tos(so)
|
|||
/*
|
||||
* Here, talk/ytalk/ntalk requests must be emulated
|
||||
*/
|
||||
void
|
||||
udp_emu(so, m)
|
||||
struct socket *so;
|
||||
struct mbuf *m;
|
||||
static void
|
||||
udp_emu(struct socket *so, struct mbuf *m)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
int addrlen = sizeof(addr);
|
||||
#ifdef EMULATE_TALK
|
||||
CTL_MSG_OLD *omsg;
|
||||
CTL_MSG *nmsg;
|
||||
char buff[sizeof(CTL_MSG)];
|
||||
u_char type;
|
||||
|
||||
|
||||
struct talk_request {
|
||||
struct talk_request *next;
|
||||
struct socket *udp_so;
|
||||
struct socket *tcp_so;
|
||||
} *req;
|
||||
|
||||
static struct talk_request *req_tbl = 0;
|
||||
|
||||
|
||||
static struct talk_request *req_tbl = 0;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct cu_header {
|
||||
uint16_t d_family; // destination family
|
||||
uint16_t d_port; // destination port
|
||||
|
@ -446,7 +451,7 @@ struct cu_header {
|
|||
*/
|
||||
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
||||
return;
|
||||
|
||||
|
||||
#define IS_OLD (so->so_emu == EMU_TALK)
|
||||
|
||||
#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_addr = our_addr;
|
||||
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
|
||||
} else { /* new talk */
|
||||
} else { /* new talk */
|
||||
omsg = (CTL_MSG_OLD *) buff;
|
||||
nmsg = mtod(m, CTL_MSG *);
|
||||
type = nmsg->type;
|
||||
|
@ -477,10 +482,10 @@ struct cu_header {
|
|||
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
|
||||
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
|
||||
}
|
||||
|
||||
if (type == LOOK_UP)
|
||||
|
||||
if (type == LOOK_UP)
|
||||
return; /* for LOOK_UP this is enough */
|
||||
|
||||
|
||||
if (IS_OLD) { /* make a copy of the message */
|
||||
COPY_MSG(nmsg, omsg);
|
||||
nmsg->vers = 1;
|
||||
|
@ -499,75 +504,75 @@ struct cu_header {
|
|||
* ports, 517 and 518. This is why we have two copies
|
||||
* of the message, one in old talk and one in new talk
|
||||
* format.
|
||||
*/
|
||||
*/
|
||||
|
||||
if (type == ANNOUNCE) {
|
||||
int s;
|
||||
u_short temp_port;
|
||||
|
||||
|
||||
for(req = req_tbl; req; req = req->next)
|
||||
if (so == req->udp_so)
|
||||
break; /* found it */
|
||||
|
||||
|
||||
if (!req) { /* no entry for so, create new */
|
||||
req = (struct talk_request *)
|
||||
malloc(sizeof(struct talk_request));
|
||||
req->udp_so = so;
|
||||
req->tcp_so = solisten(0,
|
||||
OTOSIN(omsg, addr)->sin_addr.s_addr,
|
||||
req->tcp_so = solisten(0,
|
||||
OTOSIN(omsg, addr)->sin_addr.s_addr,
|
||||
OTOSIN(omsg, addr)->sin_port,
|
||||
SS_FACCEPTONCE);
|
||||
req->next = req_tbl;
|
||||
req_tbl = req;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* replace port number in addr field */
|
||||
addrlen = sizeof(addr);
|
||||
getsockname(req->tcp_so->s,
|
||||
getsockname(req->tcp_so->s,
|
||||
(struct sockaddr *) &addr,
|
||||
&addrlen);
|
||||
&addrlen);
|
||||
OTOSIN(omsg, addr)->sin_port = addr.sin_port;
|
||||
OTOSIN(omsg, addr)->sin_addr = our_addr;
|
||||
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 */
|
||||
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
||||
OTOSIN(omsg, 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);
|
||||
addr.sin_addr = our_addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(517);
|
||||
sendto(s, (char *)omsg, sizeof(*omsg), 0,
|
||||
sendto(s, (char *)omsg, sizeof(*omsg), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr));
|
||||
addr.sin_port = htons(518);
|
||||
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
||||
(struct sockaddr *) &addr, sizeof(addr));
|
||||
closesocket(s) ;
|
||||
|
||||
omsg->type = nmsg->type = ANNOUNCE;
|
||||
omsg->type = nmsg->type = ANNOUNCE;
|
||||
OTOSIN(omsg, 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
|
||||
* local daemons. Then we delete the entry corresponding
|
||||
* to our socket from the request table.
|
||||
*/
|
||||
|
||||
|
||||
if (type == DELETE) {
|
||||
struct talk_request *temp_req, *req_next;
|
||||
int s;
|
||||
u_short temp_port;
|
||||
|
||||
|
||||
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
||||
OTOSIN(omsg, ctl_addr)->sin_port = 0;
|
||||
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
|
||||
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
addr.sin_addr = our_addr;
|
||||
addr.sin_family = AF_INET;
|
||||
|
@ -578,7 +583,7 @@ struct cu_header {
|
|||
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr));
|
||||
closesocket(s);
|
||||
|
||||
|
||||
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
|
||||
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
|
||||
|
||||
|
@ -601,18 +606,18 @@ struct cu_header {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
case EMU_CUSEEME:
|
||||
|
||||
|
||||
/*
|
||||
* Cu-SeeMe emulation.
|
||||
* Hopefully the packet is more that 16 bytes long. We don't
|
||||
* do any other tests, just replace the address and port
|
||||
* fields.
|
||||
*/
|
||||
*/
|
||||
if (m->m_len >= sizeof (*cu_head)) {
|
||||
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
||||
return;
|
||||
|
@ -620,7 +625,7 @@ struct cu_header {
|
|||
cu_head->s_port = addr.sin_port;
|
||||
cu_head->so_addr = our_addr.s_addr;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -634,9 +639,8 @@ udp_listen(port, laddr, lport, flags)
|
|||
{
|
||||
struct sockaddr_in addr;
|
||||
struct socket *so;
|
||||
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||
int opt = 1;
|
||||
|
||||
int addrlen = sizeof(struct sockaddr_in), opt = 1;
|
||||
|
||||
if ((so = socreate()) == NULL) {
|
||||
free(so);
|
||||
return NULL;
|
||||
|
@ -645,7 +649,6 @@ udp_listen(port, laddr, lport, flags)
|
|||
so->so_expire = curtime + SO_EXPIRE;
|
||||
insque(so,&udb);
|
||||
|
||||
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
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_OOBINLINE,(char *)&opt,sizeof(int)); */
|
||||
|
||||
|
||||
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
||||
so->so_fport = addr.sin_port;
|
||||
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
|
||||
so->so_faddr = alias_addr;
|
||||
else
|
||||
so->so_faddr = addr.sin_addr;
|
||||
|
||||
|
||||
so->so_lport = lport;
|
||||
so->so_laddr.s_addr = laddr;
|
||||
if (flags != SS_FACCEPTONCE)
|
||||
so->so_expire = 0;
|
||||
|
||||
|
||||
so->so_state = SS_ISFCONNECTED;
|
||||
|
||||
|
||||
return so;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* 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
|
||||
* without specific prior written permission.
|
||||
*
|
||||
|
@ -42,20 +46,12 @@ extern struct socket *udp_last_so;
|
|||
* Udp protocol header.
|
||||
* Per RFC 768, September, 1981.
|
||||
*/
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct udphdr {
|
||||
u_int16_t uh_sport; /* source port */
|
||||
u_int16_t uh_dport; /* destination port */
|
||||
int16_t uh_ulen; /* udp length */
|
||||
u_int16_t uh_sum; /* udp checksum */
|
||||
} PACKED__;
|
||||
|
||||
#ifdef PRAGMA_PACK_SUPPORTED
|
||||
#pragma pack(PACK_RESET)
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* UDP kernel structures and variables.
|
||||
|
@ -76,6 +72,7 @@ struct udpiphdr {
|
|||
#define ui_ulen ui_u.uh_ulen
|
||||
#define ui_sum ui_u.uh_sum
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
struct udpstat {
|
||||
/* input statistics: */
|
||||
u_long udps_ipackets; /* total input packets */
|
||||
|
@ -89,6 +86,7 @@ struct udpstat {
|
|||
/* output statistics: */
|
||||
u_long udps_opackets; /* total output packets */
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Names for UDP sysctl objects
|
||||
|
@ -96,19 +94,20 @@ struct udpstat {
|
|||
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
|
||||
#define UDPCTL_MAXID 2
|
||||
|
||||
#ifdef LOG_ENABLED
|
||||
extern struct udpstat udpstat;
|
||||
#endif
|
||||
|
||||
extern struct socket udb;
|
||||
struct mbuf;
|
||||
|
||||
void udp_init(void);
|
||||
void udp_input(register struct mbuf *, int);
|
||||
int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);
|
||||
int udp_attach(struct socket *);
|
||||
void udp_detach(struct socket *);
|
||||
u_int8_t udp_tos(struct socket *);
|
||||
void udp_emu(struct socket *, struct mbuf *);
|
||||
struct socket * udp_listen(u_int, u_int32_t, u_int, int);
|
||||
int udp_output2(struct socket *so, struct mbuf *m,
|
||||
void udp_init _P((void));
|
||||
void udp_input _P((register struct mbuf *, int));
|
||||
int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
|
||||
int udp_attach _P((struct socket *));
|
||||
void udp_detach _P((struct socket *));
|
||||
struct socket * udp_listen _P((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,
|
||||
int iptos);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue