mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-12 04:29:29 +00:00
parent
c20d9d3c52
commit
605c811a4a
|
@ -16,7 +16,7 @@ The copyright terms and conditions:
|
||||||
---BEGIN---
|
---BEGIN---
|
||||||
|
|
||||||
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
|
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions
|
modification, are permitted provided that the following conditions
|
||||||
are met:
|
are met:
|
||||||
|
@ -25,9 +25,6 @@ The copyright terms and conditions:
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
notice, this list of conditions and the following disclaimer in the
|
notice, this list of conditions and the following disclaimer in the
|
||||||
documentation and/or other materials provided with the distribution.
|
documentation and/or other materials provided with the distribution.
|
||||||
3. All advertising materials mentioning features or use of this software
|
|
||||||
must display the following acknowledgment:
|
|
||||||
This product includes software developed by Danny Gasparovski.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* QEMU BOOTP/DHCP server
|
* QEMU BOOTP/DHCP server
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004 Fabrice Bellard
|
* Copyright (c) 2004 Fabrice Bellard
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
@ -38,17 +38,8 @@ typedef struct {
|
||||||
|
|
||||||
BOOTPClient bootp_clients[NB_ADDR];
|
BOOTPClient bootp_clients[NB_ADDR];
|
||||||
|
|
||||||
const char *bootp_filename;
|
|
||||||
|
|
||||||
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
|
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define dprintf(fmt, args...) \
|
|
||||||
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
|
|
||||||
#else
|
|
||||||
#define dprintf(fmt, args...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static BOOTPClient *get_new_addr(struct in_addr *paddr)
|
static BOOTPClient *get_new_addr(struct in_addr *paddr)
|
||||||
{
|
{
|
||||||
BOOTPClient *bc;
|
BOOTPClient *bc;
|
||||||
|
@ -89,7 +80,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
||||||
const uint8_t *p, *p_end;
|
const uint8_t *p, *p_end;
|
||||||
int len, tag;
|
int len, tag;
|
||||||
|
|
||||||
*pmsg_type = 0;
|
*pmsg_type = 0;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
p_end = buf + size;
|
p_end = buf + size;
|
||||||
|
@ -101,7 +92,7 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
||||||
while (p < p_end) {
|
while (p < p_end) {
|
||||||
tag = p[0];
|
tag = p[0];
|
||||||
if (tag == RFC1533_PAD) {
|
if (tag == RFC1533_PAD) {
|
||||||
p++;
|
p++;
|
||||||
} else if (tag == RFC1533_END) {
|
} else if (tag == RFC1533_END) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,7 +100,6 @@ static void dhcp_decode(const uint8_t *buf, int size,
|
||||||
if (p >= p_end)
|
if (p >= p_end)
|
||||||
break;
|
break;
|
||||||
len = *p++;
|
len = *p++;
|
||||||
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
|
|
||||||
|
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case RFC2132_MSG_TYPE:
|
case RFC2132_MSG_TYPE:
|
||||||
|
@ -136,20 +126,19 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
|
|
||||||
/* extract exact DHCP msg type */
|
/* extract exact DHCP msg type */
|
||||||
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
|
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
|
||||||
dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
|
|
||||||
|
|
||||||
if (dhcp_msg_type == 0)
|
if (dhcp_msg_type == 0)
|
||||||
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
|
dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
|
||||||
|
|
||||||
if (dhcp_msg_type != DHCPDISCOVER &&
|
if (dhcp_msg_type != DHCPDISCOVER &&
|
||||||
dhcp_msg_type != DHCPREQUEST)
|
dhcp_msg_type != DHCPREQUEST)
|
||||||
return;
|
return;
|
||||||
/* XXX: this is a hack to get the client mac address */
|
/* XXX: this is a hack to get the client mac address */
|
||||||
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
|
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
|
||||||
|
|
||||||
if ((m = m_get()) == NULL)
|
if ((m = m_get()) == NULL)
|
||||||
return;
|
return;
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
rbp = (struct bootp_t *)m->m_data;
|
rbp = (struct bootp_t *)m->m_data;
|
||||||
m->m_data += sizeof(struct udpiphdr);
|
m->m_data += sizeof(struct udpiphdr);
|
||||||
memset(rbp, 0, sizeof(struct bootp_t));
|
memset(rbp, 0, sizeof(struct bootp_t));
|
||||||
|
@ -157,10 +146,8 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
if (dhcp_msg_type == DHCPDISCOVER) {
|
if (dhcp_msg_type == DHCPDISCOVER) {
|
||||||
new_addr:
|
new_addr:
|
||||||
bc = get_new_addr(&daddr.sin_addr);
|
bc = get_new_addr(&daddr.sin_addr);
|
||||||
if (!bc) {
|
if (!bc)
|
||||||
dprintf("no address left\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
memcpy(bc->macaddr, client_ethaddr, 6);
|
memcpy(bc->macaddr, client_ethaddr, 6);
|
||||||
} else {
|
} else {
|
||||||
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
|
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
|
||||||
|
@ -171,11 +158,6 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bootp_filename)
|
|
||||||
snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename);
|
|
||||||
|
|
||||||
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
|
|
||||||
|
|
||||||
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
|
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
|
||||||
saddr.sin_port = htons(BOOTP_SERVER);
|
saddr.sin_port = htons(BOOTP_SERVER);
|
||||||
|
|
||||||
|
@ -203,7 +185,7 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
*q++ = 1;
|
*q++ = 1;
|
||||||
*q++ = DHCPACK;
|
*q++ = DHCPACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dhcp_msg_type == DHCPDISCOVER ||
|
if (dhcp_msg_type == DHCPDISCOVER ||
|
||||||
dhcp_msg_type == DHCPREQUEST) {
|
dhcp_msg_type == DHCPREQUEST) {
|
||||||
*q++ = RFC2132_SRV_ID;
|
*q++ = RFC2132_SRV_ID;
|
||||||
|
@ -217,12 +199,12 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
*q++ = 0xff;
|
*q++ = 0xff;
|
||||||
*q++ = 0xff;
|
*q++ = 0xff;
|
||||||
*q++ = 0x00;
|
*q++ = 0x00;
|
||||||
|
|
||||||
*q++ = RFC1533_GATEWAY;
|
*q++ = RFC1533_GATEWAY;
|
||||||
*q++ = 4;
|
*q++ = 4;
|
||||||
memcpy(q, &saddr.sin_addr, 4);
|
memcpy(q, &saddr.sin_addr, 4);
|
||||||
q += 4;
|
q += 4;
|
||||||
|
|
||||||
*q++ = RFC1533_DNS;
|
*q++ = RFC1533_DNS;
|
||||||
*q++ = 4;
|
*q++ = 4;
|
||||||
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
|
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
|
||||||
|
@ -244,8 +226,8 @@ static void bootp_reply(struct bootp_t *bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*q++ = RFC1533_END;
|
*q++ = RFC1533_END;
|
||||||
|
|
||||||
m->m_len = sizeof(struct bootp_t) -
|
m->m_len = sizeof(struct bootp_t) -
|
||||||
sizeof(struct ip) - sizeof(struct udphdr);
|
sizeof(struct ip) - sizeof(struct udphdr);
|
||||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,10 @@
|
||||||
#define BOOTP_VENDOR_LEN 64
|
#define BOOTP_VENDOR_LEN 64
|
||||||
#define DHCP_OPT_LEN 312
|
#define DHCP_OPT_LEN 312
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct bootp_t {
|
struct bootp_t {
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct udphdr udp;
|
struct udphdr udp;
|
||||||
|
@ -108,6 +112,10 @@ struct bootp_t {
|
||||||
uint8_t bp_sname[64];
|
uint8_t bp_sname[64];
|
||||||
uint8_t bp_file[128];
|
uint8_t bp_file[128];
|
||||||
uint8_t bp_vend[DHCP_OPT_LEN];
|
uint8_t bp_vend[DHCP_OPT_LEN];
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
void bootp_input(struct mbuf *m);
|
void bootp_input(struct mbuf *m);
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -41,7 +37,7 @@
|
||||||
*
|
*
|
||||||
* This routine is very heavily used in the network
|
* This routine is very heavily used in the network
|
||||||
* code and should be modified for each CPU to be as fast as possible.
|
* code and should be modified for each CPU to be as fast as possible.
|
||||||
*
|
*
|
||||||
* XXX Since we will never span more than 1 mbuf, we can optimise this
|
* XXX Since we will never span more than 1 mbuf, we can optimise this
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -63,13 +59,13 @@ int cksum(struct mbuf *m, int len)
|
||||||
u_int16_t s[2];
|
u_int16_t s[2];
|
||||||
u_int32_t l;
|
u_int32_t l;
|
||||||
} l_util;
|
} l_util;
|
||||||
|
|
||||||
if (m->m_len == 0)
|
if (m->m_len == 0)
|
||||||
goto cont;
|
goto cont;
|
||||||
w = mtod(m, u_int16_t *);
|
w = mtod(m, u_int16_t *);
|
||||||
|
|
||||||
mlen = m->m_len;
|
mlen = m->m_len;
|
||||||
|
|
||||||
if (len < mlen)
|
if (len < mlen)
|
||||||
mlen = len;
|
mlen = len;
|
||||||
len -= mlen;
|
len -= mlen;
|
||||||
|
@ -107,7 +103,7 @@ int cksum(struct mbuf *m, int len)
|
||||||
while ((mlen -= 2) >= 0) {
|
while ((mlen -= 2) >= 0) {
|
||||||
sum += *w++;
|
sum += *w++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (byte_swapped) {
|
if (byte_swapped) {
|
||||||
REDUCE;
|
REDUCE;
|
||||||
sum <<= 8;
|
sum <<= 8;
|
||||||
|
@ -117,11 +113,11 @@ int cksum(struct mbuf *m, int len)
|
||||||
sum += s_util.s;
|
sum += s_util.s;
|
||||||
mlen = 0;
|
mlen = 0;
|
||||||
} else
|
} else
|
||||||
|
|
||||||
mlen = -1;
|
mlen = -1;
|
||||||
} else if (mlen == -1)
|
} else if (mlen == -1)
|
||||||
s_util.c[0] = *(u_int8_t *)w;
|
s_util.c[0] = *(u_int8_t *)w;
|
||||||
|
|
||||||
cont:
|
cont:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (len) {
|
if (len) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
* Portions copyright (c) 2000 Kelly Price.
|
* Portions copyright (c) 2000 Kelly Price.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -16,11 +16,8 @@ int dostats = 0;
|
||||||
#endif
|
#endif
|
||||||
int slirp_debug = 0;
|
int slirp_debug = 0;
|
||||||
|
|
||||||
extern char *strerror _P((int));
|
/* Carry over one item from main.c so that the tty's restored.
|
||||||
|
|
||||||
/* Carry over one item from main.c so that the tty's restored.
|
|
||||||
* Only done when the tty being used is /dev/tty --RedWolf */
|
* Only done when the tty being used is /dev/tty --RedWolf */
|
||||||
#ifndef CONFIG_QEMU
|
|
||||||
extern struct termios slirp_tty_settings;
|
extern struct termios slirp_tty_settings;
|
||||||
extern int slirp_tty_restore;
|
extern int slirp_tty_restore;
|
||||||
|
|
||||||
|
@ -33,7 +30,7 @@ debug_init(file, dbg)
|
||||||
/* Close the old debugging file */
|
/* Close the old debugging file */
|
||||||
if (dfd)
|
if (dfd)
|
||||||
fclose(dfd);
|
fclose(dfd);
|
||||||
|
|
||||||
dfd = fopen(file,"w");
|
dfd = fopen(file,"w");
|
||||||
if (dfd != NULL) {
|
if (dfd != NULL) {
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -59,7 +56,7 @@ dump_packet(dat, n)
|
||||||
{
|
{
|
||||||
u_char *pptr = (u_char *)dat;
|
u_char *pptr = (u_char *)dat;
|
||||||
int j,k;
|
int j,k;
|
||||||
|
|
||||||
n /= 16;
|
n /= 16;
|
||||||
n++;
|
n++;
|
||||||
DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
|
DEBUG_MISC((dfd, "PACKET DUMPED: \n"));
|
||||||
|
@ -71,30 +68,28 @@ dump_packet(dat, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Statistic routines
|
* Statistic routines
|
||||||
*
|
*
|
||||||
* These will print statistics to the screen, the debug file (dfd), or
|
* These will print statistics to the screen, the debug file (dfd), or
|
||||||
* a buffer, depending on "type", so that the stats can be sent over
|
* a buffer, depending on "type", so that the stats can be sent over
|
||||||
* the link as well.
|
* the link as well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
ttystats(ttyp)
|
ttystats(ttyp)
|
||||||
struct ttys *ttyp;
|
struct ttys *ttyp;
|
||||||
{
|
{
|
||||||
struct slirp_ifstats *is = &ttyp->ifstats;
|
struct slirp_ifstats *is = &ttyp->ifstats;
|
||||||
char buff[512];
|
char buff[512];
|
||||||
|
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
if (IF_COMP & IF_COMPRESS)
|
if (if_comp & IF_COMPRESS)
|
||||||
strcpy(buff, "on");
|
strcpy(buff, "on");
|
||||||
else if (IF_COMP & IF_NOCOMPRESS)
|
else if (if_comp & IF_NOCOMPRESS)
|
||||||
strcpy(buff, "off");
|
strcpy(buff, "off");
|
||||||
else
|
else
|
||||||
strcpy(buff, "off (for now)");
|
strcpy(buff, "off (for now)");
|
||||||
|
@ -122,20 +117,20 @@ ttystats(ttyp)
|
||||||
lprint(" %6d bad input packets\r\n", is->in_mbad);
|
lprint(" %6d bad input packets\r\n", is->in_mbad);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
allttystats(void)
|
allttystats()
|
||||||
{
|
{
|
||||||
struct ttys *ttyp;
|
struct ttys *ttyp;
|
||||||
|
|
||||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||||
ttystats(ttyp);
|
ttystats(ttyp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
void
|
||||||
ipstats(void)
|
ipstats()
|
||||||
{
|
{
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
lprint("IP stats:\r\n");
|
lprint("IP stats:\r\n");
|
||||||
lprint(" %6d total packets received (%d were unaligned)\r\n",
|
lprint(" %6d total packets received (%d were unaligned)\r\n",
|
||||||
|
@ -156,14 +151,14 @@ ipstats(void)
|
||||||
lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
|
lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_QEMU
|
#if 0
|
||||||
static void
|
void
|
||||||
vjstats(void)
|
vjstats()
|
||||||
{
|
{
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
lprint("VJ compression stats:\r\n");
|
lprint("VJ compression stats:\r\n");
|
||||||
|
|
||||||
lprint(" %6d outbound packets (%d compressed)\r\n",
|
lprint(" %6d outbound packets (%d compressed)\r\n",
|
||||||
comp_s.sls_packets, comp_s.sls_compressed);
|
comp_s.sls_packets, comp_s.sls_compressed);
|
||||||
lprint(" %6d searches for connection stats (%d misses)\r\n",
|
lprint(" %6d searches for connection stats (%d misses)\r\n",
|
||||||
|
@ -175,13 +170,13 @@ vjstats(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
void
|
||||||
tcpstats(void)
|
tcpstats()
|
||||||
{
|
{
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
lprint("TCP stats:\r\n");
|
lprint("TCP stats:\r\n");
|
||||||
|
|
||||||
lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
|
lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal);
|
||||||
lprint(" %6d data packets (%d bytes)\r\n",
|
lprint(" %6d data packets (%d bytes)\r\n",
|
||||||
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
|
tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte);
|
||||||
|
@ -194,8 +189,8 @@ tcpstats(void)
|
||||||
lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
|
lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup);
|
||||||
lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
|
lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl);
|
||||||
lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
|
lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin);
|
||||||
|
|
||||||
lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
|
lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal);
|
||||||
lprint(" %6d acks (for %d bytes)\r\n",
|
lprint(" %6d acks (for %d bytes)\r\n",
|
||||||
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
|
tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte);
|
||||||
lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
|
lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack);
|
||||||
|
@ -204,7 +199,7 @@ tcpstats(void)
|
||||||
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
|
tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte);
|
||||||
lprint(" %6d completely duplicate packets (%d bytes)\r\n",
|
lprint(" %6d completely duplicate packets (%d bytes)\r\n",
|
||||||
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
|
tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte);
|
||||||
|
|
||||||
lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
|
lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n",
|
||||||
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
|
tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte);
|
||||||
lprint(" %6d out-of-order packets (%d bytes)\r\n",
|
lprint(" %6d out-of-order packets (%d bytes)\r\n",
|
||||||
|
@ -217,7 +212,7 @@ tcpstats(void)
|
||||||
lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
|
lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum);
|
||||||
lprint(" %6d discarded for bad header offset fields\r\n",
|
lprint(" %6d discarded for bad header offset fields\r\n",
|
||||||
tcpstat.tcps_rcvbadoff);
|
tcpstat.tcps_rcvbadoff);
|
||||||
|
|
||||||
lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
|
lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt);
|
||||||
lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
|
lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts);
|
||||||
lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
|
lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects);
|
||||||
|
@ -236,15 +231,15 @@ tcpstats(void)
|
||||||
lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
|
lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack);
|
||||||
lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
|
lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat);
|
||||||
lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
|
lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss);
|
||||||
|
|
||||||
|
|
||||||
/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
|
/* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */
|
||||||
/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
|
/* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
udpstats(void)
|
udpstats()
|
||||||
{
|
{
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
|
@ -257,8 +252,8 @@ udpstats(void)
|
||||||
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
|
lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
icmpstats(void)
|
icmpstats()
|
||||||
{
|
{
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
lprint("ICMP stats:\r\n");
|
lprint("ICMP stats:\r\n");
|
||||||
|
@ -270,23 +265,23 @@ icmpstats(void)
|
||||||
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
|
lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
mbufstats(void)
|
mbufstats()
|
||||||
{
|
{
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
lprint("Mbuf stats:\r\n");
|
lprint("Mbuf stats:\r\n");
|
||||||
|
|
||||||
lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
|
lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
|
for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next)
|
||||||
i++;
|
i++;
|
||||||
lprint(" %6d mbufs on free list\r\n", i);
|
lprint(" %6d mbufs on free list\r\n", i);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
|
for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next)
|
||||||
i++;
|
i++;
|
||||||
|
@ -294,55 +289,59 @@ mbufstats(void)
|
||||||
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
|
lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
sockstats(void)
|
sockstats()
|
||||||
{
|
{
|
||||||
|
char addr[INET_ADDRSTRLEN];
|
||||||
char buff[256];
|
char buff[256];
|
||||||
int n;
|
int n;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
lprint(" \r\n");
|
lprint(" \r\n");
|
||||||
|
|
||||||
lprint(
|
lprint(
|
||||||
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n");
|
"Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n");
|
||||||
|
|
||||||
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
|
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
|
||||||
|
|
||||||
n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
|
n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
|
||||||
while (n < 17)
|
while (n < 17)
|
||||||
buff[n++] = ' ';
|
buff[n++] = ' ';
|
||||||
buff[17] = 0;
|
buff[17] = 0;
|
||||||
lprint("%s %3d %15s %5d ",
|
lprint("%s %3d %15s %5d ",
|
||||||
buff, so->s,
|
buff, so->s,
|
||||||
inet_ntoa(so->so_laddr), ntohs(so->so_lport));
|
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)),
|
||||||
|
ntohs(so->so_lport));
|
||||||
lprint("%15s %5d %5d %5d\r\n",
|
lprint("%15s %5d %5d %5d\r\n",
|
||||||
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
|
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)),
|
||||||
|
ntohs(so->so_fport),
|
||||||
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (so = udb.so_next; so != &udb; so = so->so_next) {
|
for (so = udb.so_next; so != &udb; so = so->so_next) {
|
||||||
|
|
||||||
n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
|
n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
|
||||||
while (n < 17)
|
while (n < 17)
|
||||||
buff[n++] = ' ';
|
buff[n++] = ' ';
|
||||||
buff[17] = 0;
|
buff[17] = 0;
|
||||||
lprint("%s %3d %15s %5d ",
|
lprint("%s %3d %15s %5d ",
|
||||||
buff, so->s,
|
buff, so->s,
|
||||||
inet_ntoa(so->so_laddr), ntohs(so->so_lport));
|
inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)),
|
||||||
|
ntohs(so->so_lport));
|
||||||
lprint("%15s %5d %5d %5d\r\n",
|
lprint("%15s %5d %5d %5d\r\n",
|
||||||
inet_ntoa(so->so_faddr), ntohs(so->so_fport),
|
inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)),
|
||||||
|
ntohs(so->so_fport),
|
||||||
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
so->so_rcv.sb_cc, so->so_snd.sb_cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_QEMU
|
#if 0
|
||||||
void
|
void
|
||||||
slirp_exit(exit_status)
|
slirp_exit(exit_status)
|
||||||
int exit_status;
|
int exit_status;
|
||||||
{
|
{
|
||||||
struct ttys *ttyp;
|
struct ttys *ttyp;
|
||||||
|
|
||||||
DEBUG_CALL("slirp_exit");
|
DEBUG_CALL("slirp_exit");
|
||||||
DEBUG_ARG("exit_status = %d", exit_status);
|
DEBUG_ARG("exit_status = %d", exit_status);
|
||||||
|
|
||||||
|
@ -351,7 +350,7 @@ slirp_exit(exit_status)
|
||||||
if (!dfd)
|
if (!dfd)
|
||||||
debug_init("slirp_stats", 0xf);
|
debug_init("slirp_stats", 0xf);
|
||||||
lprint_arg = (char **)&dfd;
|
lprint_arg = (char **)&dfd;
|
||||||
|
|
||||||
ipstats();
|
ipstats();
|
||||||
tcpstats();
|
tcpstats();
|
||||||
udpstats();
|
udpstats();
|
||||||
|
@ -361,35 +360,20 @@ slirp_exit(exit_status)
|
||||||
allttystats();
|
allttystats();
|
||||||
vjstats();
|
vjstats();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
for (ttyp = ttys; ttyp; ttyp = ttyp->next)
|
||||||
tty_detached(ttyp, 1);
|
tty_detached(ttyp, 1);
|
||||||
|
|
||||||
if (slirp_forked) {
|
if (slirp_forked) {
|
||||||
/* Menendez time */
|
/* Menendez time */
|
||||||
if (kill(getppid(), SIGQUIT) < 0)
|
if (kill(getppid(), SIGQUIT) < 0)
|
||||||
lprint("Couldn't kill parent process %ld!\n",
|
lprint("Couldn't kill parent process %ld!\n",
|
||||||
(long) getppid());
|
(long) getppid());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore the terminal if we gotta */
|
/* Restore the terminal if we gotta */
|
||||||
if(slirp_tty_restore)
|
if(slirp_tty_restore)
|
||||||
tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
|
tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */
|
||||||
exit(exit_status);
|
exit(exit_status);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
|
||||||
slirp_stats(void)
|
|
||||||
{
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
ipstats();
|
|
||||||
tcpstats();
|
|
||||||
udpstats();
|
|
||||||
icmpstats();
|
|
||||||
mbufstats();
|
|
||||||
sockstats();
|
|
||||||
#else
|
|
||||||
lprint("SLIRP statistics code not compiled.\n");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -36,5 +36,15 @@ extern int slirp_debug;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void debug_init _P((char *, int));
|
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);
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -64,8 +60,6 @@ struct icmpstat {
|
||||||
{ "stats", CTLTYPE_STRUCT }, \
|
{ "stats", CTLTYPE_STRUCT }, \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
extern struct icmpstat icmpstat;
|
extern struct icmpstat icmpstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,7 +7,12 @@
|
||||||
|
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
int if_queued = 0; /* Number of packets queued so far */
|
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) */
|
||||||
|
|
||||||
struct mbuf if_fastq; /* fast queue (for interactive data) */
|
struct mbuf if_fastq; /* fast queue (for interactive data) */
|
||||||
struct mbuf if_batchq; /* queue for non-interactive data */
|
struct mbuf if_batchq; /* queue for non-interactive data */
|
||||||
|
@ -36,6 +41,23 @@ ifs_remque(ifm)
|
||||||
void
|
void
|
||||||
if_init()
|
if_init()
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
|
||||||
|
* and 8 bytes for PPP, but need to have it on an 8byte boundary
|
||||||
|
*/
|
||||||
|
#ifdef USE_PPP
|
||||||
|
if_maxlinkhdr = 48;
|
||||||
|
#else
|
||||||
|
if_maxlinkhdr = 40;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
|
||||||
|
if_maxlinkhdr = 2 + 14 + 40;
|
||||||
|
#endif
|
||||||
|
if_mtu = 1500;
|
||||||
|
if_mru = 1500;
|
||||||
|
if_comp = IF_AUTOCOMP;
|
||||||
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
|
if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq;
|
||||||
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
|
if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq;
|
||||||
// sl_compress_init(&comp_s);
|
// sl_compress_init(&comp_s);
|
||||||
|
@ -55,12 +77,12 @@ writen(fd, bptr, n)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int total;
|
int total;
|
||||||
|
|
||||||
/* This should succeed most of the time */
|
/* This should succeed most of the time */
|
||||||
ret = send(fd, bptr, n,0);
|
ret = send(fd, bptr, n,0);
|
||||||
if (ret == n || ret <= 0)
|
if (ret == n || ret <= 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Didn't write everything, go into the loop */
|
/* Didn't write everything, go into the loop */
|
||||||
total = ret;
|
total = ret;
|
||||||
while (n > total) {
|
while (n > total) {
|
||||||
|
@ -75,7 +97,7 @@ writen(fd, bptr, n)
|
||||||
/*
|
/*
|
||||||
* if_input - read() the tty, do "top level" processing (ie: check for any escapes),
|
* if_input - read() the tty, do "top level" processing (ie: check for any escapes),
|
||||||
* and pass onto (*ttyp->if_input)
|
* and pass onto (*ttyp->if_input)
|
||||||
*
|
*
|
||||||
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
|
* XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
|
||||||
*/
|
*/
|
||||||
#define INBUFF_SIZE 2048 /* XXX */
|
#define INBUFF_SIZE 2048 /* XXX */
|
||||||
|
@ -85,16 +107,17 @@ if_input(ttyp)
|
||||||
{
|
{
|
||||||
u_char if_inbuff[INBUFF_SIZE];
|
u_char if_inbuff[INBUFF_SIZE];
|
||||||
int if_n;
|
int if_n;
|
||||||
|
|
||||||
DEBUG_CALL("if_input");
|
DEBUG_CALL("if_input");
|
||||||
DEBUG_ARG("ttyp = %lx", (long)ttyp);
|
DEBUG_ARG("ttyp = %lx", (long)ttyp);
|
||||||
|
|
||||||
if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
|
if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0);
|
||||||
|
|
||||||
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
|
DEBUG_MISC((dfd, " read %d bytes\n", if_n));
|
||||||
|
|
||||||
if (if_n <= 0) {
|
if (if_n <= 0) {
|
||||||
if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
|
int error = WSAGetLastError();
|
||||||
|
if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) {
|
||||||
if (ttyp->up)
|
if (ttyp->up)
|
||||||
link_up--;
|
link_up--;
|
||||||
tty_detached(ttyp, 0);
|
tty_detached(ttyp, 0);
|
||||||
|
@ -116,19 +139,19 @@ if_input(ttyp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ttyp->ones = ttyp->zeros = 0;
|
ttyp->ones = ttyp->zeros = 0;
|
||||||
|
|
||||||
(*ttyp->if_input)(ttyp, if_inbuff, if_n);
|
(*ttyp->if_input)(ttyp, if_inbuff, if_n);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if_output: Queue packet into an output queue.
|
* if_output: Queue packet into an output queue.
|
||||||
* There are 2 output queue's, if_fastq and if_batchq.
|
* There are 2 output queue's, if_fastq and if_batchq.
|
||||||
* Each output queue is a doubly linked list of double linked lists
|
* Each output queue is a doubly linked list of double linked lists
|
||||||
* of mbufs, each list belonging to one "session" (socket). This
|
* of mbufs, each list belonging to one "session" (socket). This
|
||||||
* way, we can output packets fairly by sending one packet from each
|
* way, we can output packets fairly by sending one packet from each
|
||||||
* session, instead of all the packets from one session, then all packets
|
* session, instead of all the packets from one session, then all packets
|
||||||
* from the next session, etc. Packets on the if_fastq get absolute
|
* from the next session, etc. Packets on the if_fastq get absolute
|
||||||
* priority, but if one session hogs the link, it gets "downgraded"
|
* priority, but if one session hogs the link, it gets "downgraded"
|
||||||
* to the batchq until it runs out of packets, then it'll return
|
* to the batchq until it runs out of packets, then it'll return
|
||||||
* to the fastq (eg. if the user does an ls -alR in a telnet session,
|
* to the fastq (eg. if the user does an ls -alR in a telnet session,
|
||||||
|
@ -141,11 +164,11 @@ if_output(so, ifm)
|
||||||
{
|
{
|
||||||
struct mbuf *ifq;
|
struct mbuf *ifq;
|
||||||
int on_fastq = 1;
|
int on_fastq = 1;
|
||||||
|
|
||||||
DEBUG_CALL("if_output");
|
DEBUG_CALL("if_output");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("ifm = %lx", (long)ifm);
|
DEBUG_ARG("ifm = %lx", (long)ifm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First remove the mbuf from m_usedlist,
|
* First remove the mbuf from m_usedlist,
|
||||||
* since we're gonna use m_next and m_prev ourselves
|
* since we're gonna use m_next and m_prev ourselves
|
||||||
|
@ -155,9 +178,9 @@ if_output(so, ifm)
|
||||||
remque(ifm);
|
remque(ifm);
|
||||||
ifm->m_flags &= ~M_USEDLIST;
|
ifm->m_flags &= ~M_USEDLIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if there's already a batchq list for this session.
|
* See if there's already a batchq list for this session.
|
||||||
* This can include an interactive session, which should go on fastq,
|
* This can include an interactive session, which should go on fastq,
|
||||||
* but gets too greedy... hence it'll be downgraded from fastq to batchq.
|
* but gets too greedy... hence it'll be downgraded from fastq to batchq.
|
||||||
* We mustn't put this packet back on the fastq (or we'll send it out of order)
|
* We mustn't put this packet back on the fastq (or we'll send it out of order)
|
||||||
|
@ -171,7 +194,7 @@ if_output(so, ifm)
|
||||||
goto diddit;
|
goto diddit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No match, check which queue to put it on */
|
/* No match, check which queue to put it on */
|
||||||
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
|
if (so && (so->so_iptos & IPTOS_LOWDELAY)) {
|
||||||
ifq = if_fastq.ifq_prev;
|
ifq = if_fastq.ifq_prev;
|
||||||
|
@ -187,15 +210,15 @@ if_output(so, ifm)
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
ifq = if_batchq.ifq_prev;
|
ifq = if_batchq.ifq_prev;
|
||||||
|
|
||||||
/* Create a new doubly linked list for this session */
|
/* Create a new doubly linked list for this session */
|
||||||
ifm->ifq_so = so;
|
ifm->ifq_so = so;
|
||||||
ifs_init(ifm);
|
ifs_init(ifm);
|
||||||
insque(ifm, ifq);
|
insque(ifm, ifq);
|
||||||
|
|
||||||
diddit:
|
diddit:
|
||||||
++if_queued;
|
++if_queued;
|
||||||
|
|
||||||
if (so) {
|
if (so) {
|
||||||
/* Update *_queued */
|
/* Update *_queued */
|
||||||
so->so_queued++;
|
so->so_queued++;
|
||||||
|
@ -207,12 +230,12 @@ diddit:
|
||||||
* have been sent over the link
|
* have been sent over the link
|
||||||
* (XXX These are arbitrary numbers, probably not optimal..)
|
* (XXX These are arbitrary numbers, probably not optimal..)
|
||||||
*/
|
*/
|
||||||
if (on_fastq && ((so->so_nqueued >= 6) &&
|
if (on_fastq && ((so->so_nqueued >= 6) &&
|
||||||
(so->so_nqueued - so->so_queued) >= 3)) {
|
(so->so_nqueued - so->so_queued) >= 3)) {
|
||||||
|
|
||||||
/* Remove from current queue... */
|
/* Remove from current queue... */
|
||||||
remque(ifm->ifs_next);
|
remque(ifm->ifs_next);
|
||||||
|
|
||||||
/* ...And insert in the new. That'll teach ya! */
|
/* ...And insert in the new. That'll teach ya! */
|
||||||
insque(ifm->ifs_next, &if_batchq);
|
insque(ifm->ifs_next, &if_batchq);
|
||||||
}
|
}
|
||||||
|
@ -245,16 +268,16 @@ void
|
||||||
if_start(void)
|
if_start(void)
|
||||||
{
|
{
|
||||||
struct mbuf *ifm, *ifqt;
|
struct mbuf *ifm, *ifqt;
|
||||||
|
|
||||||
DEBUG_CALL("if_start");
|
DEBUG_CALL("if_start");
|
||||||
|
|
||||||
if (if_queued == 0)
|
if (if_queued == 0)
|
||||||
return; /* Nothing to do */
|
return; /* Nothing to do */
|
||||||
|
|
||||||
again:
|
again:
|
||||||
/* check if we can really output */
|
/* check if we can really output */
|
||||||
if (!slirp_can_output())
|
if (!slirp_can_output())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See which queue to get next packet from
|
* See which queue to get next packet from
|
||||||
|
@ -268,7 +291,7 @@ if_start(void)
|
||||||
ifm = next_m;
|
ifm = next_m;
|
||||||
else
|
else
|
||||||
ifm = if_batchq.ifq_next;
|
ifm = if_batchq.ifq_next;
|
||||||
|
|
||||||
/* Set which packet to send on next iteration */
|
/* Set which packet to send on next iteration */
|
||||||
next_m = ifm->ifq_next;
|
next_m = ifm->ifq_next;
|
||||||
}
|
}
|
||||||
|
@ -276,24 +299,24 @@ if_start(void)
|
||||||
ifqt = ifm->ifq_prev;
|
ifqt = ifm->ifq_prev;
|
||||||
remque(ifm);
|
remque(ifm);
|
||||||
--if_queued;
|
--if_queued;
|
||||||
|
|
||||||
/* If there are more packets for this session, re-queue them */
|
/* If there are more packets for this session, re-queue them */
|
||||||
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
|
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
|
||||||
insque(ifm->ifs_next, ifqt);
|
insque(ifm->ifs_next, ifqt);
|
||||||
ifs_remque(ifm);
|
ifs_remque(ifm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update so_queued */
|
/* Update so_queued */
|
||||||
if (ifm->ifq_so) {
|
if (ifm->ifq_so) {
|
||||||
if (--ifm->ifq_so->so_queued == 0)
|
if (--ifm->ifq_so->so_queued == 0)
|
||||||
/* If there's no more queued, reset nqueued */
|
/* If there's no more queued, reset nqueued */
|
||||||
ifm->ifq_so->so_nqueued = 0;
|
ifm->ifq_so->so_nqueued = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encapsulate the packet for sending */
|
/* Encapsulate the packet for sending */
|
||||||
if_encap(ifm->m_data, ifm->m_len);
|
if_encap((uint8_t*)ifm->m_data, ifm->m_len);
|
||||||
|
|
||||||
m_free(ifm);
|
m_free(ifm);
|
||||||
|
|
||||||
if (if_queued)
|
if (if_queued)
|
||||||
goto again;
|
goto again;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -13,26 +13,15 @@
|
||||||
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
#define IF_AUTOCOMP 0x04 /* Autodetect (default) */
|
||||||
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
#define IF_NOCIDCOMP 0x08 /* CID compression */
|
||||||
|
|
||||||
#define IF_MTU 1500
|
/* Needed for FreeBSD */
|
||||||
#define IF_MRU 1500
|
#undef if_mtu
|
||||||
#define IF_COMP IF_AUTOCOMP /* Flags for compression */
|
extern size_t if_mtu;
|
||||||
|
extern size_t if_mru; /* MTU and MRU */
|
||||||
#if 0
|
extern int if_comp; /* Flags for compression */
|
||||||
/*
|
extern int if_maxlinkhdr;
|
||||||
* Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP,
|
|
||||||
* and 8 bytes for PPP, but need to have it on an 8byte boundary
|
|
||||||
*/
|
|
||||||
#ifdef USE_PPP
|
|
||||||
#define IF_MAXLINKHDR 48
|
|
||||||
#else
|
|
||||||
#define IF_MAXLINKHDR 40
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
|
|
||||||
#define IF_MAXLINKHDR (2 + 14 + 40)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int if_queued; /* Number of packets queued so far */
|
extern int if_queued; /* Number of packets queued so far */
|
||||||
|
extern int if_thresh; /* Number of packets queued before we start sending
|
||||||
|
* (to prevent allocing too many mbufs) */
|
||||||
|
|
||||||
extern struct mbuf if_fastq; /* fast queue (for interactive data) */
|
extern struct mbuf if_fastq; /* fast queue (for interactive data) */
|
||||||
extern struct mbuf if_batchq; /* queue for non-interactive data */
|
extern struct mbuf if_batchq; /* queue for non-interactive data */
|
||||||
|
@ -40,7 +29,6 @@ extern struct mbuf *next_m;
|
||||||
|
|
||||||
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
|
#define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
/* Interface statistics */
|
/* Interface statistics */
|
||||||
struct slirp_ifstats {
|
struct slirp_ifstats {
|
||||||
u_int out_pkts; /* Output packets */
|
u_int out_pkts; /* Output packets */
|
||||||
|
@ -51,13 +39,12 @@ struct slirp_ifstats {
|
||||||
u_int in_bytes; /* Input bytes */
|
u_int in_bytes; /* Input bytes */
|
||||||
u_int in_errpkts; /* Input Error Packets */
|
u_int in_errpkts; /* Input Error Packets */
|
||||||
u_int in_errbytes; /* Input Error Bytes */
|
u_int in_errbytes; /* Input Error Bytes */
|
||||||
|
|
||||||
u_int bytes_saved; /* Number of bytes that compression "saved" */
|
u_int bytes_saved; /* Number of bytes that compression "saved" */
|
||||||
/* ie: number of bytes that didn't need to be sent over the link
|
/* ie: number of bytes that didn't need to be sent over the link
|
||||||
* because of compression */
|
* because of compression */
|
||||||
|
|
||||||
u_int in_mbad; /* Bad incoming packets */
|
u_int in_mbad; /* Bad incoming packets */
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -76,12 +72,16 @@ typedef u_int32_t n_long; /* long as received from the net */
|
||||||
/*
|
/*
|
||||||
* Structure of an internet header, naked of options.
|
* Structure of an internet header, naked of options.
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ip {
|
struct ip {
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
u_int ip_v:4, /* version */
|
u_char ip_v:4, /* version */
|
||||||
ip_hl:4; /* header length */
|
ip_hl:4; /* header length */
|
||||||
#else
|
#else
|
||||||
u_int ip_hl:4, /* header length */
|
u_char ip_hl:4, /* header length */
|
||||||
ip_v:4; /* version */
|
ip_v:4; /* version */
|
||||||
#endif
|
#endif
|
||||||
u_int8_t ip_tos; /* type of service */
|
u_int8_t ip_tos; /* type of service */
|
||||||
|
@ -95,7 +95,11 @@ struct ip {
|
||||||
u_int8_t ip_p; /* protocol */
|
u_int8_t ip_p; /* protocol */
|
||||||
u_int16_t ip_sum; /* checksum */
|
u_int16_t ip_sum; /* checksum */
|
||||||
struct in_addr ip_src,ip_dst; /* source and dest address */
|
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define IP_MAXPACKET 65535 /* maximum packet size */
|
#define IP_MAXPACKET 65535 /* maximum packet size */
|
||||||
|
|
||||||
|
@ -139,15 +143,19 @@ struct ip {
|
||||||
/*
|
/*
|
||||||
* Time stamp option structure.
|
* Time stamp option structure.
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ip_timestamp {
|
struct ip_timestamp {
|
||||||
u_int8_t ipt_code; /* IPOPT_TS */
|
u_int8_t ipt_code; /* IPOPT_TS */
|
||||||
u_int8_t ipt_len; /* size of structure (variable) */
|
u_int8_t ipt_len; /* size of structure (variable) */
|
||||||
u_int8_t ipt_ptr; /* index of current entry */
|
u_int8_t ipt_ptr; /* index of current entry */
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
u_int ipt_oflw:4, /* overflow counter */
|
u_char ipt_oflw:4, /* overflow counter */
|
||||||
ipt_flg:4; /* flags, see below */
|
ipt_flg:4; /* flags, see below */
|
||||||
#else
|
#else
|
||||||
u_int ipt_flg:4, /* flags, see below */
|
u_char ipt_flg:4, /* flags, see below */
|
||||||
ipt_oflw:4; /* overflow counter */
|
ipt_oflw:4; /* overflow counter */
|
||||||
#endif
|
#endif
|
||||||
union ipt_timestamp {
|
union ipt_timestamp {
|
||||||
|
@ -157,7 +165,11 @@ struct ip_timestamp {
|
||||||
n_long ipt_time;
|
n_long ipt_time;
|
||||||
} ipt_ta[1];
|
} ipt_ta[1];
|
||||||
} ipt_timestamp;
|
} ipt_timestamp;
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* flag bits for ipt_flg */
|
/* flag bits for ipt_flg */
|
||||||
#define IPOPT_TS_TSONLY 0 /* timestamps only */
|
#define IPOPT_TS_TSONLY 0 /* timestamps only */
|
||||||
|
@ -204,6 +216,10 @@ typedef caddr32_t ipasfragp_32;
|
||||||
/*
|
/*
|
||||||
* Overlay for ip header used by other protocols (tcp, udp).
|
* Overlay for ip header used by other protocols (tcp, udp).
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct ipovly {
|
struct ipovly {
|
||||||
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
|
caddr32_t ih_next, ih_prev; /* for protocol sequence q's */
|
||||||
u_int8_t ih_x1; /* (unused) */
|
u_int8_t ih_x1; /* (unused) */
|
||||||
|
@ -211,7 +227,11 @@ struct ipovly {
|
||||||
u_int16_t ih_len; /* protocol length */
|
u_int16_t ih_len; /* protocol length */
|
||||||
struct in_addr ih_src; /* source internet address */
|
struct in_addr ih_src; /* source internet address */
|
||||||
struct in_addr ih_dst; /* destination internet address */
|
struct in_addr ih_dst; /* destination internet address */
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ip reassembly queue structure. Each fragment
|
* Ip reassembly queue structure. Each fragment
|
||||||
|
@ -237,10 +257,10 @@ struct ipq {
|
||||||
*/
|
*/
|
||||||
struct ipasfrag {
|
struct ipasfrag {
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
u_int ip_v:4,
|
u_char ip_v:4,
|
||||||
ip_hl:4;
|
ip_hl:4;
|
||||||
#else
|
#else
|
||||||
u_int ip_hl:4,
|
u_char ip_hl:4,
|
||||||
ip_v:4;
|
ip_v:4;
|
||||||
#endif
|
#endif
|
||||||
/* BUG : u_int changed to u_int8_t.
|
/* BUG : u_int changed to u_int8_t.
|
||||||
|
@ -272,7 +292,6 @@ struct ipoption {
|
||||||
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
|
int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
/*
|
/*
|
||||||
* Structure attached to inpcb.ip_moptions and
|
* Structure attached to inpcb.ip_moptions and
|
||||||
* passed to ip_output when IP multicast options are in use.
|
* passed to ip_output when IP multicast options are in use.
|
||||||
|
@ -307,9 +326,8 @@ struct ipstat {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct ipstat ipstat;
|
extern struct ipstat ipstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
extern struct ipq ipq; /* ip reass. queue */
|
extern struct ipq ipq; /* ip reass. queue */
|
||||||
extern u_int16_t ip_id; /* ip packet ctr, for ids */
|
extern u_int16_t ip_id; /* ip packet ctr, for ids */
|
||||||
|
extern int ip_defttl; /* default IP ttl */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,16 +33,14 @@
|
||||||
#include "slirp.h"
|
#include "slirp.h"
|
||||||
#include "ip_icmp.h"
|
#include "ip_icmp.h"
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
struct icmpstat icmpstat;
|
struct icmpstat icmpstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The message sent when emulating PING */
|
/* The message sent when emulating PING */
|
||||||
/* Be nice and tell them it's just a pseudo-ping packet */
|
/* Be nice and tell them it's just a psuedo-ping packet */
|
||||||
const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
|
char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
|
||||||
|
|
||||||
/* list of actions for icmp_error() on RX of an icmp message */
|
/* list of actions for icmp_error() on RX of an icmp message */
|
||||||
static const int icmp_flush[19] = {
|
static int icmp_flush[19] = {
|
||||||
/* ECHO REPLY (0) */ 0,
|
/* ECHO REPLY (0) */ 0,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
@ -65,7 +59,7 @@ static const int icmp_flush[19] = {
|
||||||
/* INFO (15) */ 0,
|
/* INFO (15) */ 0,
|
||||||
/* INFO REPLY (16) */ 0,
|
/* INFO REPLY (16) */ 0,
|
||||||
/* ADDR MASK (17) */ 0,
|
/* ADDR MASK (17) */ 0,
|
||||||
/* ADDR MASK REPLY (18) */ 0
|
/* ADDR MASK REPLY (18) */ 0
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -80,19 +74,19 @@ icmp_input(m, hlen)
|
||||||
register struct ip *ip=mtod(m, struct ip *);
|
register struct ip *ip=mtod(m, struct ip *);
|
||||||
int icmplen=ip->ip_len;
|
int icmplen=ip->ip_len;
|
||||||
/* int code; */
|
/* int code; */
|
||||||
|
|
||||||
DEBUG_CALL("icmp_input");
|
DEBUG_CALL("icmp_input");
|
||||||
DEBUG_ARG("m = %lx", (long )m);
|
DEBUG_ARG("m = %lx", (long )m);
|
||||||
DEBUG_ARG("m_len = %d", m->m_len);
|
DEBUG_ARG("m_len = %zu", m->m_len);
|
||||||
|
|
||||||
STAT(icmpstat.icps_received++);
|
|
||||||
|
|
||||||
|
icmpstat.icps_received++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate icmp structure in mbuf, and check
|
* Locate icmp structure in mbuf, and check
|
||||||
* that its not corrupted and of at least minimum length.
|
* that its not corrupted and of at least minimum length.
|
||||||
*/
|
*/
|
||||||
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
|
if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */
|
||||||
STAT(icmpstat.icps_tooshort++);
|
icmpstat.icps_tooshort++;
|
||||||
freeit:
|
freeit:
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
goto end_error;
|
goto end_error;
|
||||||
|
@ -102,12 +96,12 @@ icmp_input(m, hlen)
|
||||||
m->m_data += hlen;
|
m->m_data += hlen;
|
||||||
icp = mtod(m, struct icmp *);
|
icp = mtod(m, struct icmp *);
|
||||||
if (cksum(m, icmplen)) {
|
if (cksum(m, icmplen)) {
|
||||||
STAT(icmpstat.icps_checksum++);
|
icmpstat.icps_checksum++;
|
||||||
goto freeit;
|
goto freeit;
|
||||||
}
|
}
|
||||||
m->m_len += hlen;
|
m->m_len += hlen;
|
||||||
m->m_data -= hlen;
|
m->m_data -= hlen;
|
||||||
|
|
||||||
/* icmpstat.icps_inhist[icp->icmp_type]++; */
|
/* icmpstat.icps_inhist[icp->icmp_type]++; */
|
||||||
/* code = icp->icmp_code; */
|
/* code = icp->icmp_code; */
|
||||||
|
|
||||||
|
@ -123,7 +117,7 @@ icmp_input(m, hlen)
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
if ((so = socreate()) == NULL) goto freeit;
|
if ((so = socreate()) == NULL) goto freeit;
|
||||||
if(udp_attach(so) == -1) {
|
if(udp_attach(so) == -1) {
|
||||||
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
|
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
|
||||||
errno,strerror(errno)));
|
errno,strerror(errno)));
|
||||||
sofree(so);
|
sofree(so);
|
||||||
m_free(m);
|
m_free(m);
|
||||||
|
@ -137,7 +131,7 @@ icmp_input(m, hlen)
|
||||||
so->so_iptos = ip->ip_tos;
|
so->so_iptos = ip->ip_tos;
|
||||||
so->so_type = IPPROTO_ICMP;
|
so->so_type = IPPROTO_ICMP;
|
||||||
so->so_state = SS_ISFCONNECTED;
|
so->so_state = SS_ISFCONNECTED;
|
||||||
|
|
||||||
/* Send the packet */
|
/* Send the packet */
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
|
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
|
||||||
|
@ -159,7 +153,7 @@ icmp_input(m, hlen)
|
||||||
(struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
(struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||||
DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
|
DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
|
||||||
errno,strerror(errno)));
|
errno,strerror(errno)));
|
||||||
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
||||||
udp_detach(so);
|
udp_detach(so);
|
||||||
}
|
}
|
||||||
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
|
} /* if ip->ip_dst.s_addr == alias_addr.s_addr */
|
||||||
|
@ -172,12 +166,12 @@ icmp_input(m, hlen)
|
||||||
case ICMP_TSTAMP:
|
case ICMP_TSTAMP:
|
||||||
case ICMP_MASKREQ:
|
case ICMP_MASKREQ:
|
||||||
case ICMP_REDIRECT:
|
case ICMP_REDIRECT:
|
||||||
STAT(icmpstat.icps_notsupp++);
|
icmpstat.icps_notsupp++;
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
STAT(icmpstat.icps_badtype++);
|
icmpstat.icps_badtype++;
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
} /* swith */
|
} /* swith */
|
||||||
|
|
||||||
|
@ -201,18 +195,18 @@ end_error:
|
||||||
* mbuf *msrc is used as a template, but is NOT m_free()'d.
|
* mbuf *msrc is used as a template, but is NOT m_free()'d.
|
||||||
* It is reported as the bad ip packet. The header should
|
* It is reported as the bad ip packet. The header should
|
||||||
* be fully correct and in host byte order.
|
* be fully correct and in host byte order.
|
||||||
* ICMP fragmentation is illegal. All machines must accept 576 bytes in one
|
* ICMP fragmentation is illegal. All machines must accept 576 bytes in one
|
||||||
* packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
|
* packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ICMP_MAXDATALEN (IP_MSS-28)
|
#define ICMP_MAXDATALEN (IP_MSS-28)
|
||||||
void
|
void
|
||||||
icmp_error(msrc, type, code, minsize, message)
|
icmp_error(
|
||||||
struct mbuf *msrc;
|
struct mbuf *msrc,
|
||||||
u_char type;
|
u_char type,
|
||||||
u_char code;
|
u_char code,
|
||||||
int minsize;
|
int minsize,
|
||||||
char *message;
|
char *message)
|
||||||
{
|
{
|
||||||
unsigned hlen, shlen, s_ip_len;
|
unsigned hlen, shlen, s_ip_len;
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
|
@ -221,17 +215,17 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
|
|
||||||
DEBUG_CALL("icmp_error");
|
DEBUG_CALL("icmp_error");
|
||||||
DEBUG_ARG("msrc = %lx", (long )msrc);
|
DEBUG_ARG("msrc = %lx", (long )msrc);
|
||||||
DEBUG_ARG("msrc_len = %d", msrc->m_len);
|
DEBUG_ARG("msrc_len = %zu", msrc->m_len);
|
||||||
|
|
||||||
if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
|
if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error;
|
||||||
|
|
||||||
/* check msrc */
|
/* check msrc */
|
||||||
if(!msrc) goto end_error;
|
if(!msrc) goto end_error;
|
||||||
ip = mtod(msrc, struct ip *);
|
ip = mtod(msrc, struct ip *);
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
{ char bufa[20], bufb[20];
|
{ char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN];
|
||||||
strcpy(bufa, inet_ntoa(ip->ip_src));
|
inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa));
|
||||||
strcpy(bufb, inet_ntoa(ip->ip_dst));
|
inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb));
|
||||||
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
|
DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -250,7 +244,7 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
|
|
||||||
/* make a copy */
|
/* make a copy */
|
||||||
if(!(m=m_get())) goto end_error; /* get mbuf */
|
if(!(m=m_get())) goto end_error; /* get mbuf */
|
||||||
{ int new_m_size;
|
{ u_int new_m_size;
|
||||||
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
|
new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN;
|
||||||
if(new_m_size>m->m_size) m_inc(m, new_m_size);
|
if(new_m_size>m->m_size) m_inc(m, new_m_size);
|
||||||
}
|
}
|
||||||
|
@ -260,9 +254,9 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
/* make the header of the reply packet */
|
/* make the header of the reply packet */
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
hlen= sizeof(struct ip ); /* no options in reply */
|
hlen= sizeof(struct ip ); /* no options in reply */
|
||||||
|
|
||||||
/* fill in icmp */
|
/* fill in icmp */
|
||||||
m->m_data += hlen;
|
m->m_data += hlen;
|
||||||
m->m_len -= hlen;
|
m->m_len -= hlen;
|
||||||
|
|
||||||
icp = mtod(m, struct icmp *);
|
icp = mtod(m, struct icmp *);
|
||||||
|
@ -271,7 +265,7 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
|
else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */
|
||||||
s_ip_len=ICMP_MAXDATALEN;
|
s_ip_len=ICMP_MAXDATALEN;
|
||||||
|
|
||||||
m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
|
m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */
|
||||||
|
|
||||||
/* min. size = 8+sizeof(struct ip)+8 */
|
/* min. size = 8+sizeof(struct ip)+8 */
|
||||||
|
|
||||||
|
@ -305,8 +299,8 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
|
|
||||||
/* fill in ip */
|
/* fill in ip */
|
||||||
ip->ip_hl = hlen >> 2;
|
ip->ip_hl = hlen >> 2;
|
||||||
ip->ip_len = m->m_len;
|
ip->ip_len = (u_int16_t)m->m_len;
|
||||||
|
|
||||||
ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
|
ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */
|
||||||
|
|
||||||
ip->ip_ttl = MAXTTL;
|
ip->ip_ttl = MAXTTL;
|
||||||
|
@ -315,8 +309,8 @@ icmp_error(msrc, type, code, minsize, message)
|
||||||
ip->ip_src = alias_addr;
|
ip->ip_src = alias_addr;
|
||||||
|
|
||||||
(void ) ip_output((struct socket *)NULL, m);
|
(void ) ip_output((struct socket *)NULL, m);
|
||||||
|
|
||||||
STAT(icmpstat.icps_reflect++);
|
icmpstat.icps_reflect++;
|
||||||
|
|
||||||
end_error:
|
end_error:
|
||||||
return;
|
return;
|
||||||
|
@ -373,5 +367,5 @@ icmp_reflect(m)
|
||||||
|
|
||||||
(void ) ip_output((struct socket *)NULL, m);
|
(void ) ip_output((struct socket *)NULL, m);
|
||||||
|
|
||||||
STAT(icmpstat.icps_reflect++);
|
icmpstat.icps_reflect++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -47,6 +43,10 @@ typedef u_int32_t n_time;
|
||||||
/*
|
/*
|
||||||
* Structure of an icmp header.
|
* Structure of an icmp header.
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct icmp {
|
struct icmp {
|
||||||
u_char icmp_type; /* type of message, see below */
|
u_char icmp_type; /* type of message, see below */
|
||||||
u_char icmp_code; /* type sub code */
|
u_char icmp_code; /* type sub code */
|
||||||
|
@ -92,7 +92,11 @@ struct icmp {
|
||||||
#define icmp_ip icmp_dun.id_ip.idi_ip
|
#define icmp_ip icmp_dun.id_ip.idi_ip
|
||||||
#define icmp_mask icmp_dun.id_mask
|
#define icmp_mask icmp_dun.id_mask
|
||||||
#define icmp_data icmp_dun.id_data
|
#define icmp_data icmp_dun.id_data
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lower bounds on packet lengths for various types.
|
* Lower bounds on packet lengths for various types.
|
||||||
|
@ -157,8 +161,8 @@ struct icmp {
|
||||||
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
|
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
|
||||||
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
|
||||||
|
|
||||||
void icmp_input _P((struct mbuf *, int));
|
void icmp_input(struct mbuf *, int);
|
||||||
void icmp_error _P((struct mbuf *, u_char, u_char, int, char *));
|
void icmp_error(struct mbuf *, u_char, u_char, int, char *);
|
||||||
void icmp_reflect _P((struct mbuf *));
|
void icmp_reflect(struct mbuf *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,7 +33,7 @@
|
||||||
/*
|
/*
|
||||||
* Changes and additions relating to SLiRP are
|
* Changes and additions relating to SLiRP are
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
@ -45,19 +41,10 @@
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
#include "ip_icmp.h"
|
#include "ip_icmp.h"
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
int ip_defttl;
|
||||||
struct ipstat ipstat;
|
struct ipstat ipstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ipq ipq;
|
struct ipq ipq;
|
||||||
|
|
||||||
static struct ip *ip_reass(register struct ipasfrag *ip,
|
|
||||||
register struct ipq *fp);
|
|
||||||
static void ip_freef(struct ipq *fp);
|
|
||||||
static void ip_enq(register struct ipasfrag *p,
|
|
||||||
register struct ipasfrag *prev);
|
|
||||||
static void ip_deq(register struct ipasfrag *p);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IP initialization: fill in IP protocol switch table.
|
* IP initialization: fill in IP protocol switch table.
|
||||||
* All protocols not implemented in kernel go to raw IP protocol handler.
|
* All protocols not implemented in kernel go to raw IP protocol handler.
|
||||||
|
@ -69,6 +56,7 @@ ip_init()
|
||||||
ip_id = tt.tv_sec & 0xffff;
|
ip_id = tt.tv_sec & 0xffff;
|
||||||
udp_init();
|
udp_init();
|
||||||
tcp_init();
|
tcp_init();
|
||||||
|
ip_defttl = IPDEFTTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -80,38 +68,38 @@ ip_input(m)
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
{
|
{
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
int hlen;
|
u_int hlen;
|
||||||
|
|
||||||
DEBUG_CALL("ip_input");
|
DEBUG_CALL("ip_input");
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("m_len = %d", m->m_len);
|
DEBUG_ARG("m_len = %zu", m->m_len);
|
||||||
|
|
||||||
STAT(ipstat.ips_total++);
|
|
||||||
|
|
||||||
|
ipstat.ips_total++;
|
||||||
|
|
||||||
if (m->m_len < sizeof (struct ip)) {
|
if (m->m_len < sizeof (struct ip)) {
|
||||||
STAT(ipstat.ips_toosmall++);
|
ipstat.ips_toosmall++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = mtod(m, struct ip *);
|
ip = mtod(m, struct ip *);
|
||||||
|
|
||||||
if (ip->ip_v != IPVERSION) {
|
if (ip->ip_v != IPVERSION) {
|
||||||
STAT(ipstat.ips_badvers++);
|
ipstat.ips_badvers++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
hlen = ip->ip_hl << 2;
|
hlen = ip->ip_hl << 2;
|
||||||
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
|
if (hlen<sizeof(struct ip ) || hlen>m->m_len) {/* min header length */
|
||||||
STAT(ipstat.ips_badhlen++); /* or packet too short */
|
ipstat.ips_badhlen++; /* or packet too short */
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* keep ip header intact for ICMP reply
|
/* keep ip header intact for ICMP reply
|
||||||
* ip->ip_sum = cksum(m, hlen);
|
* ip->ip_sum = cksum(m, hlen);
|
||||||
* if (ip->ip_sum) {
|
* if (ip->ip_sum) {
|
||||||
*/
|
*/
|
||||||
if(cksum(m,hlen)) {
|
if(cksum(m,hlen)) {
|
||||||
STAT(ipstat.ips_badsum++);
|
ipstat.ips_badsum++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +108,7 @@ ip_input(m)
|
||||||
*/
|
*/
|
||||||
NTOHS(ip->ip_len);
|
NTOHS(ip->ip_len);
|
||||||
if (ip->ip_len < hlen) {
|
if (ip->ip_len < hlen) {
|
||||||
STAT(ipstat.ips_badlen++);
|
ipstat.ips_badlen++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
NTOHS(ip->ip_id);
|
NTOHS(ip->ip_id);
|
||||||
|
@ -133,7 +121,7 @@ ip_input(m)
|
||||||
* Drop packet if shorter than we expect.
|
* Drop packet if shorter than we expect.
|
||||||
*/
|
*/
|
||||||
if (m->m_len < ip->ip_len) {
|
if (m->m_len < ip->ip_len) {
|
||||||
STAT(ipstat.ips_tooshort++);
|
ipstat.ips_tooshort++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
/* Should drop packet if mbuf too long? hmmm... */
|
/* Should drop packet if mbuf too long? hmmm... */
|
||||||
|
@ -162,7 +150,7 @@ ip_input(m)
|
||||||
* (We could look in the reassembly queue to see
|
* (We could look in the reassembly queue to see
|
||||||
* if the packet was previously fragmented,
|
* if the packet was previously fragmented,
|
||||||
* but it's not worth the time; just let them time out.)
|
* but it's not worth the time; just let them time out.)
|
||||||
*
|
*
|
||||||
* XXX This should fail, don't fragment yet
|
* XXX This should fail, don't fragment yet
|
||||||
*/
|
*/
|
||||||
if (ip->ip_off &~ IP_DF) {
|
if (ip->ip_off &~ IP_DF) {
|
||||||
|
@ -189,7 +177,7 @@ ip_input(m)
|
||||||
ip->ip_len -= hlen;
|
ip->ip_len -= hlen;
|
||||||
if (ip->ip_off & IP_MF)
|
if (ip->ip_off & IP_MF)
|
||||||
((struct ipasfrag *)ip)->ipf_mff |= 1;
|
((struct ipasfrag *)ip)->ipf_mff |= 1;
|
||||||
else
|
else
|
||||||
((struct ipasfrag *)ip)->ipf_mff &= ~1;
|
((struct ipasfrag *)ip)->ipf_mff &= ~1;
|
||||||
|
|
||||||
ip->ip_off <<= 3;
|
ip->ip_off <<= 3;
|
||||||
|
@ -200,11 +188,11 @@ ip_input(m)
|
||||||
* attempt reassembly; if it succeeds, proceed.
|
* attempt reassembly; if it succeeds, proceed.
|
||||||
*/
|
*/
|
||||||
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
|
if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
|
||||||
STAT(ipstat.ips_fragments++);
|
ipstat.ips_fragments++;
|
||||||
ip = ip_reass((struct ipasfrag *)ip, fp);
|
ip = ip_reass((struct ipasfrag *)ip, fp);
|
||||||
if (ip == 0)
|
if (ip == 0)
|
||||||
return;
|
return;
|
||||||
STAT(ipstat.ips_reassembled++);
|
ipstat.ips_reassembled++;
|
||||||
m = dtom(ip);
|
m = dtom(ip);
|
||||||
} else
|
} else
|
||||||
if (fp)
|
if (fp)
|
||||||
|
@ -216,7 +204,7 @@ ip_input(m)
|
||||||
/*
|
/*
|
||||||
* Switch out to protocol's input routine.
|
* Switch out to protocol's input routine.
|
||||||
*/
|
*/
|
||||||
STAT(ipstat.ips_delivered++);
|
ipstat.ips_delivered++;
|
||||||
switch (ip->ip_p) {
|
switch (ip->ip_p) {
|
||||||
case IPPROTO_TCP:
|
case IPPROTO_TCP:
|
||||||
tcp_input(m, hlen, (struct socket *)NULL);
|
tcp_input(m, hlen, (struct socket *)NULL);
|
||||||
|
@ -228,7 +216,7 @@ ip_input(m)
|
||||||
icmp_input(m, hlen);
|
icmp_input(m, hlen);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
STAT(ipstat.ips_noproto++);
|
ipstat.ips_noproto++;
|
||||||
m_free(m);
|
m_free(m);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -243,14 +231,16 @@ bad:
|
||||||
* reassembly of this datagram already exists, then it
|
* reassembly of this datagram already exists, then it
|
||||||
* is given as fp; otherwise have to make a chain.
|
* is given as fp; otherwise have to make a chain.
|
||||||
*/
|
*/
|
||||||
static struct ip *
|
struct ip *
|
||||||
ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
|
ip_reass(ip, fp)
|
||||||
|
register struct ipasfrag *ip;
|
||||||
|
register struct ipq *fp;
|
||||||
{
|
{
|
||||||
register struct mbuf *m = dtom(ip);
|
register struct mbuf *m = dtom(ip);
|
||||||
register struct ipasfrag *q;
|
register struct ipasfrag *q;
|
||||||
int hlen = ip->ip_hl << 2;
|
int hlen = ip->ip_hl << 2;
|
||||||
int i, next;
|
int i, next;
|
||||||
|
|
||||||
DEBUG_CALL("ip_reass");
|
DEBUG_CALL("ip_reass");
|
||||||
DEBUG_ARG("ip = %lx", (long)ip);
|
DEBUG_ARG("ip = %lx", (long)ip);
|
||||||
DEBUG_ARG("fp = %lx", (long)fp);
|
DEBUG_ARG("fp = %lx", (long)fp);
|
||||||
|
@ -281,7 +271,7 @@ ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
|
||||||
q = (struct ipasfrag *)fp;
|
q = (struct ipasfrag *)fp;
|
||||||
goto insert;
|
goto insert;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a segment which begins after this one does.
|
* Find a segment which begins after this one does.
|
||||||
*/
|
*/
|
||||||
|
@ -375,7 +365,7 @@ insert:
|
||||||
ip = (struct ipasfrag *)(m->m_ext + delta);
|
ip = (struct ipasfrag *)(m->m_ext + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DEBUG_ARG("ip = %lx", (long)ip);
|
/* DEBUG_ARG("ip = %lx", (long)ip);
|
||||||
* ip=(struct ipasfrag *)m->m_data; */
|
* ip=(struct ipasfrag *)m->m_data; */
|
||||||
|
|
||||||
ip->ip_len = next;
|
ip->ip_len = next;
|
||||||
|
@ -391,7 +381,7 @@ insert:
|
||||||
return ((struct ip *)ip);
|
return ((struct ip *)ip);
|
||||||
|
|
||||||
dropfrag:
|
dropfrag:
|
||||||
STAT(ipstat.ips_fragdropped++);
|
ipstat.ips_fragdropped++;
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -400,8 +390,9 @@ dropfrag:
|
||||||
* Free a fragment reassembly header and all
|
* Free a fragment reassembly header and all
|
||||||
* associated datagrams.
|
* associated datagrams.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
ip_freef(struct ipq *fp)
|
ip_freef(fp)
|
||||||
|
struct ipq *fp;
|
||||||
{
|
{
|
||||||
register struct ipasfrag *q, *p;
|
register struct ipasfrag *q, *p;
|
||||||
|
|
||||||
|
@ -419,8 +410,9 @@ ip_freef(struct ipq *fp)
|
||||||
* Put an ip fragment on a reassembly chain.
|
* Put an ip fragment on a reassembly chain.
|
||||||
* Like insque, but pointers in middle of structure.
|
* Like insque, but pointers in middle of structure.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
ip_enq(p, prev)
|
||||||
|
register struct ipasfrag *p, *prev;
|
||||||
{
|
{
|
||||||
DEBUG_CALL("ip_enq");
|
DEBUG_CALL("ip_enq");
|
||||||
DEBUG_ARG("prev = %lx", (long)prev);
|
DEBUG_ARG("prev = %lx", (long)prev);
|
||||||
|
@ -433,8 +425,9 @@ ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
|
||||||
/*
|
/*
|
||||||
* To ip_enq as remque is to insque.
|
* To ip_enq as remque is to insque.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
ip_deq(register struct ipasfrag *p)
|
ip_deq(p)
|
||||||
|
register struct ipasfrag *p;
|
||||||
{
|
{
|
||||||
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
|
((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next;
|
||||||
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
|
((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev;
|
||||||
|
@ -449,9 +442,9 @@ void
|
||||||
ip_slowtimo()
|
ip_slowtimo()
|
||||||
{
|
{
|
||||||
register struct ipq *fp;
|
register struct ipq *fp;
|
||||||
|
|
||||||
DEBUG_CALL("ip_slowtimo");
|
DEBUG_CALL("ip_slowtimo");
|
||||||
|
|
||||||
fp = (struct ipq *) ipq.next;
|
fp = (struct ipq *) ipq.next;
|
||||||
if (fp == 0)
|
if (fp == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -460,7 +453,7 @@ ip_slowtimo()
|
||||||
--fp->ipq_ttl;
|
--fp->ipq_ttl;
|
||||||
fp = (struct ipq *) fp->next;
|
fp = (struct ipq *) fp->next;
|
||||||
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
|
if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
|
||||||
STAT(ipstat.ips_fragtimeout++);
|
ipstat.ips_fragtimeout++;
|
||||||
ip_freef((struct ipq *) fp->prev);
|
ip_freef((struct ipq *) fp->prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,7 +660,7 @@ bad:
|
||||||
/* Not yet */
|
/* Not yet */
|
||||||
icmp_error(m, type, code, 0, 0);
|
icmp_error(m, type, code, 0, 0);
|
||||||
|
|
||||||
STAT(ipstat.ips_badoptions++);
|
ipstat.ips_badoptions++;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,6 +688,6 @@ ip_stripoptions(m, mopt)
|
||||||
i = m->m_len - (sizeof (struct ip) + olen);
|
i = m->m_len - (sizeof (struct ip) + olen);
|
||||||
memcpy(opts, opts + olen, (unsigned)i);
|
memcpy(opts, opts + olen, (unsigned)i);
|
||||||
m->m_len -= olen;
|
m->m_len -= olen;
|
||||||
|
|
||||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -46,10 +42,6 @@
|
||||||
|
|
||||||
u_int16_t ip_id;
|
u_int16_t ip_id;
|
||||||
|
|
||||||
/* Number of packets queued before we start sending
|
|
||||||
* (to prevent allocing too many mbufs) */
|
|
||||||
#define IF_THRESH 10
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IP output. The packet in mbuf chain m contains a skeletal IP
|
* IP output. The packet in mbuf chain m contains a skeletal IP
|
||||||
* header (with len, off, ttl, proto, tos, src, dst).
|
* header (with len, off, ttl, proto, tos, src, dst).
|
||||||
|
@ -63,13 +55,14 @@ ip_output(so, m0)
|
||||||
{
|
{
|
||||||
register struct ip *ip;
|
register struct ip *ip;
|
||||||
register struct mbuf *m = m0;
|
register struct mbuf *m = m0;
|
||||||
register int hlen = sizeof(struct ip );
|
register u_int hlen = sizeof(struct ip);
|
||||||
int len, off, error = 0;
|
u_int len, off;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
DEBUG_CALL("ip_output");
|
DEBUG_CALL("ip_output");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m0 = %lx", (long)m0);
|
DEBUG_ARG("m0 = %lx", (long)m0);
|
||||||
|
|
||||||
/* We do no options */
|
/* We do no options */
|
||||||
/* if (opt) {
|
/* if (opt) {
|
||||||
* m = ip_insertoptions(m, opt, &len);
|
* m = ip_insertoptions(m, opt, &len);
|
||||||
|
@ -84,23 +77,23 @@ ip_output(so, m0)
|
||||||
ip->ip_off &= IP_DF;
|
ip->ip_off &= IP_DF;
|
||||||
ip->ip_id = htons(ip_id++);
|
ip->ip_id = htons(ip_id++);
|
||||||
ip->ip_hl = hlen >> 2;
|
ip->ip_hl = hlen >> 2;
|
||||||
STAT(ipstat.ips_localout++);
|
ipstat.ips_localout++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that we have any chance at all of being able to queue
|
* Verify that we have any chance at all of being able to queue
|
||||||
* the packet or packet fragments
|
* the packet or packet fragments
|
||||||
*/
|
*/
|
||||||
/* XXX Hmmm... */
|
/* XXX Hmmm... */
|
||||||
/* if (if_queued > IF_THRESH && towrite <= 0) {
|
/* if (if_queued > if_thresh && towrite <= 0) {
|
||||||
* error = ENOBUFS;
|
* error = ENOBUFS;
|
||||||
* goto bad;
|
* goto bad;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If small enough for interface, can just send directly.
|
* If small enough for interface, can just send directly.
|
||||||
*/
|
*/
|
||||||
if ((u_int16_t)ip->ip_len <= IF_MTU) {
|
if ((u_int16_t)ip->ip_len <= if_mtu) {
|
||||||
ip->ip_len = htons((u_int16_t)ip->ip_len);
|
ip->ip_len = htons((u_int16_t)ip->ip_len);
|
||||||
ip->ip_off = htons((u_int16_t)ip->ip_off);
|
ip->ip_off = htons((u_int16_t)ip->ip_off);
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
|
@ -116,11 +109,11 @@ ip_output(so, m0)
|
||||||
*/
|
*/
|
||||||
if (ip->ip_off & IP_DF) {
|
if (ip->ip_off & IP_DF) {
|
||||||
error = -1;
|
error = -1;
|
||||||
STAT(ipstat.ips_cantfrag++);
|
ipstat.ips_cantfrag++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */
|
len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */
|
||||||
if (len < 8) {
|
if (len < 8) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -136,18 +129,18 @@ ip_output(so, m0)
|
||||||
*/
|
*/
|
||||||
m0 = m;
|
m0 = m;
|
||||||
mhlen = sizeof (struct ip);
|
mhlen = sizeof (struct ip);
|
||||||
for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) {
|
for (off = hlen + len; off < ip->ip_len; off += len) {
|
||||||
register struct ip *mhip;
|
register struct ip *mhip;
|
||||||
m = m_get();
|
m = m_get();
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
error = -1;
|
error = -1;
|
||||||
STAT(ipstat.ips_odropped++);
|
ipstat.ips_odropped++;
|
||||||
goto sendorfree;
|
goto sendorfree;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
mhip = mtod(m, struct ip *);
|
mhip = mtod(m, struct ip *);
|
||||||
*mhip = *ip;
|
*mhip = *ip;
|
||||||
|
|
||||||
/* No options */
|
/* No options */
|
||||||
/* if (hlen > sizeof (struct ip)) {
|
/* if (hlen > sizeof (struct ip)) {
|
||||||
* mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
* mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
|
||||||
|
@ -160,28 +153,28 @@ ip_output(so, m0)
|
||||||
mhip->ip_off |= IP_MF;
|
mhip->ip_off |= IP_MF;
|
||||||
if (off + len >= (u_int16_t)ip->ip_len)
|
if (off + len >= (u_int16_t)ip->ip_len)
|
||||||
len = (u_int16_t)ip->ip_len - off;
|
len = (u_int16_t)ip->ip_len - off;
|
||||||
else
|
else
|
||||||
mhip->ip_off |= IP_MF;
|
mhip->ip_off |= IP_MF;
|
||||||
mhip->ip_len = htons((u_int16_t)(len + mhlen));
|
mhip->ip_len = htons((u_int16_t)(len + mhlen));
|
||||||
|
|
||||||
if (m_copy(m, m0, off, len) < 0) {
|
if (m_copy(m, m0, off, len) < 0) {
|
||||||
error = -1;
|
error = -1;
|
||||||
goto sendorfree;
|
goto sendorfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
mhip->ip_off = htons((u_int16_t)mhip->ip_off);
|
mhip->ip_off = htons((u_int16_t)mhip->ip_off);
|
||||||
mhip->ip_sum = 0;
|
mhip->ip_sum = 0;
|
||||||
mhip->ip_sum = cksum(m, mhlen);
|
mhip->ip_sum = cksum(m, mhlen);
|
||||||
*mnext = m;
|
*mnext = m;
|
||||||
mnext = &m->m_nextpkt;
|
mnext = &m->m_nextpkt;
|
||||||
STAT(ipstat.ips_ofragments++);
|
ipstat.ips_ofragments++;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Update first fragment by trimming what's been copied out
|
* Update first fragment by trimming what's been copied out
|
||||||
* and updating header, then send each fragment (in order).
|
* and updating header, then send each fragment (in order).
|
||||||
*/
|
*/
|
||||||
m = m0;
|
m = m0;
|
||||||
m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len);
|
m_adj(m, hlen + firstlen - ip->ip_len);
|
||||||
ip->ip_len = htons((u_int16_t)m->m_len);
|
ip->ip_len = htons((u_int16_t)m->m_len);
|
||||||
ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
|
ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF));
|
||||||
ip->ip_sum = 0;
|
ip->ip_sum = 0;
|
||||||
|
@ -197,7 +190,7 @@ sendorfree:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
STAT(ipstat.ips_fragmented++);
|
ipstat.ips_fragmented++;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
|
@ -1,33 +1,39 @@
|
||||||
#ifndef _LIBSLIRP_H
|
#ifndef _LIBSLIRP_H
|
||||||
#define _LIBSLIRP_H
|
#define _LIBSLIRP_H
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
int inet_aton(const char *cp, struct in_addr *ia);
|
||||||
|
#else
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void slirp_init(void);
|
int slirp_init(void);
|
||||||
|
|
||||||
void slirp_select_fill(int *pnfds,
|
int slirp_select_fill(int *pnfds,
|
||||||
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||||
|
|
||||||
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds);
|
||||||
|
|
||||||
void slirp_input(const uint8_t *pkt, int pkt_len);
|
void slirp_input(const uint8 *pkt, int pkt_len);
|
||||||
|
|
||||||
/* you must provide the following functions: */
|
/* you must provide the following functions: */
|
||||||
int slirp_can_output(void);
|
int slirp_can_output(void);
|
||||||
void slirp_output(const uint8_t *pkt, int pkt_len);
|
void slirp_output(const uint8 *pkt, int pkt_len);
|
||||||
|
|
||||||
int slirp_redir(int is_udp, int host_port,
|
int slirp_redir(int is_udp, int host_port,
|
||||||
struct in_addr guest_addr, int guest_port);
|
struct in_addr guest_addr, int guest_port);
|
||||||
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
|
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
|
||||||
int guest_port);
|
int guest_port);
|
||||||
|
|
||||||
extern const char *tftp_prefix;
|
extern const char *tftp_prefix;
|
||||||
extern char slirp_hostname[33];
|
extern char slirp_hostname[33];
|
||||||
|
|
||||||
void slirp_stats(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ extern char *username;
|
||||||
extern char *socket_path;
|
extern char *socket_path;
|
||||||
extern int towrite_max;
|
extern int towrite_max;
|
||||||
extern int ppp_exit;
|
extern int ppp_exit;
|
||||||
|
extern int so_options;
|
||||||
extern int tcp_keepintvl;
|
extern int tcp_keepintvl;
|
||||||
extern uint8_t client_ethaddr[6];
|
extern uint8_t client_ethaddr[6];
|
||||||
|
|
||||||
|
|
|
@ -15,49 +15,54 @@
|
||||||
* the flags
|
* the flags
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
struct mbuf *mbutl;
|
struct mbuf *mbutl;
|
||||||
char *mclrefcnt;
|
char *mclrefcnt;
|
||||||
int mbuf_alloced = 0;
|
int mbuf_alloced = 0;
|
||||||
struct mbuf m_freelist, m_usedlist;
|
struct mbuf m_freelist, m_usedlist;
|
||||||
#define MBUF_THRESH 30
|
int mbuf_thresh = 30;
|
||||||
int mbuf_max = 0;
|
int mbuf_max = 0;
|
||||||
|
size_t msize;
|
||||||
|
|
||||||
/*
|
void m_init()
|
||||||
* Find a nice value for msize
|
|
||||||
* XXX if_maxlinkhdr already in mtu
|
|
||||||
*/
|
|
||||||
#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
|
|
||||||
|
|
||||||
void
|
|
||||||
m_init()
|
|
||||||
{
|
{
|
||||||
m_freelist.m_next = m_freelist.m_prev = &m_freelist;
|
m_freelist.m_next = m_freelist.m_prev = &m_freelist;
|
||||||
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
|
m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
|
||||||
|
msize_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void msize_init()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Find a nice value for msize
|
||||||
|
* XXX if_maxlinkhdr already in mtu
|
||||||
|
*/
|
||||||
|
msize = (if_mtu>if_mru?if_mtu:if_mru) +
|
||||||
|
if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get an mbuf from the free list, if there are none
|
* Get an mbuf from the free list, if there are none
|
||||||
* malloc one
|
* malloc one
|
||||||
*
|
*
|
||||||
* Because fragmentation can occur if we alloc new mbufs and
|
* Because fragmentation can occur if we alloc new mbufs and
|
||||||
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
|
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
|
||||||
* which tells m_free to actually free() it
|
* which tells m_free to actually free() it
|
||||||
*/
|
*/
|
||||||
struct mbuf *
|
struct mbuf *m_get()
|
||||||
m_get()
|
|
||||||
{
|
{
|
||||||
register struct mbuf *m;
|
register struct mbuf *m;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
DEBUG_CALL("m_get");
|
DEBUG_CALL("m_get");
|
||||||
|
|
||||||
if (m_freelist.m_next == &m_freelist) {
|
if (m_freelist.m_next == &m_freelist) {
|
||||||
m = (struct mbuf *)malloc(MSIZE);
|
m = (struct mbuf *)malloc(msize);
|
||||||
if (m == NULL) goto end_error;
|
if (m == NULL) goto end_error;
|
||||||
mbuf_alloced++;
|
mbuf_alloced++;
|
||||||
if (mbuf_alloced > MBUF_THRESH)
|
if (mbuf_alloced > mbuf_thresh)
|
||||||
flags = M_DOFREE;
|
flags = M_DOFREE;
|
||||||
if (mbuf_alloced > mbuf_max)
|
if (mbuf_alloced > mbuf_max)
|
||||||
mbuf_max = mbuf_alloced;
|
mbuf_max = mbuf_alloced;
|
||||||
|
@ -65,13 +70,13 @@ m_get()
|
||||||
m = m_freelist.m_next;
|
m = m_freelist.m_next;
|
||||||
remque(m);
|
remque(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert it in the used list */
|
/* Insert it in the used list */
|
||||||
insque(m,&m_usedlist);
|
insque(m,&m_usedlist);
|
||||||
m->m_flags = (flags | M_USEDLIST);
|
m->m_flags = (flags | M_USEDLIST);
|
||||||
|
|
||||||
/* Initialise it */
|
/* Initialise it */
|
||||||
m->m_size = MSIZE - sizeof(struct m_hdr);
|
m->m_size = msize - sizeof(struct m_hdr);
|
||||||
m->m_data = m->m_dat;
|
m->m_data = m->m_dat;
|
||||||
m->m_len = 0;
|
m->m_len = 0;
|
||||||
m->m_nextpkt = 0;
|
m->m_nextpkt = 0;
|
||||||
|
@ -81,19 +86,17 @@ end_error:
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void m_free(struct mbuf *m)
|
||||||
m_free(m)
|
|
||||||
struct mbuf *m;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
DEBUG_CALL("m_free");
|
DEBUG_CALL("m_free");
|
||||||
DEBUG_ARG("m = %lx", (long )m);
|
DEBUG_ARG("m = %lx", (long )m);
|
||||||
|
|
||||||
if(m) {
|
if(m) {
|
||||||
/* Remove from m_usedlist */
|
/* Remove from m_usedlist */
|
||||||
if (m->m_flags & M_USEDLIST)
|
if (m->m_flags & M_USEDLIST)
|
||||||
remque(m);
|
remque(m);
|
||||||
|
|
||||||
/* If it's M_EXT, free() it */
|
/* If it's M_EXT, free() it */
|
||||||
if (m->m_flags & M_EXT)
|
if (m->m_flags & M_EXT)
|
||||||
free(m->m_ext);
|
free(m->m_ext);
|
||||||
|
@ -116,16 +119,14 @@ m_free(m)
|
||||||
* the other.. if result is too big for one mbuf, malloc()
|
* the other.. if result is too big for one mbuf, malloc()
|
||||||
* an M_EXT data segment
|
* an M_EXT data segment
|
||||||
*/
|
*/
|
||||||
void
|
void m_cat(register struct mbuf *m, register struct mbuf *n)
|
||||||
m_cat(m, n)
|
|
||||||
register struct mbuf *m, *n;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If there's no room, realloc
|
* If there's no room, realloc
|
||||||
*/
|
*/
|
||||||
if (M_FREEROOM(m) < n->m_len)
|
if (M_FREEROOM(m) < n->m_len)
|
||||||
m_inc(m,m->m_size+MINCSIZE);
|
m_inc(m,m->m_size+MINCSIZE);
|
||||||
|
|
||||||
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
|
memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
|
||||||
m->m_len += n->m_len;
|
m->m_len += n->m_len;
|
||||||
|
|
||||||
|
@ -134,23 +135,20 @@ m_cat(m, n)
|
||||||
|
|
||||||
|
|
||||||
/* make m size bytes large */
|
/* make m size bytes large */
|
||||||
void
|
void m_inc(struct mbuf *m, u_int size)
|
||||||
m_inc(m, size)
|
|
||||||
struct mbuf *m;
|
|
||||||
int size;
|
|
||||||
{
|
{
|
||||||
int datasize;
|
int datasize;
|
||||||
|
|
||||||
/* some compiles throw up on gotos. This one we can fake. */
|
/* some compiles throw up on gotos. This one we can fake. */
|
||||||
if(m->m_size>size) return;
|
if(m->m_size>size) return;
|
||||||
|
|
||||||
if (m->m_flags & M_EXT) {
|
if (m->m_flags & M_EXT) {
|
||||||
datasize = m->m_data - m->m_ext;
|
datasize = m->m_data - m->m_ext;
|
||||||
m->m_ext = (char *)realloc(m->m_ext,size);
|
m->m_ext = (char *)realloc(m->m_ext,size);
|
||||||
/* if (m->m_ext == NULL)
|
/* if (m->m_ext == NULL)
|
||||||
* return (struct mbuf *)NULL;
|
* return (struct mbuf *)NULL;
|
||||||
*/
|
*/
|
||||||
m->m_data = m->m_ext + datasize;
|
m->m_data = m->m_ext + datasize;
|
||||||
} else {
|
} else {
|
||||||
char *dat;
|
char *dat;
|
||||||
datasize = m->m_data - m->m_dat;
|
datasize = m->m_data - m->m_dat;
|
||||||
|
@ -159,22 +157,19 @@ m_inc(m, size)
|
||||||
* return (struct mbuf *)NULL;
|
* return (struct mbuf *)NULL;
|
||||||
*/
|
*/
|
||||||
memcpy(dat, m->m_dat, m->m_size);
|
memcpy(dat, m->m_dat, m->m_size);
|
||||||
|
|
||||||
m->m_ext = dat;
|
m->m_ext = dat;
|
||||||
m->m_data = m->m_ext + datasize;
|
m->m_data = m->m_ext + datasize;
|
||||||
m->m_flags |= M_EXT;
|
m->m_flags |= M_EXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->m_size = size;
|
m->m_size = size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void m_adj(struct mbuf *m, int len)
|
||||||
m_adj(m, len)
|
|
||||||
struct mbuf *m;
|
|
||||||
int len;
|
|
||||||
{
|
{
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -194,9 +189,7 @@ m_adj(m, len)
|
||||||
* Copy len bytes from m, starting off bytes into n
|
* Copy len bytes from m, starting off bytes into n
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
m_copy(n, m, off, len)
|
m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len)
|
||||||
struct mbuf *n, *m;
|
|
||||||
int off, len;
|
|
||||||
{
|
{
|
||||||
if (len > M_FREEROOM(n))
|
if (len > M_FREEROOM(n))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -212,12 +205,10 @@ m_copy(n, m, off, len)
|
||||||
* XXX This is a kludge, I should eliminate the need for it
|
* XXX This is a kludge, I should eliminate the need for it
|
||||||
* Fortunately, it's not used often
|
* Fortunately, it's not used often
|
||||||
*/
|
*/
|
||||||
struct mbuf *
|
struct mbuf *dtom(void *dat)
|
||||||
dtom(dat)
|
|
||||||
void *dat;
|
|
||||||
{
|
{
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
DEBUG_CALL("dtom");
|
DEBUG_CALL("dtom");
|
||||||
DEBUG_ARG("dat = %lx", (long )dat);
|
DEBUG_ARG("dat = %lx", (long )dat);
|
||||||
|
|
||||||
|
@ -231,9 +222,9 @@ dtom(dat)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_ERROR((dfd, "dtom failed"));
|
DEBUG_ERROR((dfd, "dtom failed"));
|
||||||
|
|
||||||
return (struct mbuf *)0;
|
return (struct mbuf *)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -67,14 +63,14 @@ struct m_hdr {
|
||||||
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
|
struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */
|
||||||
int mh_flags; /* Misc flags */
|
int mh_flags; /* Misc flags */
|
||||||
|
|
||||||
int mh_size; /* Size of data */
|
size_t mh_size; /* Size of data */
|
||||||
struct socket *mh_so;
|
struct socket *mh_so;
|
||||||
|
|
||||||
caddr_t mh_data; /* Location of data */
|
caddr_t mh_data; /* Location of data */
|
||||||
int mh_len; /* Amount of data in this mbuf */
|
size_t mh_len; /* Amount of data in this mbuf */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How much room is in the mbuf, from m_data to the end of the mbuf
|
* How much room is in the mbuf, from m_data to the end of the mbuf
|
||||||
*/
|
*/
|
||||||
#define M_ROOM(m) ((m->m_flags & M_EXT)? \
|
#define M_ROOM(m) ((m->m_flags & M_EXT)? \
|
||||||
|
@ -126,7 +122,7 @@ struct mbuf {
|
||||||
|
|
||||||
struct mbstat {
|
struct mbstat {
|
||||||
int mbs_alloced; /* Number of mbufs allocated */
|
int mbs_alloced; /* Number of mbufs allocated */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct mbstat mbstat;
|
extern struct mbstat mbstat;
|
||||||
|
@ -134,13 +130,14 @@ extern int mbuf_alloced;
|
||||||
extern struct mbuf m_freelist, m_usedlist;
|
extern struct mbuf m_freelist, m_usedlist;
|
||||||
extern int mbuf_max;
|
extern int mbuf_max;
|
||||||
|
|
||||||
void m_init _P((void));
|
void m_init(void);
|
||||||
struct mbuf * m_get _P((void));
|
void msize_init(void);
|
||||||
void m_free _P((struct mbuf *));
|
struct mbuf * m_get(void);
|
||||||
void m_cat _P((register struct mbuf *, register struct mbuf *));
|
void m_free(struct mbuf *);
|
||||||
void m_inc _P((struct mbuf *, int));
|
void m_cat(register struct mbuf *, register struct mbuf *);
|
||||||
void m_adj _P((struct mbuf *, int));
|
void m_inc(struct mbuf *, u_int);
|
||||||
int m_copy _P((struct mbuf *, struct mbuf *, int, int));
|
void m_adj(struct mbuf *, int);
|
||||||
struct mbuf * dtom _P((void *));
|
int m_copy(struct mbuf *, struct mbuf *, u_int, u_int);
|
||||||
|
struct mbuf * dtom(void *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WANT_SYS_IOCTL_H
|
#define WANT_SYS_IOCTL_H
|
||||||
|
#include <stdlib.h>
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
u_int curtime, time_fasttimo, last_slowtimo;
|
u_int curtime, time_fasttimo, last_slowtimo, detach_time;
|
||||||
|
u_int detach_wait = 600000; /* 10 minutes */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int x_port = -1;
|
int x_port = -1;
|
||||||
int x_display = 0;
|
int x_display = 0;
|
||||||
int x_screen = 0;
|
int x_screen = 0;
|
||||||
|
|
||||||
int
|
int show_x(char *buff, struct socket *inso)
|
||||||
show_x(buff, inso)
|
|
||||||
char *buff;
|
|
||||||
struct socket *inso;
|
|
||||||
{
|
{
|
||||||
if (x_port < 0) {
|
if (x_port < 0) {
|
||||||
lprint("X Redir: X not being redirected.\r\n");
|
lprint("X Redir: X not being redirected.\r\n");
|
||||||
|
@ -30,7 +29,7 @@ show_x(buff, inso)
|
||||||
if (x_display)
|
if (x_display)
|
||||||
lprint("X Redir: Redirecting to display %d\r\n", x_display);
|
lprint("X Redir: Redirecting to display %d\r\n", x_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CFG_OK;
|
return CFG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,15 +37,10 @@ show_x(buff, inso)
|
||||||
/*
|
/*
|
||||||
* XXX Allow more than one X redirection?
|
* XXX Allow more than one X redirection?
|
||||||
*/
|
*/
|
||||||
void
|
void redir_x(u_int32_t inaddr, int start_port, int display, int screen)
|
||||||
redir_x(inaddr, start_port, display, screen)
|
|
||||||
u_int32_t inaddr;
|
|
||||||
int start_port;
|
|
||||||
int display;
|
|
||||||
int screen;
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (x_port >= 0) {
|
if (x_port >= 0) {
|
||||||
lprint("X Redir: X already being redirected.\r\n");
|
lprint("X Redir: X already being redirected.\r\n");
|
||||||
show_x(0, 0);
|
show_x(0, 0);
|
||||||
|
@ -67,34 +61,33 @@ redir_x(inaddr, start_port, display, screen)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_INET_ATON
|
#ifndef HAVE_INET_ATON
|
||||||
int
|
int inet_aton(const char *cp, struct in_addr *ia)
|
||||||
inet_aton(cp, ia)
|
|
||||||
const char *cp;
|
|
||||||
struct in_addr *ia;
|
|
||||||
{
|
{
|
||||||
u_int32_t addr = inet_addr(cp);
|
return inet_pton(AF_INET, cp, &ia->s_addr);
|
||||||
if (addr == 0xffffffff)
|
|
||||||
return 0;
|
|
||||||
ia->s_addr = addr;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get our IP address and put it in our_addr
|
* Get our IP address and put it in our_addr
|
||||||
*/
|
*/
|
||||||
void
|
void getouraddr()
|
||||||
getouraddr()
|
|
||||||
{
|
{
|
||||||
char buff[256];
|
char buff[256];
|
||||||
struct hostent *he = NULL;
|
|
||||||
|
|
||||||
if (gethostname(buff,256) == 0)
|
if (gethostname(buff, sizeof(buff)) == 0)
|
||||||
he = gethostbyname(buff);
|
{
|
||||||
if (he)
|
struct addrinfo hints = { 0 };
|
||||||
our_addr = *(struct in_addr *)he->h_addr;
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
if (our_addr.s_addr == 0)
|
hints.ai_family = AF_INET;
|
||||||
our_addr.s_addr = loopback_addr.s_addr;
|
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 SIZEOF_CHAR_P == 8
|
#if SIZEOF_CHAR_P == 8
|
||||||
|
@ -104,10 +97,7 @@ struct quehead_32 {
|
||||||
u_int32_t qh_rlink;
|
u_int32_t qh_rlink;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
inline void insque_32(void *a, void *b)
|
||||||
insque_32(a, b)
|
|
||||||
void *a;
|
|
||||||
void *b;
|
|
||||||
{
|
{
|
||||||
register struct quehead_32 *element = (struct quehead_32 *) a;
|
register struct quehead_32 *element = (struct quehead_32 *) a;
|
||||||
register struct quehead_32 *head = (struct quehead_32 *) b;
|
register struct quehead_32 *head = (struct quehead_32 *) b;
|
||||||
|
@ -118,9 +108,7 @@ insque_32(a, b)
|
||||||
= (u_int32_t)element;
|
= (u_int32_t)element;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void remque_32(void *a)
|
||||||
remque_32(a)
|
|
||||||
void *a;
|
|
||||||
{
|
{
|
||||||
register struct quehead_32 *element = (struct quehead_32 *) a;
|
register struct quehead_32 *element = (struct quehead_32 *) a;
|
||||||
((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
||||||
|
@ -135,9 +123,7 @@ struct quehead {
|
||||||
struct quehead *qh_rlink;
|
struct quehead *qh_rlink;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
void insque(void *a, void *b)
|
||||||
insque(a, b)
|
|
||||||
void *a, *b;
|
|
||||||
{
|
{
|
||||||
register struct quehead *element = (struct quehead *) a;
|
register struct quehead *element = (struct quehead *) a;
|
||||||
register struct quehead *head = (struct quehead *) b;
|
register struct quehead *head = (struct quehead *) b;
|
||||||
|
@ -148,9 +134,7 @@ insque(a, b)
|
||||||
= (struct quehead *)element;
|
= (struct quehead *)element;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
void remque(void *a)
|
||||||
remque(a)
|
|
||||||
void *a;
|
|
||||||
{
|
{
|
||||||
register struct quehead *element = (struct quehead *) a;
|
register struct quehead *element = (struct quehead *) a;
|
||||||
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
||||||
|
@ -162,22 +146,16 @@ remque(a)
|
||||||
/* #endif */
|
/* #endif */
|
||||||
|
|
||||||
|
|
||||||
int
|
int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port)
|
||||||
add_exec(ex_ptr, do_pty, exec, addr, port)
|
|
||||||
struct ex_list **ex_ptr;
|
|
||||||
int do_pty;
|
|
||||||
char *exec;
|
|
||||||
int addr;
|
|
||||||
int port;
|
|
||||||
{
|
{
|
||||||
struct ex_list *tmp_ptr;
|
struct ex_list *tmp_ptr;
|
||||||
|
|
||||||
/* First, check if the port is "bound" */
|
/* First, check if the port is "bound" */
|
||||||
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
||||||
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
|
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_ptr = *ex_ptr;
|
tmp_ptr = *ex_ptr;
|
||||||
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
|
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
|
||||||
(*ex_ptr)->ex_fport = port;
|
(*ex_ptr)->ex_fport = port;
|
||||||
|
@ -197,9 +175,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port)
|
||||||
extern int sys_nerr;
|
extern int sys_nerr;
|
||||||
extern char *sys_errlist[];
|
extern char *sys_errlist[];
|
||||||
|
|
||||||
char *
|
char *strerror(int error)
|
||||||
strerror(error)
|
|
||||||
int error;
|
|
||||||
{
|
{
|
||||||
if (error < sys_nerr)
|
if (error < sys_nerr)
|
||||||
return sys_errlist[error];
|
return sys_errlist[error];
|
||||||
|
@ -212,8 +188,7 @@ strerror(error)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
int
|
int fork_exec(struct socket *so, char *ex, int do_pty)
|
||||||
fork_exec(struct socket *so, const char *ex, int do_pty)
|
|
||||||
{
|
{
|
||||||
/* not implemented */
|
/* not implemented */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -221,16 +196,13 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef CONFIG_QEMU
|
int slirp_openpty(int *amaster, int *aslave)
|
||||||
int
|
|
||||||
slirp_openpty(amaster, aslave)
|
|
||||||
int *amaster, *aslave;
|
|
||||||
{
|
{
|
||||||
register int master, slave;
|
register int master, slave;
|
||||||
|
|
||||||
#ifdef HAVE_GRANTPT
|
#ifdef HAVE_GRANTPT
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
|
if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
|
||||||
grantpt(master) < 0 ||
|
grantpt(master) < 0 ||
|
||||||
unlockpt(master) < 0 ||
|
unlockpt(master) < 0 ||
|
||||||
|
@ -238,7 +210,7 @@ slirp_openpty(amaster, aslave)
|
||||||
close(master);
|
close(master);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((slave = open(ptr, O_RDWR)) < 0 ||
|
if ((slave = open(ptr, O_RDWR)) < 0 ||
|
||||||
ioctl(slave, I_PUSH, "ptem") < 0 ||
|
ioctl(slave, I_PUSH, "ptem") < 0 ||
|
||||||
ioctl(slave, I_PUSH, "ldterm") < 0 ||
|
ioctl(slave, I_PUSH, "ldterm") < 0 ||
|
||||||
|
@ -247,16 +219,16 @@ slirp_openpty(amaster, aslave)
|
||||||
close(slave);
|
close(slave);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*amaster = master;
|
*amaster = master;
|
||||||
*aslave = slave;
|
*aslave = slave;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static char line[] = "/dev/ptyXX";
|
static char line[] = "/dev/ptyXX";
|
||||||
register const char *cp1, *cp2;
|
register const char *cp1, *cp2;
|
||||||
|
|
||||||
for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
|
for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
|
||||||
line[8] = *cp1;
|
line[8] = *cp1;
|
||||||
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
|
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
|
||||||
|
@ -286,7 +258,6 @@ slirp_openpty(amaster, aslave)
|
||||||
return (-1);
|
return (-1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX This is ugly
|
* XXX This is ugly
|
||||||
|
@ -294,57 +265,53 @@ slirp_openpty(amaster, aslave)
|
||||||
* process, which connects to this socket, after which we
|
* process, which connects to this socket, after which we
|
||||||
* exec the wanted program. If something (strange) happens,
|
* exec the wanted program. If something (strange) happens,
|
||||||
* the accept() call could block us forever.
|
* the accept() call could block us forever.
|
||||||
*
|
*
|
||||||
* do_pty = 0 Fork/exec inetd style
|
* do_pty = 0 Fork/exec inetd style
|
||||||
* do_pty = 1 Fork/exec using slirp.telnetd
|
* do_pty = 1 Fork/exec using slirp.telnetd
|
||||||
* do_ptr = 2 Fork/exec using pty
|
* do_ptr = 2 Fork/exec using pty
|
||||||
*/
|
*/
|
||||||
int
|
int fork_exec(struct socket *so, char *ex, int do_pty)
|
||||||
fork_exec(struct socket *so, const char *ex, int do_pty)
|
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
int opt;
|
int opt;
|
||||||
int master = -1;
|
int master;
|
||||||
char *argv[256];
|
char *argv[256];
|
||||||
#if 0
|
#if 0
|
||||||
char buff[256];
|
char buff[256];
|
||||||
#endif
|
#endif
|
||||||
/* don't want to clobber the original */
|
/* don't want to clobber the original */
|
||||||
char *bptr;
|
char *bptr;
|
||||||
const char *curarg;
|
char *curarg;
|
||||||
int c, i, ret;
|
int c, i, ret;
|
||||||
|
|
||||||
DEBUG_CALL("fork_exec");
|
DEBUG_CALL("fork_exec");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("ex = %lx", (long)ex);
|
DEBUG_ARG("ex = %lx", (long)ex);
|
||||||
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
DEBUG_ARG("do_pty = %lx", (long)do_pty);
|
||||||
|
|
||||||
if (do_pty == 2) {
|
if (do_pty == 2) {
|
||||||
#if 0
|
|
||||||
if (slirp_openpty(&master, &s) == -1) {
|
if (slirp_openpty(&master, &s) == -1) {
|
||||||
lprint("Error: openpty failed: %s\n", strerror(errno));
|
lprint("Error: openpty failed: %s\n", strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = 0;
|
addr.sin_port = 0;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
|
||||||
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
|
||||||
listen(s, 1) < 0) {
|
listen(s, 1) < 0) {
|
||||||
lprint("Error: inet socket: %s\n", strerror(errno));
|
lprint("Error: inet socket: %s\n", strerror(errno));
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(fork()) {
|
switch(fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
lprint("Error: fork failed: %s\n", strerror(errno));
|
lprint("Error: fork failed: %s\n", strerror(errno));
|
||||||
|
@ -352,7 +319,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
if (do_pty == 2)
|
if (do_pty == 2)
|
||||||
close(master);
|
close(master);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
/* Set the DISPLAY */
|
/* Set the DISPLAY */
|
||||||
if (do_pty == 2) {
|
if (do_pty == 2) {
|
||||||
|
@ -374,7 +341,7 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
||||||
} while (ret < 0 && errno == EINTR);
|
} while (ret < 0 && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (x_port >= 0) {
|
if (x_port >= 0) {
|
||||||
#ifdef HAVE_SETENV
|
#ifdef HAVE_SETENV
|
||||||
|
@ -385,13 +352,13 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
putenv(buff);
|
putenv(buff);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
dup2(s, 0);
|
dup2(s, 0);
|
||||||
dup2(s, 1);
|
dup2(s, 1);
|
||||||
dup2(s, 2);
|
dup2(s, 2);
|
||||||
for (s = getdtablesize() - 1; s >= 3; s--)
|
for (s = 3; s <= 255; s++)
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
bptr = strdup(ex); /* No need to free() this */
|
bptr = strdup(ex); /* No need to free() this */
|
||||||
if (do_pty == 1) {
|
if (do_pty == 1) {
|
||||||
|
@ -409,21 +376,21 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
*bptr++ = (char)0;
|
*bptr++ = (char)0;
|
||||||
argv[i++] = strdup(curarg);
|
argv[i++] = strdup(curarg);
|
||||||
} while (c);
|
} while (c);
|
||||||
|
|
||||||
argv[i] = 0;
|
argv[i] = 0;
|
||||||
execvp(argv[0], argv);
|
execvp(argv[0], argv);
|
||||||
|
|
||||||
/* Ooops, failed, let's tell the user why */
|
/* Ooops, failed, let's tell the user why */
|
||||||
{
|
{
|
||||||
char buff[256];
|
char buff[256];
|
||||||
|
|
||||||
sprintf(buff, "Error: execvp of %s failed: %s\n",
|
sprintf(buff, "Error: execvp of %s failed: %s\n",
|
||||||
argv[0], strerror(errno));
|
argv[0], strerror(errno));
|
||||||
write(2, buff, strlen(buff)+1);
|
write(2, buff, strlen(buff)+1);
|
||||||
}
|
}
|
||||||
close(0); close(1); close(2); /* XXX */
|
close(0); close(1); close(2); /* XXX */
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (do_pty == 2) {
|
if (do_pty == 2) {
|
||||||
close(s);
|
close(s);
|
||||||
|
@ -446,36 +413,32 @@ fork_exec(struct socket *so, const char *ex, int do_pty)
|
||||||
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||||
}
|
}
|
||||||
fd_nonblock(so->s);
|
fd_nonblock(so->s);
|
||||||
|
|
||||||
/* Append the telnet options now */
|
/* Append the telnet options now */
|
||||||
if (so->so_m != 0 && do_pty == 1) {
|
if (so->so_m != 0 && do_pty == 1) {
|
||||||
sbappend(so, so->so_m);
|
sbappend(so, so->so_m);
|
||||||
so->so_m = 0;
|
so->so_m = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRDUP
|
#ifndef HAVE_STRDUP
|
||||||
char *
|
char *strdup(const char *str)
|
||||||
strdup(str)
|
|
||||||
const char *str;
|
|
||||||
{
|
{
|
||||||
char *bptr;
|
char *bptr;
|
||||||
|
|
||||||
bptr = (char *)malloc(strlen(str)+1);
|
bptr = (char *)malloc(strlen(str)+1);
|
||||||
strcpy(bptr, str);
|
strcpy(bptr, str);
|
||||||
|
|
||||||
return bptr;
|
return bptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void
|
void snooze_hup(int num)
|
||||||
snooze_hup(num)
|
|
||||||
int num;
|
|
||||||
{
|
{
|
||||||
int s, ret;
|
int s, ret;
|
||||||
#ifndef NO_UNIX_SOCKETS
|
#ifndef NO_UNIX_SOCKETS
|
||||||
|
@ -483,7 +446,7 @@ snooze_hup(num)
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_in sock_in;
|
struct sockaddr_in sock_in;
|
||||||
char buff[256];
|
char buff[256];
|
||||||
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
if (slirp_socket_passwd) {
|
if (slirp_socket_passwd) {
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
@ -513,51 +476,48 @@ snooze_hup(num)
|
||||||
#endif
|
#endif
|
||||||
slirp_exit(0);
|
slirp_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void snooze()
|
||||||
snooze()
|
|
||||||
{
|
{
|
||||||
sigset_t s;
|
sigset_t s;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Don't need our data anymore */
|
/* Don't need our data anymore */
|
||||||
/* XXX This makes SunOS barf */
|
/* XXX This makes SunOS barf */
|
||||||
/* brk(0); */
|
/* brk(0); */
|
||||||
|
|
||||||
/* Close all fd's */
|
/* Close all fd's */
|
||||||
for (i = 255; i >= 0; i--)
|
for (i = 255; i >= 0; i--)
|
||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
signal(SIGQUIT, slirp_exit);
|
signal(SIGQUIT, slirp_exit);
|
||||||
signal(SIGHUP, snooze_hup);
|
signal(SIGHUP, snooze_hup);
|
||||||
sigemptyset(&s);
|
sigemptyset(&s);
|
||||||
|
|
||||||
/* Wait for any signal */
|
/* Wait for any signal */
|
||||||
sigsuspend(&s);
|
sigsuspend(&s);
|
||||||
|
|
||||||
/* Just in case ... */
|
/* Just in case ... */
|
||||||
exit(255);
|
exit(255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void relay(int s)
|
||||||
relay(s)
|
|
||||||
int s;
|
|
||||||
{
|
{
|
||||||
char buf[8192];
|
char buf[8192];
|
||||||
int n;
|
int n;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
struct ttys *ttyp;
|
struct ttys *ttyp;
|
||||||
|
|
||||||
/* Don't need our data anymore */
|
/* Don't need our data anymore */
|
||||||
/* XXX This makes SunOS barf */
|
/* XXX This makes SunOS barf */
|
||||||
/* brk(0); */
|
/* brk(0); */
|
||||||
|
|
||||||
signal(SIGQUIT, slirp_exit);
|
signal(SIGQUIT, slirp_exit);
|
||||||
signal(SIGHUP, slirp_exit);
|
signal(SIGHUP, slirp_exit);
|
||||||
signal(SIGINT, slirp_exit);
|
signal(SIGINT, slirp_exit);
|
||||||
signal(SIGTERM, slirp_exit);
|
signal(SIGTERM, slirp_exit);
|
||||||
|
|
||||||
/* Fudge to get term_raw and term_restore to work */
|
/* Fudge to get term_raw and term_restore to work */
|
||||||
if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
|
if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
|
||||||
lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
|
lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
|
||||||
|
@ -566,18 +526,18 @@ relay(s)
|
||||||
ttyp->fd = 0;
|
ttyp->fd = 0;
|
||||||
ttyp->flags |= TTY_CTTY;
|
ttyp->flags |= TTY_CTTY;
|
||||||
term_raw(ttyp);
|
term_raw(ttyp);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
|
|
||||||
FD_SET(0, &readfds);
|
FD_SET(0, &readfds);
|
||||||
FD_SET(s, &readfds);
|
FD_SET(s, &readfds);
|
||||||
|
|
||||||
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
|
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
|
||||||
|
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
slirp_exit(0);
|
slirp_exit(0);
|
||||||
|
|
||||||
if (FD_ISSET(0, &readfds)) {
|
if (FD_ISSET(0, &readfds)) {
|
||||||
n = read(0, buf, 8192);
|
n = read(0, buf, 8192);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
|
@ -586,7 +546,7 @@ relay(s)
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
slirp_exit(0);
|
slirp_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FD_ISSET(s, &readfds)) {
|
if (FD_ISSET(s, &readfds)) {
|
||||||
n = read(s, buf, 8192);
|
n = read(s, buf, 8192);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
|
@ -596,43 +556,20 @@ relay(s)
|
||||||
slirp_exit(0);
|
slirp_exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just in case.... */
|
/* Just in case.... */
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_QEMU
|
int (*lprint_print)(void *, const char *, va_list);
|
||||||
extern void term_vprintf(const char *fmt, va_list ap);
|
char *lprint_ptr, *lprint_ptr2, **lprint_arg;
|
||||||
|
|
||||||
void lprint(const char *format, ...)
|
void lprint(const char *format, ...)
|
||||||
{
|
|
||||||
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;
|
va_list args;
|
||||||
|
|
||||||
#ifdef __STDC__
|
va_start(args, format);
|
||||||
va_start(args, format);
|
|
||||||
#else
|
|
||||||
char *format;
|
|
||||||
va_start(args);
|
|
||||||
format = va_arg(args, char *);
|
|
||||||
#endif
|
|
||||||
#if 0
|
#if 0
|
||||||
/* If we're printing to an sbuf, make sure there's enough room */
|
/* If we're printing to an sbuf, make sure there's enough room */
|
||||||
/* XXX +100? */
|
/* XXX +100? */
|
||||||
|
@ -642,33 +579,33 @@ lprint(va_alist) va_dcl
|
||||||
int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
|
int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
|
||||||
int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
|
int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
|
||||||
int deltap = lprint_ptr - lprint_sb->sb_data;
|
int deltap = lprint_ptr - lprint_sb->sb_data;
|
||||||
|
|
||||||
lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
|
lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
|
||||||
lprint_sb->sb_datalen + TCP_SNDSPACE);
|
lprint_sb->sb_datalen + TCP_SNDSPACE);
|
||||||
|
|
||||||
/* Adjust all values */
|
/* Adjust all values */
|
||||||
lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
|
lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
|
||||||
lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
|
lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
|
||||||
lprint_ptr = lprint_sb->sb_data + deltap;
|
lprint_ptr = lprint_sb->sb_data + deltap;
|
||||||
|
|
||||||
lprint_sb->sb_datalen += TCP_SNDSPACE;
|
lprint_sb->sb_datalen += TCP_SNDSPACE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (lprint_print)
|
if (lprint_print)
|
||||||
lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
|
lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
|
||||||
|
|
||||||
/* Check if they want output to be logged to file as well */
|
/* Check if they want output to be logged to file as well */
|
||||||
if (lfd) {
|
if (lfd) {
|
||||||
/*
|
/*
|
||||||
* Remove \r's
|
* Remove \r's
|
||||||
* otherwise you'll get ^M all over the file
|
* otherwise you'll get ^M all over the file
|
||||||
*/
|
*/
|
||||||
int len = strlen(format);
|
int len = strlen(format);
|
||||||
char *bptr1, *bptr2;
|
char *bptr1, *bptr2;
|
||||||
|
|
||||||
bptr1 = bptr2 = strdup(format);
|
bptr1 = bptr2 = strdup(format);
|
||||||
|
|
||||||
while (len--) {
|
while (len--) {
|
||||||
if (*bptr1 == '\r')
|
if (*bptr1 == '\r')
|
||||||
memcpy(bptr1, bptr1+1, len+1);
|
memcpy(bptr1, bptr1+1, len+1);
|
||||||
|
@ -681,9 +618,7 @@ lprint(va_alist) va_dcl
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void add_emu(char *buff)
|
||||||
add_emu(buff)
|
|
||||||
char *buff;
|
|
||||||
{
|
{
|
||||||
u_int lport, fport;
|
u_int lport, fport;
|
||||||
u_int8_t tos = 0, emu = 0;
|
u_int8_t tos = 0, emu = 0;
|
||||||
|
@ -691,12 +626,12 @@ add_emu(buff)
|
||||||
char *buff3 = buff4;
|
char *buff3 = buff4;
|
||||||
struct emu_t *emup;
|
struct emu_t *emup;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
|
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
|
||||||
lprint("Error: Bad arguments\r\n");
|
lprint("Error: Bad arguments\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
|
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
|
||||||
lport = 0;
|
lport = 0;
|
||||||
if (sscanf(buff1, "%d", &fport) != 1) {
|
if (sscanf(buff1, "%d", &fport) != 1) {
|
||||||
|
@ -704,7 +639,7 @@ add_emu(buff)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
|
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
|
||||||
buff3 = 0;
|
buff3 = 0;
|
||||||
if (sscanf(buff2, "%256s", buff1) != 1) {
|
if (sscanf(buff2, "%256s", buff1) != 1) {
|
||||||
|
@ -712,7 +647,7 @@ add_emu(buff)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buff3) {
|
if (buff3) {
|
||||||
if (strcmp(buff3, "lowdelay") == 0)
|
if (strcmp(buff3, "lowdelay") == 0)
|
||||||
tos = IPTOS_LOWDELAY;
|
tos = IPTOS_LOWDELAY;
|
||||||
|
@ -723,7 +658,7 @@ add_emu(buff)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(buff1, "ftp") == 0)
|
if (strcmp(buff1, "ftp") == 0)
|
||||||
emu = EMU_FTP;
|
emu = EMU_FTP;
|
||||||
else if (strcmp(buff1, "irc") == 0)
|
else if (strcmp(buff1, "irc") == 0)
|
||||||
|
@ -734,7 +669,7 @@ add_emu(buff)
|
||||||
lprint("Error: Unknown service\r\n");
|
lprint("Error: Unknown service\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First, check that it isn't already emulated */
|
/* First, check that it isn't already emulated */
|
||||||
for (emup = tcpemu; emup; emup = emup->next) {
|
for (emup = tcpemu; emup; emup = emup->next) {
|
||||||
if (emup->lport == lport && emup->fport == fport) {
|
if (emup->lport == lport && emup->fport == fport) {
|
||||||
|
@ -742,7 +677,7 @@ add_emu(buff)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* link it */
|
/* link it */
|
||||||
emup = (struct emu_t *)malloc(sizeof (struct emu_t));
|
emup = (struct emu_t *)malloc(sizeof (struct emu_t));
|
||||||
emup->lport = (u_int16_t)lport;
|
emup->lport = (u_int16_t)lport;
|
||||||
|
@ -751,7 +686,7 @@ add_emu(buff)
|
||||||
emup->emu = emu;
|
emup->emu = emu;
|
||||||
emup->next = tcpemu;
|
emup->next = tcpemu;
|
||||||
tcpemu = emup;
|
tcpemu = emup;
|
||||||
|
|
||||||
/* And finally, mark all current sessions, if any, as being emulated */
|
/* And finally, mark all current sessions, if any, as being emulated */
|
||||||
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
|
for (so = tcb.so_next; so != &tcb; so = so->so_next) {
|
||||||
if ((lport && lport == ntohs(so->so_lport)) ||
|
if ((lport && lport == ntohs(so->so_lport)) ||
|
||||||
|
@ -762,10 +697,9 @@ add_emu(buff)
|
||||||
so->so_iptos = tos;
|
so->so_iptos = tos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
|
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BAD_SPRINTF
|
#ifdef BAD_SPRINTF
|
||||||
|
|
||||||
|
@ -776,51 +710,33 @@ add_emu(buff)
|
||||||
* Some BSD-derived systems have a sprintf which returns char *
|
* Some BSD-derived systems have a sprintf which returns char *
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int vsprintf_len(char *string, const char *format, va_list args)
|
||||||
vsprintf_len(string, format, args)
|
|
||||||
char *string;
|
|
||||||
const char *format;
|
|
||||||
va_list args;
|
|
||||||
{
|
{
|
||||||
vsprintf(string, format, args);
|
vsprintf(string, format, args);
|
||||||
return strlen(string);
|
return strlen(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int sprintf_len(char *string, const char *format, ...)
|
||||||
#ifdef __STDC__
|
|
||||||
sprintf_len(char *string, const char *format, ...)
|
|
||||||
#else
|
|
||||||
sprintf_len(va_alist) va_dcl
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
#ifdef __STDC__
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
#else
|
|
||||||
char *string;
|
|
||||||
char *format;
|
|
||||||
va_start(args);
|
|
||||||
string = va_arg(args, char *);
|
|
||||||
format = va_arg(args, char *);
|
|
||||||
#endif
|
|
||||||
vsprintf(string, format, args);
|
vsprintf(string, format, args);
|
||||||
|
va_end(args);
|
||||||
return strlen(string);
|
return strlen(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void u_sleep(int usec)
|
||||||
u_sleep(usec)
|
|
||||||
int usec;
|
|
||||||
{
|
{
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
fd_set fdset;
|
fd_set fdset;
|
||||||
|
|
||||||
FD_ZERO(&fdset);
|
FD_ZERO(&fdset);
|
||||||
|
|
||||||
t.tv_sec = 0;
|
t.tv_sec = 0;
|
||||||
t.tv_usec = usec * 1000;
|
t.tv_usec = usec * 1000;
|
||||||
|
|
||||||
select(0, &fdset, &fdset, &fdset, &t);
|
select(0, &fdset, &fdset, &fdset, &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,34 +744,30 @@ u_sleep(usec)
|
||||||
* Set fd blocking and non-blocking
|
* Set fd blocking and non-blocking
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void fd_nonblock(int fd)
|
||||||
fd_nonblock(fd)
|
|
||||||
int fd;
|
|
||||||
{
|
{
|
||||||
#ifdef FIONBIO
|
#if defined USE_FIONBIO && defined FIONBIO
|
||||||
int opt = 1;
|
ioctlsockopt_t opt = 1;
|
||||||
|
|
||||||
ioctlsocket(fd, FIONBIO, &opt);
|
ioctlsocket(fd, FIONBIO, &opt);
|
||||||
#else
|
#else
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
opt = fcntl(fd, F_GETFL, 0);
|
opt = fcntl(fd, F_GETFL, 0);
|
||||||
opt |= O_NONBLOCK;
|
opt |= O_NONBLOCK;
|
||||||
fcntl(fd, F_SETFL, opt);
|
fcntl(fd, F_SETFL, opt);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void fd_block(int fd)
|
||||||
fd_block(fd)
|
|
||||||
int fd;
|
|
||||||
{
|
{
|
||||||
#ifdef FIONBIO
|
#if defined USE_FIONBIO && defined FIONBIO
|
||||||
int opt = 0;
|
ioctlsockopt_t opt = 0;
|
||||||
|
|
||||||
ioctlsocket(fd, FIONBIO, &opt);
|
ioctlsocket(fd, FIONBIO, &opt);
|
||||||
#else
|
#else
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
opt = fcntl(fd, F_GETFL, 0);
|
opt = fcntl(fd, F_GETFL, 0);
|
||||||
opt &= ~O_NONBLOCK;
|
opt &= ~O_NONBLOCK;
|
||||||
fcntl(fd, F_SETFL, opt);
|
fcntl(fd, F_SETFL, opt);
|
||||||
|
@ -867,22 +779,17 @@ fd_block(fd)
|
||||||
/*
|
/*
|
||||||
* invoke RSH
|
* invoke RSH
|
||||||
*/
|
*/
|
||||||
int
|
int rsh_exec(struct socket *so, struct socket *ns,
|
||||||
rsh_exec(so,ns, user, host, args)
|
char *user, char *host, char *args)
|
||||||
struct socket *so;
|
|
||||||
struct socket *ns;
|
|
||||||
char *user;
|
|
||||||
char *host;
|
|
||||||
char *args;
|
|
||||||
{
|
{
|
||||||
int fd[2];
|
int fd[2];
|
||||||
int fd0[2];
|
int fd0[2];
|
||||||
int s;
|
int s;
|
||||||
char buff[256];
|
char buff[256];
|
||||||
|
|
||||||
DEBUG_CALL("rsh_exec");
|
DEBUG_CALL("rsh_exec");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
|
|
||||||
if (pipe(fd)<0) {
|
if (pipe(fd)<0) {
|
||||||
lprint("Error: pipe failed: %s\n", strerror(errno));
|
lprint("Error: pipe failed: %s\n", strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -903,7 +810,7 @@ rsh_exec(so,ns, user, host, args)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch(fork()) {
|
switch(fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
lprint("Error: fork failed: %s\n", strerror(errno));
|
lprint("Error: fork failed: %s\n", strerror(errno));
|
||||||
|
@ -912,11 +819,11 @@ rsh_exec(so,ns, user, host, args)
|
||||||
close(fd0[0]);
|
close(fd0[0]);
|
||||||
close(fd0[1]);
|
close(fd0[1]);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
close(fd[0]);
|
close(fd[0]);
|
||||||
close(fd0[0]);
|
close(fd0[0]);
|
||||||
|
|
||||||
/* Set the DISPLAY */
|
/* Set the DISPLAY */
|
||||||
if (x_port >= 0) {
|
if (x_port >= 0) {
|
||||||
#ifdef HAVE_SETENV
|
#ifdef HAVE_SETENV
|
||||||
|
@ -927,29 +834,29 @@ rsh_exec(so,ns, user, host, args)
|
||||||
putenv(buff);
|
putenv(buff);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
dup2(fd0[1], 0);
|
dup2(fd0[1], 0);
|
||||||
dup2(fd0[1], 1);
|
dup2(fd0[1], 1);
|
||||||
dup2(fd[1], 2);
|
dup2(fd[1], 2);
|
||||||
for (s = 3; s <= 255; s++)
|
for (s = 3; s <= 255; s++)
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
execlp("rsh","rsh","-l", user, host, args, NULL);
|
execlp("rsh","rsh","-l", user, host, args, NULL);
|
||||||
|
|
||||||
/* Ooops, failed, let's tell the user why */
|
/* Ooops, failed, let's tell the user why */
|
||||||
|
|
||||||
sprintf(buff, "Error: execlp of %s failed: %s\n",
|
sprintf(buff, "Error: execlp of %s failed: %s\n",
|
||||||
"rsh", strerror(errno));
|
"rsh", strerror(errno));
|
||||||
write(2, buff, strlen(buff)+1);
|
write(2, buff, strlen(buff)+1);
|
||||||
close(0); close(1); close(2); /* XXX */
|
close(0); close(1); close(2); /* XXX */
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
close(fd[1]);
|
close(fd[1]);
|
||||||
close(fd0[1]);
|
close(fd0[1]);
|
||||||
ns->s=fd[0];
|
ns->s=fd[0];
|
||||||
so->s=fd0[0];
|
so->s=fd0[0];
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -12,22 +12,22 @@ struct ex_list {
|
||||||
int ex_pty; /* Do we want a pty? */
|
int ex_pty; /* Do we want a pty? */
|
||||||
int ex_addr; /* The last byte of the address */
|
int ex_addr; /* The last byte of the address */
|
||||||
int ex_fport; /* Port to telnet to */
|
int ex_fport; /* Port to telnet to */
|
||||||
const char *ex_exec; /* Command line of what to exec */
|
char *ex_exec; /* Command line of what to exec */
|
||||||
struct ex_list *ex_next;
|
struct ex_list *ex_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct ex_list *exec_list;
|
extern struct ex_list *exec_list;
|
||||||
extern u_int curtime, time_fasttimo, last_slowtimo;
|
extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait;
|
||||||
|
|
||||||
extern int (*lprint_print) _P((void *, const char *, va_list));
|
extern int (*lprint_print)(void *, const char *, va_list);
|
||||||
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
|
extern char *lprint_ptr, *lprint_ptr2, **lprint_arg;
|
||||||
extern struct sbuf *lprint_sb;
|
extern struct sbuf *lprint_sb;
|
||||||
|
|
||||||
#ifndef HAVE_STRDUP
|
#ifndef HAVE_STRDUP
|
||||||
char *strdup _P((const char *));
|
char *strdup(const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void do_wait _P((int));
|
void do_wait(int);
|
||||||
|
|
||||||
#define EMU_NONE 0x0
|
#define EMU_NONE 0x0
|
||||||
|
|
||||||
|
@ -63,27 +63,25 @@ struct emu_t {
|
||||||
struct emu_t *next;
|
struct emu_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef CONFIG_QEMU
|
|
||||||
extern struct emu_t *tcpemu;
|
extern struct emu_t *tcpemu;
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int x_port, x_server, x_display;
|
extern int x_port, x_server, x_display;
|
||||||
|
|
||||||
int show_x _P((char *, struct socket *));
|
int show_x(char *, struct socket *);
|
||||||
void redir_x _P((u_int32_t, int, int, int));
|
void redir_x(u_int32_t, int, int, int);
|
||||||
void getouraddr _P((void));
|
void getouraddr(void);
|
||||||
inline void slirp_insque _P((void *, void *));
|
void slirp_insque(void *, void *);
|
||||||
inline void slirp_remque _P((void *));
|
void slirp_remque(void *);
|
||||||
int add_exec _P((struct ex_list **, int, char *, int, int));
|
int add_exec(struct ex_list **, int, char *, int, int);
|
||||||
int slirp_openpty _P((int *, int *));
|
int slirp_openpty(int *, int *);
|
||||||
int fork_exec(struct socket *so, const char *ex, int do_pty);
|
int fork_exec(struct socket *, char *, int);
|
||||||
void snooze_hup _P((int));
|
void snooze_hup(int);
|
||||||
void snooze _P((void));
|
void snooze(void);
|
||||||
void relay _P((int));
|
void relay(int);
|
||||||
void add_emu _P((char *));
|
void add_emu(char *);
|
||||||
void u_sleep _P((int));
|
void u_sleep(int);
|
||||||
void fd_nonblock _P((int));
|
void fd_nonblock(int);
|
||||||
void fd_block _P((int));
|
void fd_block(int);
|
||||||
int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));
|
int rsh_exec(struct socket *, struct socket *, char *, char *, char *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,37 +1,31 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
|
|
||||||
|
|
||||||
/* Done as a macro in socket.h */
|
/* Done as a macro in socket.h */
|
||||||
/* int
|
/* int
|
||||||
* sbspace(struct sockbuff *sb)
|
* sbspace(struct sockbuff *sb)
|
||||||
* {
|
* {
|
||||||
* return SB_DATALEN - sb->sb_cc;
|
* return SB_DATALEN - sb->sb_cc;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void sbfree(struct sbuf *sb)
|
||||||
sbfree(sb)
|
|
||||||
struct sbuf *sb;
|
|
||||||
{
|
{
|
||||||
free(sb->sb_data);
|
free(sb->sb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void sbdrop(struct sbuf *sb, u_int num)
|
||||||
sbdrop(sb, num)
|
|
||||||
struct sbuf *sb;
|
|
||||||
int num;
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We can only drop how much we have
|
* We can only drop how much we have
|
||||||
* This should never succeed
|
* This should never succeed
|
||||||
*/
|
*/
|
||||||
if(num > sb->sb_cc)
|
if(num > sb->sb_cc)
|
||||||
num = sb->sb_cc;
|
num = sb->sb_cc;
|
||||||
|
@ -39,13 +33,10 @@ sbdrop(sb, num)
|
||||||
sb->sb_rptr += num;
|
sb->sb_rptr += num;
|
||||||
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
|
if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
|
||||||
sb->sb_rptr -= sb->sb_datalen;
|
sb->sb_rptr -= sb->sb_datalen;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void sbreserve(struct sbuf *sb, size_t size)
|
||||||
sbreserve(sb, size)
|
|
||||||
struct sbuf *sb;
|
|
||||||
int size;
|
|
||||||
{
|
{
|
||||||
if (sb->sb_data) {
|
if (sb->sb_data) {
|
||||||
/* Already alloced, realloc if necessary */
|
/* Already alloced, realloc if necessary */
|
||||||
|
@ -73,24 +64,21 @@ sbreserve(sb, size)
|
||||||
* this prevents an unnecessary copy of the data
|
* this prevents an unnecessary copy of the data
|
||||||
* (the socket is non-blocking, so we won't hang)
|
* (the socket is non-blocking, so we won't hang)
|
||||||
*/
|
*/
|
||||||
void
|
void sbappend(struct socket *so, struct mbuf *m)
|
||||||
sbappend(so, m)
|
|
||||||
struct socket *so;
|
|
||||||
struct mbuf *m;
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
DEBUG_CALL("sbappend");
|
DEBUG_CALL("sbappend");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("m->m_len = %d", m->m_len);
|
DEBUG_ARG("m->m_len = %zu", m->m_len);
|
||||||
|
|
||||||
/* Shouldn't happen, but... e.g. foreign host closes connection */
|
/* Shouldn't happen, but... e.g. foreign host closes connection */
|
||||||
if (m->m_len <= 0) {
|
if (m->m_len <= 0) {
|
||||||
m_free(m);
|
m_free(m);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is urgent data, call sosendoob
|
* If there is urgent data, call sosendoob
|
||||||
* if not all was sent, sowrite will take care of the rest
|
* if not all was sent, sowrite will take care of the rest
|
||||||
|
@ -102,16 +90,16 @@ sbappend(so, m)
|
||||||
sosendoob(so);
|
sosendoob(so);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We only write if there's nothing in the buffer,
|
* We only write if there's nothing in the buffer,
|
||||||
* ottherwise it'll arrive out of order, and hence corrupt
|
* ottherwise it'll arrive out of order, and hence corrupt
|
||||||
*/
|
*/
|
||||||
if (!so->so_rcv.sb_cc)
|
if (!so->so_rcv.sb_cc)
|
||||||
ret = send(so->s, m->m_data, m->m_len, 0);
|
ret = send(so->s, m->m_data, m->m_len, 0);
|
||||||
|
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
/*
|
/*
|
||||||
* Nothing was written
|
* Nothing was written
|
||||||
* It's possible that the socket has closed, but
|
* It's possible that the socket has closed, but
|
||||||
* we don't need to check because if it has closed,
|
* we don't need to check because if it has closed,
|
||||||
|
@ -135,11 +123,10 @@ sbappend(so, m)
|
||||||
* Copy the data from m into sb
|
* Copy the data from m into sb
|
||||||
* The caller is responsible to make sure there's enough room
|
* The caller is responsible to make sure there's enough room
|
||||||
*/
|
*/
|
||||||
static void
|
void sbappendsb(struct sbuf *sb, struct mbuf *m)
|
||||||
sbappendsb(struct sbuf *sb, struct mbuf *m)
|
|
||||||
{
|
{
|
||||||
int len, n, nn;
|
int len, n, nn;
|
||||||
|
|
||||||
len = m->m_len;
|
len = m->m_len;
|
||||||
|
|
||||||
if (sb->sb_wptr < sb->sb_rptr) {
|
if (sb->sb_wptr < sb->sb_rptr) {
|
||||||
|
@ -172,15 +159,10 @@ sbappendsb(struct sbuf *sb, struct mbuf *m)
|
||||||
* Don't update the sbuf rptr, this will be
|
* Don't update the sbuf rptr, this will be
|
||||||
* done in sbdrop when the data is acked
|
* done in sbdrop when the data is acked
|
||||||
*/
|
*/
|
||||||
void
|
void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to)
|
||||||
sbcopy(sb, off, len, to)
|
|
||||||
struct sbuf *sb;
|
|
||||||
int off;
|
|
||||||
int len;
|
|
||||||
char *to;
|
|
||||||
{
|
{
|
||||||
char *from;
|
char *from;
|
||||||
|
|
||||||
from = sb->sb_rptr + off;
|
from = sb->sb_rptr + off;
|
||||||
if (from >= sb->sb_data + sb->sb_datalen)
|
if (from >= sb->sb_data + sb->sb_datalen)
|
||||||
from -= sb->sb_datalen;
|
from -= sb->sb_datalen;
|
||||||
|
@ -198,4 +180,4 @@ sbcopy(sb, off, len, to)
|
||||||
memcpy(to+off,sb->sb_data,len);
|
memcpy(to+off,sb->sb_data,len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SBUF_H_
|
#ifndef _SBUF_H_
|
||||||
#define _SBUF_H_
|
#define _SBUF_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
|
#define sbflush(sb) sbdrop((sb),(sb)->sb_cc)
|
||||||
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
#define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc)
|
||||||
|
|
||||||
|
@ -21,10 +23,11 @@ struct sbuf {
|
||||||
char *sb_data; /* Actual data */
|
char *sb_data; /* Actual data */
|
||||||
};
|
};
|
||||||
|
|
||||||
void sbfree _P((struct sbuf *));
|
void sbfree(struct sbuf *);
|
||||||
void sbdrop _P((struct sbuf *, int));
|
void sbdrop(struct sbuf *, u_int);
|
||||||
void sbreserve _P((struct sbuf *, int));
|
void sbreserve(struct sbuf *, size_t);
|
||||||
void sbappend _P((struct socket *, struct mbuf *));
|
void sbappend(struct socket *, struct mbuf *);
|
||||||
void sbcopy _P((struct sbuf *, int, int, char *));
|
void sbappendsb(struct sbuf *, struct mbuf *);
|
||||||
|
void sbcopy(struct sbuf *, u_int, u_int, char *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@ struct in_addr special_addr;
|
||||||
/* virtual address alias for host */
|
/* virtual address alias for host */
|
||||||
struct in_addr alias_addr;
|
struct in_addr alias_addr;
|
||||||
|
|
||||||
static const uint8_t special_ethaddr[6] = {
|
const uint8_t special_ethaddr[6] = {
|
||||||
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
|
0x52, 0x54, 0x00, 0x12, 0x35, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,10 +38,10 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
IP_ADDR_STRING *pIPAddr;
|
IP_ADDR_STRING *pIPAddr;
|
||||||
struct in_addr tmp_addr;
|
struct in_addr tmp_addr;
|
||||||
|
|
||||||
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
|
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
|
||||||
BufLen = sizeof(FIXED_INFO);
|
BufLen = sizeof(FIXED_INFO);
|
||||||
|
|
||||||
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
|
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
|
||||||
if (FixedInfo) {
|
if (FixedInfo) {
|
||||||
GlobalFree(FixedInfo);
|
GlobalFree(FixedInfo);
|
||||||
|
@ -49,7 +49,7 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
}
|
}
|
||||||
FixedInfo = GlobalAlloc(GPTR, BufLen);
|
FixedInfo = GlobalAlloc(GPTR, BufLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
|
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
|
||||||
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
|
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
|
||||||
if (FixedInfo) {
|
if (FixedInfo) {
|
||||||
|
@ -58,14 +58,14 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pIPAddr = &(FixedInfo->DnsServerList);
|
pIPAddr = &(FixedInfo->DnsServerList);
|
||||||
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
|
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
|
||||||
*pdns_addr = tmp_addr;
|
*pdns_addr = tmp_addr;
|
||||||
#if 0
|
#if 0
|
||||||
printf( "DNS Servers:\n" );
|
printf( "DNS Servers:\n" );
|
||||||
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
|
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
|
||||||
|
|
||||||
pIPAddr = FixedInfo -> DnsServerList.Next;
|
pIPAddr = FixedInfo -> DnsServerList.Next;
|
||||||
while ( pIPAddr ) {
|
while ( pIPAddr ) {
|
||||||
printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
|
printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
|
||||||
|
@ -84,18 +84,16 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
static int get_dns_addr(struct in_addr *pdns_addr)
|
static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
{
|
{
|
||||||
char buff[512];
|
char buff[512];
|
||||||
char buff2[256];
|
char buff2[256+1];
|
||||||
FILE *f;
|
FILE *f;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
struct in_addr tmp_addr;
|
struct in_addr tmp_addr;
|
||||||
|
|
||||||
f = fopen("/etc/resolv.conf", "r");
|
f = fopen("/etc/resolv.conf", "r");
|
||||||
if (!f)
|
if (!f)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
lprint("IP address of your DNS(s): ");
|
lprint("IP address of your DNS(s): ");
|
||||||
#endif
|
|
||||||
while (fgets(buff, 512, f) != NULL) {
|
while (fgets(buff, 512, f) != NULL) {
|
||||||
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
|
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
|
||||||
if (!inet_aton(buff2, &tmp_addr))
|
if (!inet_aton(buff2, &tmp_addr))
|
||||||
|
@ -105,20 +103,13 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
/* If it's the first one, set it to dns_addr */
|
/* If it's the first one, set it to dns_addr */
|
||||||
if (!found)
|
if (!found)
|
||||||
*pdns_addr = tmp_addr;
|
*pdns_addr = tmp_addr;
|
||||||
#ifdef DEBUG
|
|
||||||
else
|
else
|
||||||
lprint(", ");
|
lprint(", ");
|
||||||
#endif
|
|
||||||
if (++found > 3) {
|
if (++found > 3) {
|
||||||
#ifdef DEBUG
|
|
||||||
lprint("(more)");
|
lprint("(more)");
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
} else
|
||||||
#ifdef DEBUG
|
|
||||||
else
|
|
||||||
lprint("%s", inet_ntoa(tmp_addr));
|
lprint("%s", inet_ntoa(tmp_addr));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
@ -130,16 +121,16 @@ static int get_dns_addr(struct in_addr *pdns_addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static void slirp_cleanup(void)
|
void slirp_cleanup(void)
|
||||||
{
|
{
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void slirp_init(void)
|
int slirp_init(void)
|
||||||
{
|
{
|
||||||
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
|
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
WSADATA Data;
|
WSADATA Data;
|
||||||
|
@ -159,14 +150,13 @@ void slirp_init(void)
|
||||||
/* set default addresses */
|
/* set default addresses */
|
||||||
inet_aton("127.0.0.1", &loopback_addr);
|
inet_aton("127.0.0.1", &loopback_addr);
|
||||||
|
|
||||||
if (get_dns_addr(&dns_addr) < 0) {
|
if (get_dns_addr(&dns_addr) < 0)
|
||||||
dns_addr = loopback_addr;
|
return -1;
|
||||||
fprintf (stderr, "Warning: No DNS servers found\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
inet_aton(CTL_SPECIAL, &special_addr);
|
inet_aton(CTL_SPECIAL, &special_addr);
|
||||||
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
|
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
|
||||||
getouraddr();
|
getouraddr();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
|
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
|
||||||
|
@ -189,57 +179,56 @@ static void updtime(void)
|
||||||
static void updtime(void)
|
static void updtime(void)
|
||||||
{
|
{
|
||||||
gettimeofday(&tt, 0);
|
gettimeofday(&tt, 0);
|
||||||
|
|
||||||
curtime = (u_int)tt.tv_sec * (u_int)1000;
|
curtime = (u_int)tt.tv_sec * (u_int)1000;
|
||||||
curtime += (u_int)tt.tv_usec / (u_int)1000;
|
curtime += (u_int)tt.tv_usec / (u_int)1000;
|
||||||
|
|
||||||
if ((tt.tv_usec % 1000) >= 500)
|
if ((tt.tv_usec % 1000) >= 500)
|
||||||
curtime++;
|
curtime++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void slirp_select_fill(int *pnfds,
|
int slirp_select_fill(int *pnfds,
|
||||||
fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
{
|
{
|
||||||
struct socket *so, *so_next;
|
struct socket *so, *so_next;
|
||||||
struct timeval timeout;
|
|
||||||
int nfds;
|
int nfds;
|
||||||
int tmp_time;
|
int timeout, tmp_time;
|
||||||
|
|
||||||
/* fail safe */
|
/* fail safe */
|
||||||
global_readfds = NULL;
|
global_readfds = NULL;
|
||||||
global_writefds = NULL;
|
global_writefds = NULL;
|
||||||
global_xfds = NULL;
|
global_xfds = NULL;
|
||||||
|
|
||||||
nfds = *pnfds;
|
nfds = *pnfds;
|
||||||
/*
|
/*
|
||||||
* First, TCP sockets
|
* First, TCP sockets
|
||||||
*/
|
*/
|
||||||
do_slowtimo = 0;
|
do_slowtimo = 0;
|
||||||
if (link_up) {
|
if (link_up) {
|
||||||
/*
|
/*
|
||||||
* *_slowtimo needs calling if there are IP fragments
|
* *_slowtimo needs calling if there are IP fragments
|
||||||
* in the fragment queue, or there are TCP connections active
|
* in the fragment queue, or there are TCP connections active
|
||||||
*/
|
*/
|
||||||
do_slowtimo = ((tcb.so_next != &tcb) ||
|
do_slowtimo = ((tcb.so_next != &tcb) ||
|
||||||
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
|
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
|
||||||
|
|
||||||
for (so = tcb.so_next; so != &tcb; so = so_next) {
|
for (so = tcb.so_next; so != &tcb; so = so_next) {
|
||||||
so_next = so->so_next;
|
so_next = so->so_next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we need a tcp_fasttimo
|
* See if we need a tcp_fasttimo
|
||||||
*/
|
*/
|
||||||
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
|
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
|
||||||
time_fasttimo = curtime; /* Flag when we want a fasttimo */
|
time_fasttimo = curtime; /* Flag when we want a fasttimo */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOFDREF can include still connecting to local-host,
|
* NOFDREF can include still connecting to local-host,
|
||||||
* newly socreated() sockets etc. Don't want to select these.
|
* newly socreated() sockets etc. Don't want to select these.
|
||||||
*/
|
*/
|
||||||
if (so->so_state & SS_NOFDREF || so->s == -1)
|
if (so->so_state & SS_NOFDREF || so->s == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set for reading sockets which are accepting
|
* Set for reading sockets which are accepting
|
||||||
*/
|
*/
|
||||||
|
@ -248,7 +237,7 @@ void slirp_select_fill(int *pnfds,
|
||||||
UPD_NFDS(so->s);
|
UPD_NFDS(so->s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set for writing sockets which are connecting
|
* Set for writing sockets which are connecting
|
||||||
*/
|
*/
|
||||||
|
@ -257,7 +246,7 @@ void slirp_select_fill(int *pnfds,
|
||||||
UPD_NFDS(so->s);
|
UPD_NFDS(so->s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set for writing if we are connected, can send more, and
|
* Set for writing if we are connected, can send more, and
|
||||||
* we have something to send
|
* we have something to send
|
||||||
|
@ -266,7 +255,7 @@ void slirp_select_fill(int *pnfds,
|
||||||
FD_SET(so->s, writefds);
|
FD_SET(so->s, writefds);
|
||||||
UPD_NFDS(so->s);
|
UPD_NFDS(so->s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set for reading (and urgent data) if we are connected, can
|
* Set for reading (and urgent data) if we are connected, can
|
||||||
* receive more, and we have room for it XXX /2 ?
|
* receive more, and we have room for it XXX /2 ?
|
||||||
|
@ -277,13 +266,13 @@ void slirp_select_fill(int *pnfds,
|
||||||
UPD_NFDS(so->s);
|
UPD_NFDS(so->s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UDP sockets
|
* UDP sockets
|
||||||
*/
|
*/
|
||||||
for (so = udb.so_next; so != &udb; so = so_next) {
|
for (so = udb.so_next; so != &udb; so = so_next) {
|
||||||
so_next = so->so_next;
|
so_next = so->so_next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if it's timed out
|
* See if it's timed out
|
||||||
*/
|
*/
|
||||||
|
@ -294,7 +283,7 @@ void slirp_select_fill(int *pnfds,
|
||||||
} else
|
} else
|
||||||
do_slowtimo = 1; /* Let socket expire */
|
do_slowtimo = 1; /* Let socket expire */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When UDP packets are received from over the
|
* When UDP packets are received from over the
|
||||||
* link, they're sendto()'d straight away, so
|
* link, they're sendto()'d straight away, so
|
||||||
|
@ -311,51 +300,58 @@ void slirp_select_fill(int *pnfds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup timeout to use minimum CPU usage, especially when idle
|
* Setup timeout to use minimum CPU usage, especially when idle
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
timeout = -1;
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
if (do_slowtimo) {
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
# 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;
|
||||||
|
|
||||||
/* Can only fasttimo if we also slowtimo */
|
/* Can only fasttimo if we also slowtimo */
|
||||||
if (time_fasttimo) {
|
if (time_fasttimo) {
|
||||||
tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
|
tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000;
|
||||||
if (tmp_time < 0)
|
if (tmp_time < 0)
|
||||||
tmp_time = 0;
|
tmp_time = 0;
|
||||||
|
|
||||||
/* Choose the smallest of the 2 */
|
/* Choose the smallest of the 2 */
|
||||||
if (tmp_time < timeout.tv_usec)
|
if (tmp_time < timeout)
|
||||||
timeout.tv_usec = (u_int)tmp_time;
|
timeout = tmp_time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*pnfds = nfds;
|
*pnfds = nfds;
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
* Adjust the timeout to make the minimum timeout
|
||||||
|
* 2ms (XXX?) to lessen the CPU load
|
||||||
|
*/
|
||||||
|
if (timeout < (FAST_TIMO * 1000))
|
||||||
|
timeout = FAST_TIMO * 1000;
|
||||||
|
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
{
|
{
|
||||||
struct socket *so, *so_next;
|
struct socket *so, *so_next;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
global_readfds = readfds;
|
global_readfds = readfds;
|
||||||
global_writefds = writefds;
|
global_writefds = writefds;
|
||||||
global_xfds = xfds;
|
global_xfds = xfds;
|
||||||
|
|
||||||
/* Update time */
|
/* Update time */
|
||||||
updtime();
|
updtime();
|
||||||
|
@ -364,11 +360,11 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
* See if anything has timed out
|
* See if anything has timed out
|
||||||
*/
|
*/
|
||||||
if (link_up) {
|
if (link_up) {
|
||||||
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
|
if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
|
||||||
tcp_fasttimo();
|
tcp_fasttimo();
|
||||||
time_fasttimo = 0;
|
time_fasttimo = 0;
|
||||||
}
|
}
|
||||||
if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
|
if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
|
||||||
ip_slowtimo();
|
ip_slowtimo();
|
||||||
tcp_slowtimo();
|
tcp_slowtimo();
|
||||||
last_slowtimo = curtime;
|
last_slowtimo = curtime;
|
||||||
|
@ -390,7 +386,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
* (and they can crash the program)
|
* (and they can crash the program)
|
||||||
*/
|
*/
|
||||||
if (so->so_state & SS_NOFDREF || so->s == -1)
|
if (so->so_state & SS_NOFDREF || so->s == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for URG data
|
* Check for URG data
|
||||||
|
@ -398,7 +394,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
* test for readfds below if this succeeds
|
* test for readfds below if this succeeds
|
||||||
*/
|
*/
|
||||||
if (FD_ISSET(so->s, xfds))
|
if (FD_ISSET(so->s, xfds))
|
||||||
sorecvoob(so);
|
sorecvoob(so);
|
||||||
/*
|
/*
|
||||||
* Check sockets for reading
|
* Check sockets for reading
|
||||||
*/
|
*/
|
||||||
|
@ -414,82 +410,88 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
|
|
||||||
/* Output it if we read something */
|
/* Output it if we read something */
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
tcp_output(sototcpcb(so));
|
tcp_output(sototcpcb(so));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check sockets for writing
|
* Check sockets for writing
|
||||||
*/
|
*/
|
||||||
if (FD_ISSET(so->s, writefds)) {
|
if (FD_ISSET(so->s, writefds)) {
|
||||||
/*
|
/*
|
||||||
* Check for non-blocking, still-connecting sockets
|
* Check for non-blocking, still-connecting sockets
|
||||||
*/
|
*/
|
||||||
if (so->so_state & SS_ISFCONNECTING) {
|
if (so->so_state & SS_ISFCONNECTING) {
|
||||||
/* Connected */
|
/* Connected */
|
||||||
so->so_state &= ~SS_ISFCONNECTING;
|
so->so_state &= ~SS_ISFCONNECTING;
|
||||||
|
|
||||||
ret = send(so->s, &ret, 0, 0);
|
ret = send(so->s, (char*)&ret, 0, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* XXXXX Must fix, zero bytes is a NOP */
|
/* XXXXX Must fix, zero bytes is a NOP */
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
int error = WSAGetLastError();
|
||||||
errno == EINPROGRESS || errno == ENOTCONN)
|
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||||
continue;
|
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* else failed */
|
/* else failed */
|
||||||
so->so_state = SS_NOFDREF;
|
so->so_state = SS_NOFDREF;
|
||||||
}
|
}
|
||||||
/* else so->so_state &= ~SS_ISFCONNECTING; */
|
/* else so->so_state &= ~SS_ISFCONNECTING; */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Continue tcp_input
|
* Continue tcp_input
|
||||||
*/
|
*/
|
||||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
||||||
/* continue; */
|
/* continue; */
|
||||||
} else
|
}
|
||||||
ret = sowrite(so);
|
else
|
||||||
/*
|
ret = sowrite(so);
|
||||||
* XXXXX If we wrote something (a lot), there
|
/*
|
||||||
* could be a need for a window update.
|
* XXXXX If we wrote something (a lot), there
|
||||||
* In the worst case, the remote will send
|
* could be a need for a window update.
|
||||||
* a window probe to get things going again
|
* In the worst case, the remote will send
|
||||||
*/
|
* a window probe to get things going again
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe a still-connecting, non-blocking socket
|
* Probe a still-connecting, non-blocking socket
|
||||||
* to check if it's still alive
|
* to check if it's still alive
|
||||||
*/
|
*/
|
||||||
#ifdef PROBE_CONN
|
#ifdef PROBE_CONN
|
||||||
if (so->so_state & SS_ISFCONNECTING) {
|
if (so->so_state & SS_ISFCONNECTING) {
|
||||||
ret = recv(so->s, (char *)&ret, 0,0);
|
ret = recv(so->s, (char *)&ret, 0, 0);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* XXX */
|
/* XXX */
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
int error = WSAGetLastError();
|
||||||
errno == EINPROGRESS || errno == ENOTCONN)
|
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||||
continue; /* Still connecting, continue */
|
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||||
|
continue; /* Still connecting, continue */
|
||||||
|
|
||||||
/* else failed */
|
/* else failed */
|
||||||
so->so_state = SS_NOFDREF;
|
so->so_state = SS_NOFDREF;
|
||||||
|
|
||||||
/* tcp_input will take care of it */
|
/* tcp_input will take care of it */
|
||||||
} else {
|
}
|
||||||
ret = send(so->s, &ret, 0,0);
|
else {
|
||||||
if (ret < 0) {
|
ret = send(so->s, &ret, 0, 0);
|
||||||
/* XXX */
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK ||
|
/* XXX */
|
||||||
errno == EINPROGRESS || errno == ENOTCONN)
|
int error = WSAGetLastError();
|
||||||
continue;
|
if (error == EAGAIN || error == WSAEWOULDBLOCK ||
|
||||||
/* else failed */
|
error == WSAEINPROGRESS || error == WSAENOTCONN)
|
||||||
so->so_state = SS_NOFDREF;
|
continue;
|
||||||
} else
|
/* else failed */
|
||||||
so->so_state &= ~SS_ISFCONNECTING;
|
so->so_state = SS_NOFDREF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
so->so_state &= ~SS_ISFCONNECTING;
|
||||||
|
|
||||||
}
|
}
|
||||||
tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
|
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
|
||||||
} /* SS_ISFCONNECTING */
|
} /* SS_ISFCONNECTING */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now UDP sockets.
|
* Now UDP sockets.
|
||||||
|
@ -500,25 +502,25 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
so_next = so->so_next;
|
so_next = so->so_next;
|
||||||
|
|
||||||
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
|
if (so->s != -1 && FD_ISSET(so->s, readfds)) {
|
||||||
sorecvfrom(so);
|
sorecvfrom(so);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we can start outputting
|
* See if we can start outputting
|
||||||
*/
|
*/
|
||||||
if (if_queued && link_up)
|
if (if_queued && link_up)
|
||||||
if_start();
|
if_start();
|
||||||
|
|
||||||
/* clear global file descriptor sets.
|
/* clear global file descriptor sets.
|
||||||
* these reside on the stack in vl.c
|
* these reside on the stack in vl.c
|
||||||
* so they're unusable if we're not in
|
* so they're unusable if we're not in
|
||||||
* slirp_select_fill or slirp_select_poll.
|
* slirp_select_fill or slirp_select_poll.
|
||||||
*/
|
*/
|
||||||
global_readfds = NULL;
|
global_readfds = NULL;
|
||||||
global_writefds = NULL;
|
global_writefds = NULL;
|
||||||
global_xfds = NULL;
|
global_xfds = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ETH_ALEN 6
|
#define ETH_ALEN 6
|
||||||
|
@ -530,7 +532,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
|
||||||
#define ARPOP_REQUEST 1 /* ARP request */
|
#define ARPOP_REQUEST 1 /* ARP request */
|
||||||
#define ARPOP_REPLY 2 /* ARP reply */
|
#define ARPOP_REPLY 2 /* ARP reply */
|
||||||
|
|
||||||
struct ethhdr
|
struct ethhdr
|
||||||
{
|
{
|
||||||
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
|
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
|
||||||
unsigned char h_source[ETH_ALEN]; /* source ether addr */
|
unsigned char h_source[ETH_ALEN]; /* source ether addr */
|
||||||
|
@ -568,7 +570,7 @@ void arp_input(const uint8_t *pkt, int pkt_len)
|
||||||
switch(ar_op) {
|
switch(ar_op) {
|
||||||
case ARPOP_REQUEST:
|
case ARPOP_REQUEST:
|
||||||
if (!memcmp(ah->ar_tip, &special_addr, 3)) {
|
if (!memcmp(ah->ar_tip, &special_addr, 3)) {
|
||||||
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
|
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
|
||||||
goto arp_ok;
|
goto arp_ok;
|
||||||
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
|
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
|
||||||
if (ex_ptr->ex_addr == ah->ar_tip[3])
|
if (ex_ptr->ex_addr == ah->ar_tip[3])
|
||||||
|
@ -609,8 +611,8 @@ void slirp_input(const uint8_t *pkt, int pkt_len)
|
||||||
|
|
||||||
if (pkt_len < ETH_HLEN)
|
if (pkt_len < ETH_HLEN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
proto = ntohs(*(uint16_t *)(pkt + 12));
|
proto = (pkt[12] << 8) | pkt[13];
|
||||||
switch(proto) {
|
switch(proto) {
|
||||||
case ETH_P_ARP:
|
case ETH_P_ARP:
|
||||||
arp_input(pkt, pkt_len);
|
arp_input(pkt, pkt_len);
|
||||||
|
@ -651,24 +653,24 @@ void if_encap(const uint8_t *ip_data, int ip_data_len)
|
||||||
slirp_output(buf, ip_data_len + ETH_HLEN);
|
slirp_output(buf, ip_data_len + ETH_HLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
int slirp_redir(int is_udp, int host_port,
|
int slirp_redir(int is_udp, int host_port,
|
||||||
struct in_addr guest_addr, int guest_port)
|
struct in_addr guest_addr, int guest_port)
|
||||||
{
|
{
|
||||||
if (is_udp) {
|
if (is_udp) {
|
||||||
if (!udp_listen(htons(host_port), guest_addr.s_addr,
|
if (!udp_listen(htons(host_port), guest_addr.s_addr,
|
||||||
htons(guest_port), 0))
|
htons(guest_port), 0))
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
if (!solisten(htons(host_port), guest_addr.s_addr,
|
if (!solisten(htons(host_port), guest_addr.s_addr,
|
||||||
htons(guest_port), 0))
|
htons(guest_port), 0))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
|
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
|
||||||
int guest_port)
|
int guest_port)
|
||||||
{
|
{
|
||||||
return add_exec(&exec_list, do_pty, (char *)args,
|
return add_exec(&exec_list, do_pty, (char *)args,
|
||||||
addr_low_byte, htons(guest_port));
|
addr_low_byte, htons(guest_port));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,12 @@
|
||||||
|
|
||||||
#define CONFIG_QEMU
|
#define CONFIG_QEMU
|
||||||
|
|
||||||
//#define DEBUG 1
|
#define DEBUG 1
|
||||||
|
|
||||||
// Uncomment the following line to enable SLIRP statistics printing in Qemu
|
|
||||||
//#define LOG_ENABLED
|
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
#define STAT(expr) expr
|
|
||||||
#else
|
|
||||||
#define STAT(expr) do { } while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_QEMU
|
#ifndef CONFIG_QEMU
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#endif
|
#endif
|
||||||
#include "config-host.h"
|
#include "config.h"
|
||||||
#include "slirp_config.h"
|
#include "slirp_config.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -28,20 +19,31 @@ typedef uint16_t u_int16_t;
|
||||||
typedef uint32_t u_int32_t;
|
typedef uint32_t u_int32_t;
|
||||||
typedef uint64_t u_int64_t;
|
typedef uint64_t u_int64_t;
|
||||||
typedef char *caddr_t;
|
typedef char *caddr_t;
|
||||||
|
typedef int socklen_t;
|
||||||
|
typedef unsigned long ioctlsockopt_t;
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
# include <windows.h>
|
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
|
# include <WS2tcpip.h>
|
||||||
# include <sys/timeb.h>
|
# include <sys/timeb.h>
|
||||||
# include <iphlpapi.h>
|
# include <iphlpapi.h>
|
||||||
|
|
||||||
# define EWOULDBLOCK WSAEWOULDBLOCK
|
# define USE_FIONBIO 1
|
||||||
# define EINPROGRESS WSAEINPROGRESS
|
|
||||||
# define ENOTCONN WSAENOTCONN
|
/* Basilisk II Router defines those */
|
||||||
# define EHOSTUNREACH WSAEHOSTUNREACH
|
# define udp_read_completion slirp_udp_read_completion
|
||||||
# define ENETUNREACH WSAENETUNREACH
|
# define write_udp slirp_write_udp
|
||||||
# define ECONNREFUSED WSAECONNREFUSED
|
# define init_udp slirp_init_udp
|
||||||
|
# define final_udp slirp_final_udp
|
||||||
#else
|
#else
|
||||||
|
# define WSAGetLastError() (int)(errno)
|
||||||
|
# define WSASetLastError(e) (void)(errno = (e))
|
||||||
|
# define WSAEWOULDBLOCK EWOULDBLOCK
|
||||||
|
# define WSAEINPROGRESS EINPROGRESS
|
||||||
|
# define WSAENOTCONN ENOTCONN
|
||||||
|
# define WSAEHOSTUNREACH EHOSTUNREACH
|
||||||
|
# define WSAENETUNREACH ENETUNREACH
|
||||||
|
# define WSAECONNREFUSED ECONNREFUSED
|
||||||
|
typedef int ioctlsockopt_t;
|
||||||
# define ioctlsocket ioctl
|
# define ioctlsocket ioctl
|
||||||
# define closesocket(s) close(s)
|
# define closesocket(s) close(s)
|
||||||
# define O_BINARY 0
|
# define O_BINARY 0
|
||||||
|
@ -51,8 +53,13 @@ typedef char *caddr_t;
|
||||||
#ifdef HAVE_SYS_BITYPES_H
|
#ifdef HAVE_SYS_BITYPES_H
|
||||||
# include <sys/bitypes.h>
|
# include <sys/bitypes.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_STDINT_H
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NEED_TYPEDEFS
|
#ifdef NEED_TYPEDEFS
|
||||||
typedef char int8_t;
|
typedef char int8_t;
|
||||||
|
@ -83,6 +90,11 @@ typedef unsigned char u_int8_t;
|
||||||
# endif
|
# endif
|
||||||
#endif /* NEED_TYPEDEFS */
|
#endif /* NEED_TYPEDEFS */
|
||||||
|
|
||||||
|
/* Basilisk II types glue */
|
||||||
|
typedef u_int8_t uint8;
|
||||||
|
typedef u_int16_t uint16;
|
||||||
|
typedef u_int32_t uint32;
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -117,17 +129,6 @@ typedef unsigned char u_int8_t;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _P
|
|
||||||
#ifndef NO_PROTOTYPES
|
|
||||||
# define _P(x) x
|
|
||||||
#else
|
|
||||||
# define _P(x) ()
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -138,20 +139,23 @@ typedef unsigned char u_int8_t;
|
||||||
|
|
||||||
/* Systems lacking strdup() definition in <string.h>. */
|
/* Systems lacking strdup() definition in <string.h>. */
|
||||||
#if defined(ultrix)
|
#if defined(ultrix)
|
||||||
char *strdup _P((const char *));
|
char *strdup(const char *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Systems lacking malloc() definition in <stdlib.h>. */
|
/* Systems lacking malloc() definition in <stdlib.h>. */
|
||||||
#if defined(ultrix) || defined(hcx)
|
#if defined(ultrix) || defined(hcx)
|
||||||
void *malloc _P((size_t arg));
|
void *malloc(size_t arg);
|
||||||
void free _P((void *ptr));
|
void free(void *ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_INET_ATON
|
#ifndef HAVE_INET_ATON
|
||||||
int inet_aton _P((const char *cp, struct in_addr *ia));
|
int inet_aton(const char *cp, struct in_addr *ia);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#endif
|
||||||
#ifndef NO_UNIX_SOCKETS
|
#ifndef NO_UNIX_SOCKETS
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -183,11 +187,7 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
|
||||||
#include <ppp/slirppp.h>
|
#include <ppp/slirppp.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __STDC__
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#else
|
|
||||||
#include <varargs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -202,6 +202,20 @@ int inet_aton _P((const char *cp, struct in_addr *ia));
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#if defined __GNUC__
|
||||||
|
#define PACKED__ __attribute__ ((packed))
|
||||||
|
#elif defined _MSC_VER
|
||||||
|
#define PRAGMA_PACK_SUPPORTED 1
|
||||||
|
#define PACK_RESET
|
||||||
|
#define PACKED__
|
||||||
|
#elif defined __sgi
|
||||||
|
#define PRAGMA_PACK_SUPPORTED 1
|
||||||
|
#define PACK_RESET 0
|
||||||
|
#define PACKED__
|
||||||
|
#else
|
||||||
|
#error "Packed attribute or pragma shall be supported"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ip.h"
|
#include "ip.h"
|
||||||
#include "tcp.h"
|
#include "tcp.h"
|
||||||
#include "tcp_timer.h"
|
#include "tcp_timer.h"
|
||||||
|
@ -232,45 +246,47 @@ extern struct ttys *ttys_unit[MAX_INTERFACES];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FULL_BOLT
|
#ifndef FULL_BOLT
|
||||||
void if_start _P((void));
|
void if_start(void);
|
||||||
#else
|
#else
|
||||||
void if_start _P((struct ttys *));
|
void if_start(struct ttys *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BAD_SPRINTF
|
#ifdef BAD_SPRINTF
|
||||||
# define vsprintf vsprintf_len
|
# define vsprintf vsprintf_len
|
||||||
# define sprintf sprintf_len
|
# define sprintf sprintf_len
|
||||||
extern int vsprintf_len _P((char *, const char *, va_list));
|
extern int vsprintf_len(char *, const char *, va_list);
|
||||||
extern int sprintf_len _P((char *, const char *, ...));
|
extern int sprintf_len(char *, const char *, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DECLARE_SPRINTF
|
#ifdef DECLARE_SPRINTF
|
||||||
# ifndef BAD_SPRINTF
|
# ifndef BAD_SPRINTF
|
||||||
extern int vsprintf _P((char *, const char *, va_list));
|
extern int vsprintf(char *, const char *, va_list);
|
||||||
# endif
|
# endif
|
||||||
extern int vfprintf _P((FILE *, const char *, va_list));
|
extern int vfprintf(FILE *, const char *, va_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_STRERROR
|
#ifndef HAVE_STRERROR
|
||||||
extern char *strerror _P((int error));
|
extern char *strerror(int error);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_INDEX
|
#ifndef HAVE_INDEX
|
||||||
char *index _P((const char *, int));
|
char *index(const char *, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_GETHOSTID
|
#ifndef HAVE_GETHOSTID
|
||||||
long gethostid _P((void));
|
long gethostid(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lprint _P((const char *, ...));
|
void lprint(const char *, ...);
|
||||||
|
|
||||||
|
extern int do_echo;
|
||||||
|
|
||||||
#if SIZEOF_CHAR_P == 4
|
#if SIZEOF_CHAR_P == 4
|
||||||
# define insque_32 insque
|
# define insque_32 insque
|
||||||
# define remque_32 remque
|
# define remque_32 remque
|
||||||
#else
|
#else
|
||||||
inline void insque_32 _P((void *, void *));
|
extern inline void insque_32(void *, void *);
|
||||||
inline void remque_32 _P((void *));
|
extern inline void remque_32(void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -279,46 +295,51 @@ void lprint _P((const char *, ...));
|
||||||
|
|
||||||
#define DEFAULT_BAUD 115200
|
#define DEFAULT_BAUD 115200
|
||||||
|
|
||||||
#define SO_OPTIONS DO_KEEPALIVE
|
|
||||||
#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL)
|
|
||||||
|
|
||||||
/* cksum.c */
|
/* cksum.c */
|
||||||
int cksum(struct mbuf *m, int len);
|
int cksum(struct mbuf *m, int len);
|
||||||
|
|
||||||
/* if.c */
|
/* if.c */
|
||||||
void if_init _P((void));
|
void if_init(void);
|
||||||
void if_output _P((struct socket *, struct mbuf *));
|
void if_output(struct socket *, struct mbuf *);
|
||||||
|
|
||||||
/* ip_input.c */
|
/* ip_input.c */
|
||||||
void ip_init _P((void));
|
void ip_init(void);
|
||||||
void ip_input _P((struct mbuf *));
|
void ip_input(struct mbuf *);
|
||||||
void ip_slowtimo _P((void));
|
struct ip * ip_reass(register struct ipasfrag *, register struct ipq *);
|
||||||
void ip_stripoptions _P((register struct mbuf *, struct mbuf *));
|
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 *);
|
||||||
|
|
||||||
/* ip_output.c */
|
/* ip_output.c */
|
||||||
int ip_output _P((struct socket *, struct mbuf *));
|
int ip_output(struct socket *, struct mbuf *);
|
||||||
|
|
||||||
/* tcp_input.c */
|
/* tcp_input.c */
|
||||||
void tcp_input _P((register struct mbuf *, int, struct socket *));
|
int tcp_reass(register struct tcpcb *, register struct tcpiphdr *, struct mbuf *);
|
||||||
int tcp_mss _P((register struct tcpcb *, u_int));
|
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);
|
||||||
|
|
||||||
/* tcp_output.c */
|
/* tcp_output.c */
|
||||||
int tcp_output _P((register struct tcpcb *));
|
int tcp_output(register struct tcpcb *);
|
||||||
void tcp_setpersist _P((register struct tcpcb *));
|
void tcp_setpersist(register struct tcpcb *);
|
||||||
|
|
||||||
/* tcp_subr.c */
|
/* tcp_subr.c */
|
||||||
void tcp_init _P((void));
|
void tcp_init(void);
|
||||||
void tcp_template _P((struct tcpcb *));
|
void tcp_template(struct tcpcb *);
|
||||||
void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int));
|
void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int);
|
||||||
struct tcpcb * tcp_newtcpcb _P((struct socket *));
|
struct tcpcb * tcp_newtcpcb(struct socket *);
|
||||||
struct tcpcb * tcp_close _P((register struct tcpcb *));
|
struct tcpcb * tcp_close(register struct tcpcb *);
|
||||||
void tcp_sockclosed _P((struct tcpcb *));
|
void tcp_drain(void);
|
||||||
int tcp_fconnect _P((struct socket *));
|
void tcp_sockclosed(struct tcpcb *);
|
||||||
void tcp_connect _P((struct socket *));
|
int tcp_fconnect(struct socket *);
|
||||||
int tcp_attach _P((struct socket *));
|
void tcp_connect(struct socket *);
|
||||||
u_int8_t tcp_tos _P((struct socket *));
|
int tcp_attach(struct socket *);
|
||||||
int tcp_emu _P((struct socket *, struct mbuf *));
|
u_int8_t tcp_tos(struct socket *);
|
||||||
int tcp_ctl _P((struct socket *));
|
int tcp_emu(struct socket *, struct mbuf *);
|
||||||
|
int tcp_ctl(struct socket *);
|
||||||
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
||||||
|
|
||||||
#ifdef USE_PPP
|
#ifdef USE_PPP
|
||||||
|
@ -334,9 +355,4 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err);
|
||||||
#define max(x,y) ((x) > (y) ? (x) : (y))
|
#define max(x,y) ((x) > (y) ? (x) : (y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#undef errno
|
|
||||||
#define errno (WSAGetLastError())
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,11 +40,6 @@
|
||||||
*/
|
*/
|
||||||
#undef USE_LOWCPU
|
#undef USE_LOWCPU
|
||||||
|
|
||||||
/* Define this if your compiler doesn't like prototypes */
|
|
||||||
#ifndef __STDC__
|
|
||||||
#define NO_PROTOTYPES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/*
|
/*
|
||||||
* Autoconf defined configuration options
|
* Autoconf defined configuration options
|
||||||
|
@ -54,40 +49,11 @@
|
||||||
/* Ignore this */
|
/* Ignore this */
|
||||||
#undef DUMMY_PPP
|
#undef DUMMY_PPP
|
||||||
|
|
||||||
/* Define if you have unistd.h */
|
/* XXX: Define according to how time.h should be included */
|
||||||
#define HAVE_UNISTD_H
|
#undef TIME_WITH_SYS_TIME
|
||||||
|
|
||||||
/* Define if you have stdlib.h */
|
|
||||||
#define HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define if you have sys/ioctl.h */
|
|
||||||
#undef HAVE_SYS_IOCTL_H
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define HAVE_SYS_IOCTL_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define if you have sys/filio.h */
|
|
||||||
#undef HAVE_SYS_FILIO_H
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#define HAVE_SYS_FILIO_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define if you have strerror */
|
|
||||||
#define HAVE_STRERROR
|
|
||||||
|
|
||||||
/* Define if you have strdup() */
|
|
||||||
#define HAVE_STRDUP
|
|
||||||
|
|
||||||
/* Define according to how time.h should be included */
|
|
||||||
#define TIME_WITH_SYS_TIME 0
|
#define TIME_WITH_SYS_TIME 0
|
||||||
#undef HAVE_SYS_TIME_H
|
#undef HAVE_SYS_TIME_H
|
||||||
|
|
||||||
/* Define if you have sys/bitypes.h */
|
|
||||||
#undef HAVE_SYS_BITYPES_H
|
|
||||||
|
|
||||||
/* Define if the machine is big endian */
|
|
||||||
//#undef WORDS_BIGENDIAN
|
|
||||||
|
|
||||||
/* Define if your sprintf returns char * instead of int */
|
/* Define if your sprintf returns char * instead of int */
|
||||||
#undef BAD_SPRINTF
|
#undef BAD_SPRINTF
|
||||||
|
|
||||||
|
@ -103,56 +69,17 @@
|
||||||
/* Define if a declaration of sprintf/fprintf is needed */
|
/* Define if a declaration of sprintf/fprintf is needed */
|
||||||
#undef DECLARE_SPRINTF
|
#undef DECLARE_SPRINTF
|
||||||
|
|
||||||
/* Define if you have a POSIX.1 sys/wait.h */
|
|
||||||
#undef HAVE_SYS_WAIT_H
|
|
||||||
|
|
||||||
/* Define if you have sys/select.h */
|
|
||||||
#undef HAVE_SYS_SELECT_H
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define HAVE_SYS_SELECT_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define if you have strings.h */
|
|
||||||
#define HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define if you have arpa/inet.h */
|
|
||||||
#undef HAVE_ARPA_INET_H
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define HAVE_ARPA_INET_H
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define if you have sys/signal.h */
|
|
||||||
#undef HAVE_SYS_SIGNAL_H
|
|
||||||
|
|
||||||
/* Define if you have sys/stropts.h */
|
/* Define if you have sys/stropts.h */
|
||||||
#undef HAVE_SYS_STROPTS_H
|
#undef HAVE_SYS_STROPTS_H
|
||||||
|
|
||||||
/* Define to whatever your compiler thinks inline should be */
|
|
||||||
#define inline inline
|
|
||||||
|
|
||||||
/* Define to whatever your compiler thinks const should be */
|
|
||||||
#define const const
|
|
||||||
|
|
||||||
/* Define if your compiler doesn't like prototypes */
|
|
||||||
#undef NO_PROTOTYPES
|
|
||||||
|
|
||||||
/* Define if you don't have u_int32_t etc. typedef'd */
|
/* Define if you don't have u_int32_t etc. typedef'd */
|
||||||
#undef NEED_TYPEDEFS
|
#undef NEED_TYPEDEFS
|
||||||
#ifdef __sun__
|
#ifdef __sun__
|
||||||
#define NEED_TYPEDEFS
|
#define NEED_TYPEDEFS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define to sizeof(char) */
|
|
||||||
#define SIZEOF_CHAR 1
|
|
||||||
|
|
||||||
/* Define to sizeof(short) */
|
|
||||||
#define SIZEOF_SHORT 2
|
|
||||||
|
|
||||||
/* Define to sizeof(int) */
|
|
||||||
#define SIZEOF_INT 4
|
|
||||||
|
|
||||||
/* Define to sizeof(char *) */
|
/* Define to sizeof(char *) */
|
||||||
#define SIZEOF_CHAR_P (HOST_LONG_BITS / 8)
|
#define SIZEOF_CHAR_P SIZEOF_VOID_P
|
||||||
|
|
||||||
/* Define if you have random() */
|
/* Define if you have random() */
|
||||||
#undef HAVE_RANDOM
|
#undef HAVE_RANDOM
|
||||||
|
@ -160,12 +87,6 @@
|
||||||
/* Define if you have srandom() */
|
/* Define if you have srandom() */
|
||||||
#undef HAVE_SRANDOM
|
#undef HAVE_SRANDOM
|
||||||
|
|
||||||
/* Define if you have inet_aton */
|
|
||||||
#undef HAVE_INET_ATON
|
|
||||||
#ifndef _WIN32
|
|
||||||
#define HAVE_INET_ATON
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Define if you have setenv */
|
/* Define if you have setenv */
|
||||||
#undef HAVE_SETENV
|
#undef HAVE_SETENV
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WANT_SYS_IOCTL_H
|
#define WANT_SYS_IOCTL_H
|
||||||
|
#include <stdlib.h>
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
#include "ip_icmp.h"
|
#include "ip_icmp.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
@ -13,16 +14,18 @@
|
||||||
#include <sys/filio.h>
|
#include <sys/filio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void sofcantrcvmore(struct socket *so);
|
#ifdef _WIN32
|
||||||
static void sofcantsendmore(struct socket *so);
|
#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN)
|
||||||
|
#else
|
||||||
|
#define IS_EAGAIN(e) ((e) == EAGAIN)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
void
|
||||||
static void
|
|
||||||
so_init()
|
so_init()
|
||||||
{
|
{
|
||||||
/* Nothing yet */
|
/* Nothing yet */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct socket *
|
struct socket *
|
||||||
solookup(head, laddr, lport, faddr, fport)
|
solookup(head, laddr, lport, faddr, fport)
|
||||||
|
@ -33,19 +36,19 @@ solookup(head, laddr, lport, faddr, fport)
|
||||||
u_int fport;
|
u_int fport;
|
||||||
{
|
{
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
for (so = head->so_next; so != head; so = so->so_next) {
|
for (so = head->so_next; so != head; so = so->so_next) {
|
||||||
if (so->so_lport == lport &&
|
if (so->so_lport == lport &&
|
||||||
so->so_laddr.s_addr == laddr.s_addr &&
|
so->so_laddr.s_addr == laddr.s_addr &&
|
||||||
so->so_faddr.s_addr == faddr.s_addr &&
|
so->so_faddr.s_addr == faddr.s_addr &&
|
||||||
so->so_fport == fport)
|
so->so_fport == fport)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (so == head)
|
if (so == head)
|
||||||
return (struct socket *)NULL;
|
return (struct socket *)NULL;
|
||||||
return so;
|
return so;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -57,7 +60,7 @@ struct socket *
|
||||||
socreate()
|
socreate()
|
||||||
{
|
{
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
so = (struct socket *)malloc(sizeof(struct socket));
|
so = (struct socket *)malloc(sizeof(struct socket));
|
||||||
if(so) {
|
if(so) {
|
||||||
memset(so, 0, sizeof(struct socket));
|
memset(so, 0, sizeof(struct socket));
|
||||||
|
@ -82,10 +85,10 @@ sofree(so)
|
||||||
tcp_last_so = &tcb;
|
tcp_last_so = &tcb;
|
||||||
else if (so == udp_last_so)
|
else if (so == udp_last_so)
|
||||||
udp_last_so = &udb;
|
udp_last_so = &udb;
|
||||||
|
|
||||||
m_free(so->so_m);
|
m_free(so->so_m);
|
||||||
|
|
||||||
if(so->so_next && so->so_prev)
|
if(so->so_next && so->so_prev)
|
||||||
remque(so); /* crashes if so is not in a queue */
|
remque(so); /* crashes if so is not in a queue */
|
||||||
|
|
||||||
free(so);
|
free(so);
|
||||||
|
@ -100,22 +103,23 @@ int
|
||||||
soread(so)
|
soread(so)
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
{
|
{
|
||||||
int n, nn, lss, total;
|
int n, nn;
|
||||||
|
u_int lss, total;
|
||||||
struct sbuf *sb = &so->so_snd;
|
struct sbuf *sb = &so->so_snd;
|
||||||
int len = sb->sb_datalen - sb->sb_cc;
|
u_int len = sb->sb_datalen - sb->sb_cc;
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
int mss = so->so_tcpcb->t_maxseg;
|
u_int mss = so->so_tcpcb->t_maxseg;
|
||||||
|
|
||||||
DEBUG_CALL("soread");
|
DEBUG_CALL("soread");
|
||||||
DEBUG_ARG("so = %lx", (long )so);
|
DEBUG_ARG("so = %lx", (long )so);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No need to check if there's enough room to read.
|
* No need to check if there's enough room to read.
|
||||||
* soread wouldn't have been called if there weren't
|
* soread wouldn't have been called if there weren't
|
||||||
*/
|
*/
|
||||||
|
|
||||||
len = sb->sb_datalen - sb->sb_cc;
|
len = sb->sb_datalen - sb->sb_cc;
|
||||||
|
|
||||||
iov[0].iov_base = sb->sb_wptr;
|
iov[0].iov_base = sb->sb_wptr;
|
||||||
if (sb->sb_wptr < sb->sb_rptr) {
|
if (sb->sb_wptr < sb->sb_rptr) {
|
||||||
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
|
iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
|
||||||
|
@ -154,15 +158,16 @@ soread(so)
|
||||||
n = 1;
|
n = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_READV
|
#ifdef HAVE_READV
|
||||||
nn = readv(so->s, (struct iovec *)iov, n);
|
nn = readv(so->s, (struct iovec *)iov, n);
|
||||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||||
#else
|
#else
|
||||||
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||||
#endif
|
#endif
|
||||||
if (nn <= 0) {
|
if (nn <= 0) {
|
||||||
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
|
int error = WSAGetLastError();
|
||||||
|
if (nn < 0 && IS_EAGAIN(error))
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
|
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
|
||||||
|
@ -171,7 +176,7 @@ soread(so)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_READV
|
#ifndef HAVE_READV
|
||||||
/*
|
/*
|
||||||
* If there was no error, try and read the second time round
|
* If there was no error, try and read the second time round
|
||||||
|
@ -188,10 +193,10 @@ soread(so)
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
nn += ret;
|
nn += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Update fields */
|
/* Update fields */
|
||||||
sb->sb_cc += nn;
|
sb->sb_cc += nn;
|
||||||
sb->sb_wptr += nn;
|
sb->sb_wptr += nn;
|
||||||
|
@ -199,10 +204,10 @@ soread(so)
|
||||||
sb->sb_wptr -= sb->sb_datalen;
|
sb->sb_wptr -= sb->sb_datalen;
|
||||||
return nn;
|
return nn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get urgent data
|
* Get urgent data
|
||||||
*
|
*
|
||||||
* When the socket is created, we set it SO_OOBINLINE,
|
* When the socket is created, we set it SO_OOBINLINE,
|
||||||
* so when OOB data arrives, we soread() it and everything
|
* so when OOB data arrives, we soread() it and everything
|
||||||
* in the send buffer is sent as urgent data
|
* in the send buffer is sent as urgent data
|
||||||
|
@ -215,13 +220,13 @@ sorecvoob(so)
|
||||||
|
|
||||||
DEBUG_CALL("sorecvoob");
|
DEBUG_CALL("sorecvoob");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We take a guess at how much urgent data has arrived.
|
* We take a guess at how much urgent data has arrived.
|
||||||
* In most situations, when urgent data arrives, the next
|
* In most situations, when urgent data arrives, the next
|
||||||
* read() should get all the urgent data. This guess will
|
* read() should get all the urgent data. This guess will
|
||||||
* be wrong however if more data arrives just after the
|
* be wrong however if more data arrives just after the
|
||||||
* urgent data, or the read() doesn't return all the
|
* urgent data, or the read() doesn't return all the
|
||||||
* urgent data.
|
* urgent data.
|
||||||
*/
|
*/
|
||||||
soread(so);
|
soread(so);
|
||||||
|
@ -241,24 +246,24 @@ sosendoob(so)
|
||||||
{
|
{
|
||||||
struct sbuf *sb = &so->so_rcv;
|
struct sbuf *sb = &so->so_rcv;
|
||||||
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
|
char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
|
||||||
|
|
||||||
int n, len;
|
int n, len;
|
||||||
|
|
||||||
DEBUG_CALL("sosendoob");
|
DEBUG_CALL("sosendoob");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
|
DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
|
||||||
|
|
||||||
if (so->so_urgc > 2048)
|
if (so->so_urgc > 2048)
|
||||||
so->so_urgc = 2048; /* XXXX */
|
so->so_urgc = 2048; /* XXXX */
|
||||||
|
|
||||||
if (sb->sb_rptr < sb->sb_wptr) {
|
if (sb->sb_rptr < sb->sb_wptr) {
|
||||||
/* We can send it directly */
|
/* We can send it directly */
|
||||||
n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
|
n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
|
||||||
so->so_urgc -= n;
|
so->so_urgc -= n;
|
||||||
|
|
||||||
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
|
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Since there's no sendv or sendtov like writev,
|
* Since there's no sendv or sendtov like writev,
|
||||||
* we must copy all data to a linear buffer then
|
* we must copy all data to a linear buffer then
|
||||||
* send it all
|
* send it all
|
||||||
|
@ -278,20 +283,20 @@ sosendoob(so)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (n != len)
|
if (n != len)
|
||||||
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
|
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
|
||||||
#endif
|
#endif
|
||||||
DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
|
DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
|
||||||
}
|
}
|
||||||
|
|
||||||
sb->sb_cc -= n;
|
sb->sb_cc -= n;
|
||||||
sb->sb_rptr += n;
|
sb->sb_rptr += n;
|
||||||
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
||||||
sb->sb_rptr -= sb->sb_datalen;
|
sb->sb_rptr -= sb->sb_datalen;
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write data from so_rcv to so's socket,
|
* Write data from so_rcv to so's socket,
|
||||||
* updating all sbuf field as necessary
|
* updating all sbuf field as necessary
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
@ -300,12 +305,12 @@ sowrite(so)
|
||||||
{
|
{
|
||||||
int n,nn;
|
int n,nn;
|
||||||
struct sbuf *sb = &so->so_rcv;
|
struct sbuf *sb = &so->so_rcv;
|
||||||
int len = sb->sb_cc;
|
u_int len = sb->sb_cc;
|
||||||
struct iovec iov[2];
|
struct iovec iov[2];
|
||||||
|
|
||||||
DEBUG_CALL("sowrite");
|
DEBUG_CALL("sowrite");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
|
|
||||||
if (so->so_urgc) {
|
if (so->so_urgc) {
|
||||||
sosendoob(so);
|
sosendoob(so);
|
||||||
if (sb->sb_cc == 0)
|
if (sb->sb_cc == 0)
|
||||||
|
@ -316,9 +321,9 @@ sowrite(so)
|
||||||
* No need to check if there's something to write,
|
* No need to check if there's something to write,
|
||||||
* sowrite wouldn't have been called otherwise
|
* sowrite wouldn't have been called otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
len = sb->sb_cc;
|
len = sb->sb_cc;
|
||||||
|
|
||||||
iov[0].iov_base = sb->sb_rptr;
|
iov[0].iov_base = sb->sb_rptr;
|
||||||
if (sb->sb_rptr < sb->sb_wptr) {
|
if (sb->sb_rptr < sb->sb_wptr) {
|
||||||
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
|
iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
|
||||||
|
@ -341,14 +346,17 @@ sowrite(so)
|
||||||
|
|
||||||
#ifdef HAVE_READV
|
#ifdef HAVE_READV
|
||||||
nn = writev(so->s, (const struct iovec *)iov, n);
|
nn = writev(so->s, (const struct iovec *)iov, n);
|
||||||
|
|
||||||
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
||||||
#else
|
#else
|
||||||
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
|
||||||
#endif
|
#endif
|
||||||
/* This should never happen, but people tell me it does *shrug* */
|
/* This should never happen, but people tell me it does *shrug* */
|
||||||
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
|
if (nn < 0) {
|
||||||
return 0;
|
int error = WSAGetLastError();
|
||||||
|
if (IS_EAGAIN(error))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (nn <= 0) {
|
if (nn <= 0) {
|
||||||
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
|
DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
|
||||||
|
@ -357,7 +365,7 @@ sowrite(so)
|
||||||
tcp_sockclosed(sototcpcb(so));
|
tcp_sockclosed(sototcpcb(so));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_READV
|
#ifndef HAVE_READV
|
||||||
if (n == 2 && nn == iov[0].iov_len) {
|
if (n == 2 && nn == iov[0].iov_len) {
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -367,20 +375,20 @@ sowrite(so)
|
||||||
}
|
}
|
||||||
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Update sbuf */
|
/* Update sbuf */
|
||||||
sb->sb_cc -= nn;
|
sb->sb_cc -= nn;
|
||||||
sb->sb_rptr += nn;
|
sb->sb_rptr += nn;
|
||||||
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
|
||||||
sb->sb_rptr -= sb->sb_datalen;
|
sb->sb_rptr -= sb->sb_datalen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If in DRAIN mode, and there's no more data, set
|
* If in DRAIN mode, and there's no more data, set
|
||||||
* it CANTSENDMORE
|
* it CANTSENDMORE
|
||||||
*/
|
*/
|
||||||
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
|
if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
|
||||||
sofcantsendmore(so);
|
sofcantsendmore(so);
|
||||||
|
|
||||||
return nn;
|
return nn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,25 +400,26 @@ sorecvfrom(so)
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int addrlen = sizeof(struct sockaddr_in);
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
DEBUG_CALL("sorecvfrom");
|
DEBUG_CALL("sorecvfrom");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
|
|
||||||
if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
|
if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */
|
||||||
char buff[256];
|
char buff[256];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = recvfrom(so->s, buff, 256, 0,
|
len = recvfrom(so->s, buff, 256, 0,
|
||||||
(struct sockaddr *)&addr, &addrlen);
|
(struct sockaddr *)&addr, &addrlen);
|
||||||
/* XXX Check if reply is "correct"? */
|
/* XXX Check if reply is "correct"? */
|
||||||
|
|
||||||
if(len == -1 || len == 0) {
|
if(len == -1 || len == 0) {
|
||||||
u_char code=ICMP_UNREACH_PORT;
|
u_char code=ICMP_UNREACH_PORT;
|
||||||
|
|
||||||
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
int error = WSAGetLastError();
|
||||||
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
|
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||||
|
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
|
||||||
|
|
||||||
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
|
DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
|
||||||
errno,strerror(errno)));
|
errno,strerror(errno)));
|
||||||
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
||||||
|
@ -422,36 +431,38 @@ sorecvfrom(so)
|
||||||
udp_detach(so);
|
udp_detach(so);
|
||||||
} else { /* A "normal" UDP packet */
|
} else { /* A "normal" UDP packet */
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
int len, n;
|
u_int len;
|
||||||
|
ioctlsockopt_t n;
|
||||||
|
|
||||||
if (!(m = m_get())) return;
|
if (!(m = m_get())) return;
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Shouldn't FIONREAD packets destined for port 53,
|
* XXX Shouldn't FIONREAD packets destined for port 53,
|
||||||
* but I don't know the max packet size for DNS lookups
|
* but I don't know the max packet size for DNS lookups
|
||||||
*/
|
*/
|
||||||
len = M_FREEROOM(m);
|
len = M_FREEROOM(m);
|
||||||
/* if (so->so_fport != htons(53)) { */
|
/* if (so->so_fport != htons(53)) { */
|
||||||
ioctlsocket(so->s, FIONREAD, &n);
|
ioctlsocket(so->s, FIONREAD, &n);
|
||||||
|
|
||||||
if (n > len) {
|
if (n > len) {
|
||||||
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
|
n = (m->m_data - m->m_dat) + m->m_len + n + 1;
|
||||||
m_inc(m, n);
|
m_inc(m, n);
|
||||||
len = M_FREEROOM(m);
|
len = M_FREEROOM(m);
|
||||||
}
|
}
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
m->m_len = recvfrom(so->s, m->m_data, len, 0,
|
m->m_len = recvfrom(so->s, m->m_data, len, 0,
|
||||||
(struct sockaddr *)&addr, &addrlen);
|
(struct sockaddr *)&addr, &addrlen);
|
||||||
DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
|
DEBUG_MISC((dfd, " did recvfrom %zu, errno = %d-%s\n",
|
||||||
m->m_len, errno,strerror(errno)));
|
m->m_len, errno,strerror(errno)));
|
||||||
if(m->m_len<0) {
|
if(m->m_len<0) {
|
||||||
u_char code=ICMP_UNREACH_PORT;
|
u_char code=ICMP_UNREACH_PORT;
|
||||||
|
|
||||||
if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
int error = WSAGetLastError();
|
||||||
else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
|
if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST;
|
||||||
|
else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET;
|
||||||
|
|
||||||
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
|
DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
|
||||||
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
|
||||||
m_free(m);
|
m_free(m);
|
||||||
|
@ -474,8 +485,8 @@ sorecvfrom(so)
|
||||||
* m->m_len = 0;
|
* m->m_len = 0;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this packet was destined for CTL_ADDR,
|
* If this packet was destined for CTL_ADDR,
|
||||||
* make it look like that's where it came from, done by udp_output
|
* make it look like that's where it came from, done by udp_output
|
||||||
*/
|
*/
|
||||||
|
@ -498,7 +509,7 @@ sosendto(so, m)
|
||||||
DEBUG_CALL("sosendto");
|
DEBUG_CALL("sosendto");
|
||||||
DEBUG_ARG("so = %lx", (long)so);
|
DEBUG_ARG("so = %lx", (long)so);
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
|
if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
|
||||||
/* It's an alias */
|
/* It's an alias */
|
||||||
|
@ -515,14 +526,16 @@ sosendto(so, m)
|
||||||
addr.sin_addr = so->so_faddr;
|
addr.sin_addr = so->so_faddr;
|
||||||
addr.sin_port = so->so_fport;
|
addr.sin_port = so->so_fport;
|
||||||
|
|
||||||
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)));
|
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))));
|
||||||
|
|
||||||
/* Don't care what port we get */
|
/* Don't care what port we get */
|
||||||
ret = sendto(so->s, m->m_data, m->m_len, 0,
|
ret = sendto(so->s, m->m_data, m->m_len, 0,
|
||||||
(struct sockaddr *)&addr, sizeof (struct sockaddr));
|
(struct sockaddr *)&addr, sizeof (struct sockaddr));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kill the socket if there's no reply in 4 minutes,
|
* Kill the socket if there's no reply in 4 minutes,
|
||||||
* but only if it's an expirable socket
|
* but only if it's an expirable socket
|
||||||
|
@ -545,58 +558,57 @@ solisten(port, laddr, lport, flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
int s, addrlen = sizeof(addr), opt = 1;
|
int s;
|
||||||
|
socklen_t addrlen = sizeof(addr);
|
||||||
|
int opt = 1;
|
||||||
|
|
||||||
DEBUG_CALL("solisten");
|
DEBUG_CALL("solisten");
|
||||||
DEBUG_ARG("port = %d", port);
|
DEBUG_ARG("port = %d", port);
|
||||||
DEBUG_ARG("laddr = %x", laddr);
|
DEBUG_ARG("laddr = %x", laddr);
|
||||||
DEBUG_ARG("lport = %d", lport);
|
DEBUG_ARG("lport = %d", lport);
|
||||||
DEBUG_ARG("flags = %x", flags);
|
DEBUG_ARG("flags = %x", flags);
|
||||||
|
|
||||||
if ((so = socreate()) == NULL) {
|
if ((so = socreate()) == NULL) {
|
||||||
/* free(so); Not sofree() ??? free(NULL) == NOP */
|
/* free(so); Not sofree() ??? free(NULL) == NOP */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
|
/* Don't tcp_attach... we don't need so_snd nor so_rcv */
|
||||||
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
|
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
|
||||||
free(so);
|
free(so);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
insque(so,&tcb);
|
insque(so,&tcb);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SS_FACCEPTONCE sockets must time out.
|
* SS_FACCEPTONCE sockets must time out.
|
||||||
*/
|
*/
|
||||||
if (flags & SS_FACCEPTONCE)
|
if (flags & SS_FACCEPTONCE)
|
||||||
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
|
so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
|
||||||
|
|
||||||
so->so_state = (SS_FACCEPTCONN|flags);
|
so->so_state = (SS_FACCEPTCONN|flags);
|
||||||
so->so_lport = lport; /* Kept in network format */
|
so->so_lport = lport; /* Kept in network format */
|
||||||
so->so_laddr.s_addr = laddr; /* Ditto */
|
so->so_laddr.s_addr = laddr; /* Ditto */
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
addr.sin_port = port;
|
addr.sin_port = port;
|
||||||
|
|
||||||
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
|
||||||
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
|
(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
|
||||||
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
|
(bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
|
||||||
(listen(s,1) < 0)) {
|
(listen(s,1) < 0)) {
|
||||||
int tmperrno = errno; /* Don't clobber the real reason we failed */
|
int error = WSAGetLastError(); /* Don't clobber the real reason we failed */
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
sofree(so);
|
sofree(so);
|
||||||
/* Restore the real errno */
|
/* Restore the real errno */
|
||||||
#ifdef _WIN32
|
WSASetLastError(error);
|
||||||
WSASetLastError(tmperrno);
|
|
||||||
#else
|
|
||||||
errno = tmperrno;
|
|
||||||
#endif
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
|
||||||
|
|
||||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
||||||
so->so_fport = addr.sin_port;
|
so->so_fport = addr.sin_port;
|
||||||
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
|
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
|
||||||
|
@ -608,32 +620,30 @@ solisten(port, laddr, lport, flags)
|
||||||
return so;
|
return so;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
/*
|
|
||||||
* Data is available in so_rcv
|
* Data is available in so_rcv
|
||||||
* Just write() the data to the socket
|
* Just write() the data to the socket
|
||||||
* XXX not yet...
|
* XXX not yet...
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
sorwakeup(so)
|
sorwakeup(so)
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
{
|
{
|
||||||
/* sowrite(so); */
|
/* sowrite(so); */
|
||||||
/* FD_CLR(so->s,&writefds); */
|
/* FD_CLR(so->s,&writefds); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data has been freed in so_snd
|
* Data has been freed in so_snd
|
||||||
* We have room for a read() if we want to
|
* We have room for a read() if we want to
|
||||||
* For now, don't read, it'll be done in the main loop
|
* For now, don't read, it'll be done in the main loop
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
sowwakeup(so)
|
sowwakeup(so)
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
{
|
{
|
||||||
/* Nothing, yet */
|
/* Nothing, yet */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Various session state calls
|
* Various session state calls
|
||||||
|
@ -658,8 +668,9 @@ soisfconnected(so)
|
||||||
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
|
so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
sofcantrcvmore(struct socket *so)
|
sofcantrcvmore(so)
|
||||||
|
struct socket *so;
|
||||||
{
|
{
|
||||||
if ((so->so_state & SS_NOFDREF) == 0) {
|
if ((so->so_state & SS_NOFDREF) == 0) {
|
||||||
shutdown(so->s,0);
|
shutdown(so->s,0);
|
||||||
|
@ -674,8 +685,9 @@ sofcantrcvmore(struct socket *so)
|
||||||
so->so_state |= SS_FCANTRCVMORE;
|
so->so_state |= SS_FCANTRCVMORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
sofcantsendmore(struct socket *so)
|
sofcantsendmore(so)
|
||||||
|
struct socket *so;
|
||||||
{
|
{
|
||||||
if ((so->so_state & SS_NOFDREF) == 0) {
|
if ((so->so_state & SS_NOFDREF) == 0) {
|
||||||
shutdown(so->s,1); /* send FIN to fhost */
|
shutdown(so->s,1); /* send FIN to fhost */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -33,21 +33,21 @@ struct socket {
|
||||||
struct in_addr so_laddr; /* local host table entry */
|
struct in_addr so_laddr; /* local host table entry */
|
||||||
u_int16_t so_fport; /* foreign port */
|
u_int16_t so_fport; /* foreign port */
|
||||||
u_int16_t so_lport; /* local port */
|
u_int16_t so_lport; /* local port */
|
||||||
|
|
||||||
u_int8_t so_iptos; /* Type of service */
|
u_int8_t so_iptos; /* Type of service */
|
||||||
u_int8_t so_emu; /* Is the socket emulated? */
|
u_int8_t so_emu; /* Is the socket emulated? */
|
||||||
|
|
||||||
u_char so_type; /* Type of socket, UDP or TCP */
|
u_char so_type; /* Type of socket, UDP or TCP */
|
||||||
int so_state; /* internal state flags SS_*, below */
|
int so_state; /* internal state flags SS_*, below */
|
||||||
|
|
||||||
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */
|
||||||
u_int so_expire; /* When the socket will expire */
|
u_int so_expire; /* When the socket will expire */
|
||||||
|
|
||||||
int so_queued; /* Number of packets queued from this socket */
|
int so_queued; /* Number of packets queued from this socket */
|
||||||
int so_nqueued; /* Number of packets queued in a row
|
int so_nqueued; /* Number of packets queued in a row
|
||||||
* Used to determine when to "downgrade" a session
|
* Used to determine when to "downgrade" a session
|
||||||
* from fastq to batchq */
|
* from fastq to batchq */
|
||||||
|
|
||||||
struct sbuf so_rcv; /* Receive buffer */
|
struct sbuf so_rcv; /* Receive buffer */
|
||||||
struct sbuf so_snd; /* Send buffer */
|
struct sbuf so_snd; /* Send buffer */
|
||||||
void * extra; /* Extra pointer */
|
void * extra; /* Extra pointer */
|
||||||
|
@ -81,19 +81,24 @@ struct iovec {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int));
|
void so_init(void);
|
||||||
struct socket * socreate _P((void));
|
struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int);
|
||||||
void sofree _P((struct socket *));
|
struct socket * socreate(void);
|
||||||
int soread _P((struct socket *));
|
void sofree(struct socket *);
|
||||||
void sorecvoob _P((struct socket *));
|
int soread(struct socket *);
|
||||||
int sosendoob _P((struct socket *));
|
void sorecvoob(struct socket *);
|
||||||
int sowrite _P((struct socket *));
|
int sosendoob(struct socket *);
|
||||||
void sorecvfrom _P((struct socket *));
|
int sowrite(struct socket *);
|
||||||
int sosendto _P((struct socket *, struct mbuf *));
|
void sorecvfrom(struct socket *);
|
||||||
struct socket * solisten _P((u_int, u_int32_t, u_int, int));
|
int sosendto(struct socket *, struct mbuf *);
|
||||||
void soisfconnecting _P((register struct socket *));
|
struct socket * solisten(u_int, u_int32_t, u_int, int);
|
||||||
void soisfconnected _P((register struct socket *));
|
void sorwakeup(struct socket *);
|
||||||
void soisfdisconnected _P((struct socket *));
|
void sowwakeup(struct socket *);
|
||||||
void sofwdrain _P((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 *);
|
||||||
|
|
||||||
#endif /* _SOCKET_H_ */
|
#endif /* _SOCKET_H_ */
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -42,6 +38,8 @@ typedef u_int32_t tcp_seq;
|
||||||
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
#define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */
|
||||||
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
#define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */
|
||||||
|
|
||||||
|
extern size_t tcp_rcvspace;
|
||||||
|
extern size_t tcp_sndspace;
|
||||||
extern struct socket *tcp_last_so;
|
extern struct socket *tcp_last_so;
|
||||||
|
|
||||||
#define TCP_SNDSPACE 8192
|
#define TCP_SNDSPACE 8192
|
||||||
|
@ -51,16 +49,20 @@ extern struct socket *tcp_last_so;
|
||||||
* TCP header.
|
* TCP header.
|
||||||
* Per RFC 793, September, 1981.
|
* Per RFC 793, September, 1981.
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tcphdr {
|
struct tcphdr {
|
||||||
u_int16_t th_sport; /* source port */
|
u_int16_t th_sport; /* source port */
|
||||||
u_int16_t th_dport; /* destination port */
|
u_int16_t th_dport; /* destination port */
|
||||||
tcp_seq th_seq; /* sequence number */
|
tcp_seq th_seq; /* sequence number */
|
||||||
tcp_seq th_ack; /* acknowledgement number */
|
tcp_seq th_ack; /* acknowledgement number */
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
u_int th_off:4, /* data offset */
|
u_char th_off:4, /* data offset */
|
||||||
th_x2:4; /* (unused) */
|
th_x2:4; /* (unused) */
|
||||||
#else
|
#else
|
||||||
u_int th_x2:4, /* (unused) */
|
u_char th_x2:4, /* (unused) */
|
||||||
th_off:4; /* data offset */
|
th_off:4; /* data offset */
|
||||||
#endif
|
#endif
|
||||||
u_int8_t th_flags;
|
u_int8_t th_flags;
|
||||||
|
@ -73,7 +75,11 @@ struct tcphdr {
|
||||||
u_int16_t th_win; /* window */
|
u_int16_t th_win; /* window */
|
||||||
u_int16_t th_sum; /* checksum */
|
u_int16_t th_sum; /* checksum */
|
||||||
u_int16_t th_urp; /* urgent pointer */
|
u_int16_t th_urp; /* urgent pointer */
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tcp_var.h"
|
#include "tcp_var.h"
|
||||||
|
|
||||||
|
@ -170,6 +176,6 @@ struct tcphdr {
|
||||||
|
|
||||||
extern tcp_seq tcp_iss; /* tcp initial send seq # */
|
extern tcp_seq tcp_iss; /* tcp initial send seq # */
|
||||||
|
|
||||||
extern const char * const tcpstates[];
|
extern char *tcpstates[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,8 +33,8 @@
|
||||||
/*
|
/*
|
||||||
* Changes and additions relating to SLiRP
|
* Changes and additions relating to SLiRP
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -48,16 +44,16 @@
|
||||||
* Since this is only used in "stats socket", we give meaning
|
* Since this is only used in "stats socket", we give meaning
|
||||||
* names instead of the REAL names
|
* names instead of the REAL names
|
||||||
*/
|
*/
|
||||||
const char * const tcpstates[] = {
|
char *tcpstates[] = {
|
||||||
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
|
/* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */
|
||||||
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
|
"REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD",
|
||||||
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
|
"ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
|
||||||
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
|
"LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u_char tcp_outflags[TCP_NSTATES] = {
|
u_char tcp_outflags[TCP_NSTATES] = {
|
||||||
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
|
TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
|
||||||
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
|
TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK,
|
||||||
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
|
TH_FIN|TH_ACK, TH_ACK, TH_ACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,9 +63,7 @@ static const u_char tcp_outflags[TCP_NSTATES] = {
|
||||||
/*
|
/*
|
||||||
* Tcp output routine: figure out what should be sent and send it.
|
* Tcp output routine: figure out what should be sent and send it.
|
||||||
*/
|
*/
|
||||||
int
|
int tcp_output(register struct tcpcb *tp)
|
||||||
tcp_output(tp)
|
|
||||||
register struct tcpcb *tp;
|
|
||||||
{
|
{
|
||||||
register struct socket *so = tp->t_socket;
|
register struct socket *so = tp->t_socket;
|
||||||
register long len, win;
|
register long len, win;
|
||||||
|
@ -79,10 +73,10 @@ tcp_output(tp)
|
||||||
u_char opt[MAX_TCPOPTLEN];
|
u_char opt[MAX_TCPOPTLEN];
|
||||||
unsigned optlen, hdrlen;
|
unsigned optlen, hdrlen;
|
||||||
int idle, sendalot;
|
int idle, sendalot;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_output");
|
DEBUG_CALL("tcp_output");
|
||||||
DEBUG_ARG("tp = %lx", (long )tp);
|
DEBUG_ARG("tp = %lx", (long )tp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine length of data that should be transmitted,
|
* Determine length of data that should be transmitted,
|
||||||
* and flags that will be used.
|
* and flags that will be used.
|
||||||
|
@ -103,9 +97,9 @@ again:
|
||||||
win = min(tp->snd_wnd, tp->snd_cwnd);
|
win = min(tp->snd_wnd, tp->snd_cwnd);
|
||||||
|
|
||||||
flags = tcp_outflags[tp->t_state];
|
flags = tcp_outflags[tp->t_state];
|
||||||
|
|
||||||
DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
|
DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If in persist timeout with window of 0, send 1 byte.
|
* If in persist timeout with window of 0, send 1 byte.
|
||||||
* Otherwise, if window is small but nonzero
|
* Otherwise, if window is small but nonzero
|
||||||
|
@ -130,7 +124,7 @@ again:
|
||||||
* to send then the probe will be the FIN
|
* to send then the probe will be the FIN
|
||||||
* itself.
|
* itself.
|
||||||
*/
|
*/
|
||||||
if (off < so->so_snd.sb_cc)
|
if (off < (int)so->so_snd.sb_cc)
|
||||||
flags &= ~TH_FIN;
|
flags &= ~TH_FIN;
|
||||||
win = 1;
|
win = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,7 +152,7 @@ again:
|
||||||
tp->snd_nxt = tp->snd_una;
|
tp->snd_nxt = tp->snd_una;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > tp->t_maxseg) {
|
if (len > tp->t_maxseg) {
|
||||||
len = tp->t_maxseg;
|
len = tp->t_maxseg;
|
||||||
sendalot = 1;
|
sendalot = 1;
|
||||||
|
@ -200,17 +194,17 @@ again:
|
||||||
* window, then want to send a window update to peer.
|
* window, then want to send a window update to peer.
|
||||||
*/
|
*/
|
||||||
if (win > 0) {
|
if (win > 0) {
|
||||||
/*
|
/*
|
||||||
* "adv" is the amount we can increase the window,
|
* "adv" is the amount we can increase the window,
|
||||||
* taking into account that we are limited by
|
* taking into account that we are limited by
|
||||||
* TCP_MAXWIN << tp->rcv_scale.
|
* TCP_MAXWIN << tp->rcv_scale.
|
||||||
*/
|
*/
|
||||||
long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
|
long adv = min(win, TCP_MAXWIN << tp->rcv_scale) -
|
||||||
(tp->rcv_adv - tp->rcv_nxt);
|
(tp->rcv_adv - tp->rcv_nxt);
|
||||||
|
|
||||||
if (adv >= (long) (2 * tp->t_maxseg))
|
if (adv >= (long)(2 * tp->t_maxseg))
|
||||||
goto send;
|
goto send;
|
||||||
if (2 * adv >= (long) so->so_rcv.sb_datalen)
|
if (2 * adv >= (long)so->so_rcv.sb_datalen)
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,8 +257,8 @@ again:
|
||||||
/*
|
/*
|
||||||
* No reason to send a segment, just return.
|
* No reason to send a segment, just return.
|
||||||
*/
|
*/
|
||||||
STAT(tcpstat.tcps_didnuttin++);
|
tcpstat.tcps_didnuttin++;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
send:
|
send:
|
||||||
|
@ -302,9 +296,9 @@ send:
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a timestamp and echo-reply if this is a SYN and our side
|
* Send a timestamp and echo-reply if this is a SYN and our side
|
||||||
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side
|
* wants to use timestamps (TF_REQ_TSTMP is set) or both our side
|
||||||
* and our peer have sent timestamps in our SYN's.
|
* and our peer have sent timestamps in our SYN's.
|
||||||
*/
|
*/
|
||||||
|
@ -322,7 +316,7 @@ send:
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
hdrlen += optlen;
|
hdrlen += optlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust data length if insertion of options will
|
* Adjust data length if insertion of options will
|
||||||
* bump the packet length beyond the t_maxseg length.
|
* bump the packet length beyond the t_maxseg length.
|
||||||
|
@ -339,13 +333,13 @@ send:
|
||||||
*/
|
*/
|
||||||
if (len) {
|
if (len) {
|
||||||
if (tp->t_force && len == 1)
|
if (tp->t_force && len == 1)
|
||||||
STAT(tcpstat.tcps_sndprobe++);
|
tcpstat.tcps_sndprobe++;
|
||||||
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
|
else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
|
||||||
STAT(tcpstat.tcps_sndrexmitpack++);
|
tcpstat.tcps_sndrexmitpack++;
|
||||||
STAT(tcpstat.tcps_sndrexmitbyte += len);
|
tcpstat.tcps_sndrexmitbyte += len;
|
||||||
} else {
|
} else {
|
||||||
STAT(tcpstat.tcps_sndpack++);
|
tcpstat.tcps_sndpack++;
|
||||||
STAT(tcpstat.tcps_sndbyte += len);
|
tcpstat.tcps_sndbyte += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = m_get();
|
m = m_get();
|
||||||
|
@ -354,16 +348,16 @@ send:
|
||||||
error = 1;
|
error = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
m->m_len = hdrlen;
|
m->m_len = hdrlen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will always succeed, since we make sure our mbufs
|
* This will always succeed, since we make sure our mbufs
|
||||||
* are big enough to hold one MSS packet + header + ... etc.
|
* are big enough to hold one MSS packet + header + ... etc.
|
||||||
*/
|
*/
|
||||||
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */
|
/* if (len <= MHLEN - hdrlen - max_linkhdr) { */
|
||||||
|
|
||||||
sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen);
|
sbcopy(&so->so_snd, off, len, mtod(m, caddr_t) + hdrlen);
|
||||||
m->m_len += len;
|
m->m_len += len;
|
||||||
|
|
||||||
/* } else {
|
/* } else {
|
||||||
|
@ -382,13 +376,13 @@ send:
|
||||||
flags |= TH_PUSH;
|
flags |= TH_PUSH;
|
||||||
} else {
|
} else {
|
||||||
if (tp->t_flags & TF_ACKNOW)
|
if (tp->t_flags & TF_ACKNOW)
|
||||||
STAT(tcpstat.tcps_sndacks++);
|
tcpstat.tcps_sndacks++;
|
||||||
else if (flags & (TH_SYN|TH_FIN|TH_RST))
|
else if (flags & (TH_SYN|TH_FIN|TH_RST))
|
||||||
STAT(tcpstat.tcps_sndctrl++);
|
tcpstat.tcps_sndctrl++;
|
||||||
else if (SEQ_GT(tp->snd_up, tp->snd_una))
|
else if (SEQ_GT(tp->snd_up, tp->snd_una))
|
||||||
STAT(tcpstat.tcps_sndurg++);
|
tcpstat.tcps_sndurg++;
|
||||||
else
|
else
|
||||||
STAT(tcpstat.tcps_sndwinup++);
|
tcpstat.tcps_sndwinup++;
|
||||||
|
|
||||||
m = m_get();
|
m = m_get();
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
|
@ -396,12 +390,12 @@ send:
|
||||||
error = 1;
|
error = 1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
m->m_len = hdrlen;
|
m->m_len = hdrlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
ti = mtod(m, struct tcpiphdr *);
|
ti = mtod(m, struct tcpiphdr *);
|
||||||
|
|
||||||
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
|
memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -409,7 +403,7 @@ send:
|
||||||
* window for use in delaying messages about window sizes.
|
* window for use in delaying messages about window sizes.
|
||||||
* If resending a FIN, be sure not to use a new sequence number.
|
* If resending a FIN, be sure not to use a new sequence number.
|
||||||
*/
|
*/
|
||||||
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
|
if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
|
||||||
tp->snd_nxt == tp->snd_max)
|
tp->snd_nxt == tp->snd_max)
|
||||||
tp->snd_nxt--;
|
tp->snd_nxt--;
|
||||||
/*
|
/*
|
||||||
|
@ -439,17 +433,17 @@ send:
|
||||||
* Calculate receive window. Don't shrink window,
|
* Calculate receive window. Don't shrink window,
|
||||||
* but avoid silly window syndrome.
|
* but avoid silly window syndrome.
|
||||||
*/
|
*/
|
||||||
if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg)
|
if (win < (so->so_rcv.sb_datalen / 4) && win < tp->t_maxseg)
|
||||||
win = 0;
|
win = 0;
|
||||||
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
|
if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale))
|
||||||
win = (long)TCP_MAXWIN << tp->rcv_scale;
|
win = (u_long) (TCP_MAXWIN << tp->rcv_scale);
|
||||||
if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
|
if (win < (tp->rcv_adv - tp->rcv_nxt))
|
||||||
win = (long)(tp->rcv_adv - tp->rcv_nxt);
|
win = (tp->rcv_adv - tp->rcv_nxt);
|
||||||
ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
|
ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale));
|
||||||
|
|
||||||
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
if (SEQ_GT(tp->snd_up, tp->snd_una)) {
|
||||||
ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
|
ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq)));
|
||||||
#ifdef notdef
|
#ifdef notdef
|
||||||
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
|
if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
|
||||||
ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
|
ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt));
|
||||||
#endif
|
#endif
|
||||||
|
@ -500,7 +494,7 @@ send:
|
||||||
if (tp->t_rtt == 0) {
|
if (tp->t_rtt == 0) {
|
||||||
tp->t_rtt = 1;
|
tp->t_rtt = 1;
|
||||||
tp->t_rtseq = startseq;
|
tp->t_rtseq = startseq;
|
||||||
STAT(tcpstat.tcps_segstimed++);
|
tcpstat.tcps_segstimed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,14 +525,14 @@ send:
|
||||||
* the template, but need a way to checksum without them.
|
* the template, but need a way to checksum without them.
|
||||||
*/
|
*/
|
||||||
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
|
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
((struct ip *)ti)->ip_len = (u_int16_t) m->m_len;
|
||||||
|
|
||||||
((struct ip *)ti)->ip_len = m->m_len;
|
((struct ip *)ti)->ip_ttl = ip_defttl;
|
||||||
|
|
||||||
((struct ip *)ti)->ip_ttl = IPDEFTTL;
|
|
||||||
((struct ip *)ti)->ip_tos = so->so_iptos;
|
((struct ip *)ti)->ip_tos = so->so_iptos;
|
||||||
|
|
||||||
/* #if BSD >= 43 */
|
/* #if BSD >= 43 */
|
||||||
/* Don't do IP options... */
|
/* Don't do IP options... */
|
||||||
/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
|
/* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
|
||||||
|
@ -547,7 +541,7 @@ send:
|
||||||
error = ip_output(so, m);
|
error = ip_output(so, m);
|
||||||
|
|
||||||
/* #else
|
/* #else
|
||||||
* error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
|
* error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
|
||||||
* so->so_options & SO_DONTROUTE);
|
* so->so_options & SO_DONTROUTE);
|
||||||
* #endif
|
* #endif
|
||||||
*/
|
*/
|
||||||
|
@ -567,7 +561,7 @@ out:
|
||||||
*/
|
*/
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
STAT(tcpstat.tcps_sndtotal++);
|
tcpstat.tcps_sndtotal++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data sent (as far as we can tell).
|
* Data sent (as far as we can tell).
|
||||||
|
@ -585,9 +579,7 @@ out:
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void tcp_setpersist(register struct tcpcb *tp)
|
||||||
tcp_setpersist(tp)
|
|
||||||
register struct tcpcb *tp;
|
|
||||||
{
|
{
|
||||||
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
|
int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -36,14 +32,14 @@
|
||||||
|
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
int tcp_keepidle = TCPTV_KEEP_IDLE;
|
||||||
|
int tcp_keepintvl = TCPTV_KEEPINTVL;
|
||||||
|
int tcp_maxidle;
|
||||||
|
int so_options = DO_KEEPALIVE;
|
||||||
|
|
||||||
struct tcpstat tcpstat; /* tcp statistics */
|
struct tcpstat tcpstat; /* tcp statistics */
|
||||||
#endif
|
|
||||||
|
|
||||||
u_int32_t tcp_now; /* for RFC 1323 timestamps */
|
u_int32_t tcp_now; /* for RFC 1323 timestamps */
|
||||||
|
|
||||||
static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fast timeout routine for processing delayed acks
|
* Fast timeout routine for processing delayed acks
|
||||||
*/
|
*/
|
||||||
|
@ -54,7 +50,7 @@ tcp_fasttimo()
|
||||||
register struct tcpcb *tp;
|
register struct tcpcb *tp;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_fasttimo");
|
DEBUG_CALL("tcp_fasttimo");
|
||||||
|
|
||||||
so = tcb.so_next;
|
so = tcb.so_next;
|
||||||
if (so)
|
if (so)
|
||||||
for (; so != &tcb; so = so->so_next)
|
for (; so != &tcb; so = so->so_next)
|
||||||
|
@ -62,7 +58,7 @@ tcp_fasttimo()
|
||||||
(tp->t_flags & TF_DELACK)) {
|
(tp->t_flags & TF_DELACK)) {
|
||||||
tp->t_flags &= ~TF_DELACK;
|
tp->t_flags &= ~TF_DELACK;
|
||||||
tp->t_flags |= TF_ACKNOW;
|
tp->t_flags |= TF_ACKNOW;
|
||||||
STAT(tcpstat.tcps_delack++);
|
tcpstat.tcps_delack++;
|
||||||
(void) tcp_output(tp);
|
(void) tcp_output(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +76,8 @@ tcp_slowtimo()
|
||||||
register int i;
|
register int i;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_slowtimo");
|
DEBUG_CALL("tcp_slowtimo");
|
||||||
|
|
||||||
|
tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
|
||||||
/*
|
/*
|
||||||
* Search through tcb's and update active timers.
|
* Search through tcb's and update active timers.
|
||||||
*/
|
*/
|
||||||
|
@ -126,19 +123,21 @@ tcp_canceltimers(tp)
|
||||||
tp->t_timer[i] = 0;
|
tp->t_timer[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
||||||
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
|
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP timer processing.
|
* TCP timer processing.
|
||||||
*/
|
*/
|
||||||
static struct tcpcb *
|
struct tcpcb *
|
||||||
tcp_timers(register struct tcpcb *tp, int timer)
|
tcp_timers(tp, timer)
|
||||||
|
register struct tcpcb *tp;
|
||||||
|
int timer;
|
||||||
{
|
{
|
||||||
register int rexmt;
|
register int rexmt;
|
||||||
|
|
||||||
DEBUG_CALL("tcp_timers");
|
DEBUG_CALL("tcp_timers");
|
||||||
|
|
||||||
switch (timer) {
|
switch (timer) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -149,8 +148,8 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
*/
|
*/
|
||||||
case TCPT_2MSL:
|
case TCPT_2MSL:
|
||||||
if (tp->t_state != TCPS_TIME_WAIT &&
|
if (tp->t_state != TCPS_TIME_WAIT &&
|
||||||
tp->t_idle <= TCP_MAXIDLE)
|
tp->t_idle <= tcp_maxidle)
|
||||||
tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL;
|
tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
|
||||||
else
|
else
|
||||||
tp = tcp_close(tp);
|
tp = tcp_close(tp);
|
||||||
break;
|
break;
|
||||||
|
@ -161,12 +160,12 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* to a longer retransmit interval and retransmit one segment.
|
* to a longer retransmit interval and retransmit one segment.
|
||||||
*/
|
*/
|
||||||
case TCPT_REXMT:
|
case TCPT_REXMT:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXXXX If a packet has timed out, then remove all the queued
|
* XXXXX If a packet has timed out, then remove all the queued
|
||||||
* packets for that session.
|
* packets for that session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
|
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
|
||||||
/*
|
/*
|
||||||
* This is a hack to suit our terminal server here at the uni of canberra
|
* This is a hack to suit our terminal server here at the uni of canberra
|
||||||
|
@ -175,33 +174,33 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* keep retransmitting it, it'll keep eating the zeroes, so we keep
|
* keep retransmitting it, it'll keep eating the zeroes, so we keep
|
||||||
* retransmitting, and eventually the connection dies...
|
* retransmitting, and eventually the connection dies...
|
||||||
* (this only happens on incoming data)
|
* (this only happens on incoming data)
|
||||||
*
|
*
|
||||||
* So, if we were gonna drop the connection from too many retransmits,
|
* So, if we were gonna drop the connection from too many retransmits,
|
||||||
* don't... instead halve the t_maxseg, which might break up the NULLs and
|
* don't... instead halve the t_maxseg, which might break up the NULLs and
|
||||||
* let them through
|
* let them through
|
||||||
*
|
*
|
||||||
* *sigh*
|
* *sigh*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
tp->t_maxseg >>= 1;
|
tp->t_maxseg >>= 1;
|
||||||
if (tp->t_maxseg < 32) {
|
if (tp->t_maxseg < 32) {
|
||||||
/*
|
/*
|
||||||
* We tried our best, now the connection must die!
|
* We tried our best, now the connection must die!
|
||||||
*/
|
*/
|
||||||
tp->t_rxtshift = TCP_MAXRXTSHIFT;
|
tp->t_rxtshift = TCP_MAXRXTSHIFT;
|
||||||
STAT(tcpstat.tcps_timeoutdrop++);
|
tcpstat.tcps_timeoutdrop++;
|
||||||
tp = tcp_drop(tp, tp->t_softerror);
|
tp = tcp_drop(tp, tp->t_softerror);
|
||||||
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
|
/* tp->t_softerror : ETIMEDOUT); */ /* XXX */
|
||||||
return (tp); /* XXX */
|
return (tp); /* XXX */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set rxtshift to 6, which is still at the maximum
|
* Set rxtshift to 6, which is still at the maximum
|
||||||
* backoff time
|
* backoff time
|
||||||
*/
|
*/
|
||||||
tp->t_rxtshift = 6;
|
tp->t_rxtshift = 6;
|
||||||
}
|
}
|
||||||
STAT(tcpstat.tcps_rexmttimeo++);
|
tcpstat.tcps_rexmttimeo++;
|
||||||
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
|
||||||
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
TCPT_RANGESET(tp->t_rxtcur, rexmt,
|
||||||
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
|
(short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */
|
||||||
|
@ -237,7 +236,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* size increase exponentially with time. If the
|
* size increase exponentially with time. If the
|
||||||
* window is larger than the path can handle, this
|
* window is larger than the path can handle, this
|
||||||
* exponential growth results in dropped packet(s)
|
* exponential growth results in dropped packet(s)
|
||||||
* almost immediately. To get more time between
|
* almost immediately. To get more time between
|
||||||
* drops but still "push" the network to take advantage
|
* drops but still "push" the network to take advantage
|
||||||
* of improving conditions, we switch from exponential
|
* of improving conditions, we switch from exponential
|
||||||
* to linear window opening at some threshold size.
|
* to linear window opening at some threshold size.
|
||||||
|
@ -264,7 +263,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* Force a byte to be output, if possible.
|
* Force a byte to be output, if possible.
|
||||||
*/
|
*/
|
||||||
case TCPT_PERSIST:
|
case TCPT_PERSIST:
|
||||||
STAT(tcpstat.tcps_persisttimeo++);
|
tcpstat.tcps_persisttimeo++;
|
||||||
tcp_setpersist(tp);
|
tcp_setpersist(tp);
|
||||||
tp->t_force = 1;
|
tp->t_force = 1;
|
||||||
(void) tcp_output(tp);
|
(void) tcp_output(tp);
|
||||||
|
@ -276,13 +275,13 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* or drop connection if idle for too long.
|
* or drop connection if idle for too long.
|
||||||
*/
|
*/
|
||||||
case TCPT_KEEP:
|
case TCPT_KEEP:
|
||||||
STAT(tcpstat.tcps_keeptimeo++);
|
tcpstat.tcps_keeptimeo++;
|
||||||
if (tp->t_state < TCPS_ESTABLISHED)
|
if (tp->t_state < TCPS_ESTABLISHED)
|
||||||
goto dropit;
|
goto dropit;
|
||||||
|
|
||||||
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */
|
/* if (tp->t_socket->so_options & SO_KEEPALIVE && */
|
||||||
if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) {
|
||||||
if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE)
|
if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
|
||||||
goto dropit;
|
goto dropit;
|
||||||
/*
|
/*
|
||||||
* Send a packet designed to force a response
|
* Send a packet designed to force a response
|
||||||
|
@ -296,7 +295,7 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
* by the protocol spec, this requires the
|
* by the protocol spec, this requires the
|
||||||
* correspondent TCP to respond.
|
* correspondent TCP to respond.
|
||||||
*/
|
*/
|
||||||
STAT(tcpstat.tcps_keepprobe++);
|
tcpstat.tcps_keepprobe++;
|
||||||
#ifdef TCP_COMPAT_42
|
#ifdef TCP_COMPAT_42
|
||||||
/*
|
/*
|
||||||
* The keepalive packet must have nonzero length
|
* The keepalive packet must have nonzero length
|
||||||
|
@ -308,13 +307,13 @@ tcp_timers(register struct tcpcb *tp, int timer)
|
||||||
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
|
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
|
||||||
tp->rcv_nxt, tp->snd_una - 1, 0);
|
tp->rcv_nxt, tp->snd_una - 1, 0);
|
||||||
#endif
|
#endif
|
||||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
|
tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
|
||||||
} else
|
} else
|
||||||
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
|
tp->t_timer[TCPT_KEEP] = tcp_keepidle;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dropit:
|
dropit:
|
||||||
STAT(tcpstat.tcps_keepdrops++);
|
tcpstat.tcps_keepdrops++;
|
||||||
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
|
tp = tcp_drop(tp, 0); /* ETIMEDOUT); */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -126,12 +122,17 @@ char *tcptimers[] =
|
||||||
(tv) = (tvmax); \
|
(tv) = (tvmax); \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const int tcp_backoff[];
|
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[];
|
||||||
|
|
||||||
struct tcpcb;
|
struct tcpcb;
|
||||||
|
|
||||||
void tcp_fasttimo _P((void));
|
void tcp_fasttimo(void);
|
||||||
void tcp_slowtimo _P((void));
|
void tcp_slowtimo(void);
|
||||||
void tcp_canceltimers _P((struct tcpcb *));
|
void tcp_canceltimers(struct tcpcb *);
|
||||||
|
struct tcpcb * tcp_timers(register struct tcpcb *, int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -185,7 +181,6 @@ typedef u_int32_t mbufp_32;
|
||||||
#endif
|
#endif
|
||||||
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
|
#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
/*
|
/*
|
||||||
* TCP statistics.
|
* TCP statistics.
|
||||||
* Many of these should be kept per connection,
|
* Many of these should be kept per connection,
|
||||||
|
@ -248,8 +243,6 @@ struct tcpstat {
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct tcpstat tcpstat; /* tcp statistics */
|
extern struct tcpstat tcpstat; /* tcp statistics */
|
||||||
#endif
|
|
||||||
|
|
||||||
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
|
extern u_int32_t tcp_now; /* for RFC 1323 timestamps */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* tftp.c - a simple, read-only tftp server for qemu
|
* tftp.c - a simple, read-only tftp server for qemu
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004 Magnus Damm <damm@opensource.se>
|
* Copyright (c) 2004 Magnus Damm <damm@opensource.se>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
@ -26,15 +26,15 @@
|
||||||
|
|
||||||
struct tftp_session {
|
struct tftp_session {
|
||||||
int in_use;
|
int in_use;
|
||||||
unsigned char filename[TFTP_FILENAME_MAX];
|
char filename[TFTP_FILENAME_MAX];
|
||||||
|
|
||||||
struct in_addr client_ip;
|
struct in_addr client_ip;
|
||||||
u_int16_t client_port;
|
u_int16_t client_port;
|
||||||
|
|
||||||
int timestamp;
|
int timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
|
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
|
||||||
|
|
||||||
const char *tftp_prefix;
|
const char *tftp_prefix;
|
||||||
|
|
||||||
|
@ -102,15 +102,8 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int bytes_read = 0;
|
int bytes_read = 0;
|
||||||
char buffer[1024];
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = snprintf(buffer, sizeof(buffer), "%s/%s",
|
fd = open(spt->filename, O_RDONLY | O_BINARY);
|
||||||
tftp_prefix, spt->filename);
|
|
||||||
if (n >= sizeof(buffer))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
fd = open(buffer, O_RDONLY | O_BINARY);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -127,53 +120,13 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
|
||||||
return bytes_read;
|
return bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tftp_send_oack(struct tftp_session *spt,
|
static int tftp_send_error(struct tftp_session *spt,
|
||||||
const char *key, uint32_t value,
|
|
||||||
struct tftp_t *recv_tp)
|
|
||||||
{
|
|
||||||
struct sockaddr_in saddr, daddr;
|
|
||||||
struct mbuf *m;
|
|
||||||
struct tftp_t *tp;
|
|
||||||
int n = 0;
|
|
||||||
|
|
||||||
m = m_get();
|
|
||||||
|
|
||||||
if (!m)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memset(m->m_data, 0, m->m_size);
|
|
||||||
|
|
||||||
m->m_data += IF_MAXLINKHDR;
|
|
||||||
tp = (void *)m->m_data;
|
|
||||||
m->m_data += sizeof(struct udpiphdr);
|
|
||||||
|
|
||||||
tp->tp_op = htons(TFTP_OACK);
|
|
||||||
n += sprintf(tp->x.tp_buf + n, "%s", key) + 1;
|
|
||||||
n += sprintf(tp->x.tp_buf + n, "%u", value) + 1;
|
|
||||||
|
|
||||||
saddr.sin_addr = recv_tp->ip.ip_dst;
|
|
||||||
saddr.sin_port = recv_tp->udp.uh_dport;
|
|
||||||
|
|
||||||
daddr.sin_addr = spt->client_ip;
|
|
||||||
daddr.sin_port = spt->client_port;
|
|
||||||
|
|
||||||
m->m_len = sizeof(struct tftp_t) - 514 + n -
|
|
||||||
sizeof(struct ip) - sizeof(struct udphdr);
|
|
||||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int tftp_send_error(struct tftp_session *spt,
|
|
||||||
u_int16_t errorcode, const char *msg,
|
u_int16_t errorcode, const char *msg,
|
||||||
struct tftp_t *recv_tp)
|
struct tftp_t *recv_tp)
|
||||||
{
|
{
|
||||||
struct sockaddr_in saddr, daddr;
|
struct sockaddr_in saddr, daddr;
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
struct tftp_t *tp;
|
struct tftp_t *tp;
|
||||||
int nobytes;
|
|
||||||
|
|
||||||
m = m_get();
|
m = m_get();
|
||||||
|
|
||||||
|
@ -183,13 +136,14 @@ static int tftp_send_error(struct tftp_session *spt,
|
||||||
|
|
||||||
memset(m->m_data, 0, m->m_size);
|
memset(m->m_data, 0, m->m_size);
|
||||||
|
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
tp = (void *)m->m_data;
|
tp = (void *)m->m_data;
|
||||||
m->m_data += sizeof(struct udpiphdr);
|
m->m_data += sizeof(struct udpiphdr);
|
||||||
|
|
||||||
tp->tp_op = htons(TFTP_ERROR);
|
tp->tp_op = htons(TFTP_ERROR);
|
||||||
tp->x.tp_error.tp_error_code = htons(errorcode);
|
tp->x.tp_error.tp_error_code = htons(errorcode);
|
||||||
strcpy(tp->x.tp_error.tp_msg, msg);
|
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;
|
||||||
|
|
||||||
saddr.sin_addr = recv_tp->ip.ip_dst;
|
saddr.sin_addr = recv_tp->ip.ip_dst;
|
||||||
saddr.sin_port = recv_tp->udp.uh_dport;
|
saddr.sin_port = recv_tp->udp.uh_dport;
|
||||||
|
@ -197,9 +151,7 @@ static int tftp_send_error(struct tftp_session *spt,
|
||||||
daddr.sin_addr = spt->client_ip;
|
daddr.sin_addr = spt->client_ip;
|
||||||
daddr.sin_port = spt->client_port;
|
daddr.sin_port = spt->client_port;
|
||||||
|
|
||||||
nobytes = 2;
|
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
|
||||||
|
|
||||||
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
|
|
||||||
sizeof(struct ip) - sizeof(struct udphdr);
|
sizeof(struct ip) - sizeof(struct udphdr);
|
||||||
|
|
||||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||||
|
@ -209,7 +161,7 @@ static int tftp_send_error(struct tftp_session *spt,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tftp_send_data(struct tftp_session *spt,
|
static int tftp_send_data(struct tftp_session *spt,
|
||||||
u_int16_t block_nr,
|
u_int16_t block_nr,
|
||||||
struct tftp_t *recv_tp)
|
struct tftp_t *recv_tp)
|
||||||
{
|
{
|
||||||
|
@ -230,10 +182,10 @@ static int tftp_send_data(struct tftp_session *spt,
|
||||||
|
|
||||||
memset(m->m_data, 0, m->m_size);
|
memset(m->m_data, 0, m->m_size);
|
||||||
|
|
||||||
m->m_data += IF_MAXLINKHDR;
|
m->m_data += if_maxlinkhdr;
|
||||||
tp = (void *)m->m_data;
|
tp = (void *)m->m_data;
|
||||||
m->m_data += sizeof(struct udpiphdr);
|
m->m_data += sizeof(struct udpiphdr);
|
||||||
|
|
||||||
tp->tp_op = htons(TFTP_DATA);
|
tp->tp_op = htons(TFTP_DATA);
|
||||||
tp->x.tp_data.tp_block_nr = htons(block_nr);
|
tp->x.tp_data.tp_block_nr = htons(block_nr);
|
||||||
|
|
||||||
|
@ -255,7 +207,7 @@ static int tftp_send_data(struct tftp_session *spt,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
|
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
|
||||||
sizeof(struct ip) - sizeof(struct udphdr);
|
sizeof(struct ip) - sizeof(struct udphdr);
|
||||||
|
|
||||||
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
|
||||||
|
@ -285,7 +237,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
||||||
spt = &tftp_sessions[s];
|
spt = &tftp_sessions[s];
|
||||||
|
|
||||||
src = tp->x.tp_buf;
|
src = tp->x.tp_buf;
|
||||||
dst = spt->filename;
|
dst = (u_int8_t *)spt->filename;
|
||||||
n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
|
n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
|
||||||
|
|
||||||
/* get name */
|
/* get name */
|
||||||
|
@ -297,30 +249,28 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[k] == '\0') {
|
if (src[k] == '\0') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k >= n) {
|
if (k >= n) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
k++;
|
k++;
|
||||||
|
|
||||||
/* check mode */
|
/* check mode */
|
||||||
if ((n - k) < 6) {
|
if ((n - k) < 6) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(&src[k], "octet\0", 6) != 0) {
|
if (memcmp(&src[k], "octet\0", 6) != 0) {
|
||||||
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
|
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
k += 6; /* skipping octet */
|
|
||||||
|
|
||||||
/* do sanity checks on the filename */
|
/* do sanity checks on the filename */
|
||||||
|
|
||||||
if ((spt->filename[0] != '/')
|
if ((spt->filename[0] != '/')
|
||||||
|
@ -332,60 +282,19 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
||||||
|
|
||||||
/* only allow exported prefixes */
|
/* only allow exported prefixes */
|
||||||
|
|
||||||
if (!tftp_prefix) {
|
if (!tftp_prefix
|
||||||
|
|| (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) {
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the file exists */
|
/* check if the file exists */
|
||||||
|
|
||||||
if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
|
if (tftp_read_data(spt, 0, (u_int8_t *)spt->filename, 0) < 0) {
|
||||||
tftp_send_error(spt, 1, "File not found", tp);
|
tftp_send_error(spt, 1, "File not found", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[n - 1] != 0) {
|
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (k < n) {
|
|
||||||
const char *key, *value;
|
|
||||||
|
|
||||||
key = src + k;
|
|
||||||
k += strlen(key) + 1;
|
|
||||||
|
|
||||||
if (k >= n) {
|
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = src + k;
|
|
||||||
k += strlen(value) + 1;
|
|
||||||
|
|
||||||
if (strcmp(key, "tsize") == 0) {
|
|
||||||
int tsize = atoi(value);
|
|
||||||
struct stat stat_p;
|
|
||||||
|
|
||||||
if (tsize == 0 && tftp_prefix) {
|
|
||||||
char buffer[1024];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = snprintf(buffer, sizeof(buffer), "%s/%s",
|
|
||||||
tftp_prefix, spt->filename);
|
|
||||||
|
|
||||||
if (stat(buffer, &stat_p) == 0)
|
|
||||||
tsize = stat_p.st_size;
|
|
||||||
else {
|
|
||||||
tftp_send_error(spt, 1, "File not found", tp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tftp_send_oack(spt, "tsize", tsize, tp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tftp_send_data(spt, 1, tp);
|
tftp_send_data(spt, 1, tp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,8 +308,8 @@ static void tftp_handle_ack(struct tftp_t *tp, int pktlen)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tftp_send_data(&tftp_sessions[s],
|
if (tftp_send_data(&tftp_sessions[s],
|
||||||
ntohs(tp->x.tp_data.tp_block_nr) + 1,
|
ntohs(tp->x.tp_data.tp_block_nr) + 1,
|
||||||
tp) < 0) {
|
tp) < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,25 +9,32 @@
|
||||||
#define TFTP_DATA 3
|
#define TFTP_DATA 3
|
||||||
#define TFTP_ACK 4
|
#define TFTP_ACK 4
|
||||||
#define TFTP_ERROR 5
|
#define TFTP_ERROR 5
|
||||||
#define TFTP_OACK 6
|
|
||||||
|
|
||||||
#define TFTP_FILENAME_MAX 512
|
#define TFTP_FILENAME_MAX 512
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct tftp_t {
|
struct tftp_t {
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct udphdr udp;
|
struct udphdr udp;
|
||||||
u_int16_t tp_op;
|
u_int16_t tp_op;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
u_int16_t tp_block_nr;
|
u_int16_t tp_block_nr;
|
||||||
u_int8_t tp_buf[512];
|
u_int8_t tp_buf[512];
|
||||||
} tp_data;
|
} tp_data;
|
||||||
struct {
|
struct {
|
||||||
u_int16_t tp_error_code;
|
u_int16_t tp_error_code;
|
||||||
u_int8_t tp_msg[512];
|
u_int8_t tp_msg[512];
|
||||||
} tp_error;
|
} tp_error;
|
||||||
u_int8_t tp_buf[512 + 2];
|
u_int8_t tp_buf[512 + 2];
|
||||||
} x;
|
} x;
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
void tftp_input(struct mbuf *m);
|
void tftp_input(struct mbuf *m);
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -37,31 +33,27 @@
|
||||||
/*
|
/*
|
||||||
* Changes and additions relating to SLiRP
|
* Changes and additions relating to SLiRP
|
||||||
* Copyright (c) 1995 Danny Gasparovski.
|
* Copyright (c) 1995 Danny Gasparovski.
|
||||||
*
|
*
|
||||||
* Please read the file COPYRIGHT for the
|
* Please read the file COPYRIGHT for the
|
||||||
* terms and conditions of the copyright.
|
* terms and conditions of the copyright.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <slirp.h>
|
#include <slirp.h>
|
||||||
#include "ip_icmp.h"
|
#include "ip_icmp.h"
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
struct udpstat udpstat;
|
struct udpstat udpstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
struct socket udb;
|
struct socket udb;
|
||||||
|
|
||||||
static u_int8_t udp_tos(struct socket *so);
|
|
||||||
static void udp_emu(struct socket *so, struct mbuf *m);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UDP protocol implementation.
|
* UDP protocol implementation.
|
||||||
* Per RFC 768, August, 1980.
|
* Per RFC 768, August, 1980.
|
||||||
*/
|
*/
|
||||||
#ifndef COMPAT_42
|
#ifndef COMPAT_42
|
||||||
#define UDPCKSUM 1
|
int udpcksum = 1;
|
||||||
#else
|
#else
|
||||||
#define UDPCKSUM 0 /* XXX */
|
int udpcksum = 0; /* XXX */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct socket *udp_last_so = &udb;
|
struct socket *udp_last_so = &udb;
|
||||||
|
@ -71,8 +63,8 @@ udp_init()
|
||||||
{
|
{
|
||||||
udb.so_next = udb.so_prev = &udb;
|
udb.so_next = udb.so_prev = &udb;
|
||||||
}
|
}
|
||||||
/* m->m_data points at ip packet header
|
/* m->m_data points at ip packet header
|
||||||
* m->m_len length ip packet
|
* m->m_len length ip packet
|
||||||
* ip->ip_len length data (IPDU)
|
* ip->ip_len length data (IPDU)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -84,14 +76,14 @@ udp_input(m, iphlen)
|
||||||
register struct udphdr *uh;
|
register struct udphdr *uh;
|
||||||
/* struct mbuf *opts = 0;*/
|
/* struct mbuf *opts = 0;*/
|
||||||
int len;
|
int len;
|
||||||
struct ip save_ip;
|
struct ip save_ip;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
|
|
||||||
DEBUG_CALL("udp_input");
|
DEBUG_CALL("udp_input");
|
||||||
DEBUG_ARG("m = %lx", (long)m);
|
DEBUG_ARG("m = %lx", (long)m);
|
||||||
DEBUG_ARG("iphlen = %d", iphlen);
|
DEBUG_ARG("iphlen = %d", iphlen);
|
||||||
|
|
||||||
STAT(udpstat.udps_ipackets++);
|
udpstat.udps_ipackets++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip IP options, if any; should skip this,
|
* Strip IP options, if any; should skip this,
|
||||||
|
@ -118,34 +110,34 @@ udp_input(m, iphlen)
|
||||||
|
|
||||||
if (ip->ip_len != len) {
|
if (ip->ip_len != len) {
|
||||||
if (len > ip->ip_len) {
|
if (len > ip->ip_len) {
|
||||||
STAT(udpstat.udps_badlen++);
|
udpstat.udps_badlen++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
m_adj(m, len - ip->ip_len);
|
m_adj(m, len - ip->ip_len);
|
||||||
ip->ip_len = len;
|
ip->ip_len = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save a copy of the IP header in case we want restore it
|
* Save a copy of the IP header in case we want restore it
|
||||||
* for sending an ICMP error message in response.
|
* for sending an ICMP error message in response.
|
||||||
*/
|
*/
|
||||||
save_ip = *ip;
|
save_ip = *ip;
|
||||||
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
|
save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checksum extended UDP header and data.
|
* Checksum extended UDP header and data.
|
||||||
*/
|
*/
|
||||||
if (UDPCKSUM && uh->uh_sum) {
|
if (udpcksum && uh->uh_sum) {
|
||||||
((struct ipovly *)ip)->ih_next = 0;
|
((struct ipovly *)ip)->ih_next = 0;
|
||||||
((struct ipovly *)ip)->ih_prev = 0;
|
((struct ipovly *)ip)->ih_prev = 0;
|
||||||
((struct ipovly *)ip)->ih_x1 = 0;
|
((struct ipovly *)ip)->ih_x1 = 0;
|
||||||
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
|
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
|
||||||
/* keep uh_sum for ICMP reply
|
/* keep uh_sum for ICMP reply
|
||||||
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
|
* uh->uh_sum = cksum(m, len + sizeof (struct ip));
|
||||||
* if (uh->uh_sum) {
|
* if (uh->uh_sum) {
|
||||||
*/
|
*/
|
||||||
if(cksum(m, len + sizeof(struct ip))) {
|
if(cksum(m, len + sizeof(struct ip))) {
|
||||||
STAT(udpstat.udps_badsum++);
|
udpstat.udps_badsum++;
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +165,7 @@ udp_input(m, iphlen)
|
||||||
if (so->so_lport != uh->uh_sport ||
|
if (so->so_lport != uh->uh_sport ||
|
||||||
so->so_laddr.s_addr != ip->ip_src.s_addr) {
|
so->so_laddr.s_addr != ip->ip_src.s_addr) {
|
||||||
struct socket *tmp;
|
struct socket *tmp;
|
||||||
|
|
||||||
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
|
for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {
|
||||||
if (tmp->so_lport == uh->uh_sport &&
|
if (tmp->so_lport == uh->uh_sport &&
|
||||||
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
|
tmp->so_laddr.s_addr == ip->ip_src.s_addr) {
|
||||||
|
@ -186,11 +178,11 @@ udp_input(m, iphlen)
|
||||||
if (tmp == &udb) {
|
if (tmp == &udb) {
|
||||||
so = NULL;
|
so = NULL;
|
||||||
} else {
|
} else {
|
||||||
STAT(udpstat.udpps_pcbcachemiss++);
|
udpstat.udpps_pcbcachemiss++;
|
||||||
udp_last_so = so;
|
udp_last_so = so;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (so == NULL) {
|
if (so == NULL) {
|
||||||
/*
|
/*
|
||||||
* If there's no socket for this packet,
|
* If there's no socket for this packet,
|
||||||
|
@ -198,22 +190,22 @@ udp_input(m, iphlen)
|
||||||
*/
|
*/
|
||||||
if ((so = socreate()) == NULL) goto bad;
|
if ((so = socreate()) == NULL) goto bad;
|
||||||
if(udp_attach(so) == -1) {
|
if(udp_attach(so) == -1) {
|
||||||
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
|
DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
|
||||||
errno,strerror(errno)));
|
errno,strerror(errno)));
|
||||||
sofree(so);
|
sofree(so);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup fields
|
* Setup fields
|
||||||
*/
|
*/
|
||||||
/* udp_last_so = so; */
|
/* udp_last_so = so; */
|
||||||
so->so_laddr = ip->ip_src;
|
so->so_laddr = ip->ip_src;
|
||||||
so->so_lport = uh->uh_sport;
|
so->so_lport = uh->uh_sport;
|
||||||
|
|
||||||
if ((so->so_iptos = udp_tos(so)) == 0)
|
if ((so->so_iptos = udp_tos(so)) == 0)
|
||||||
so->so_iptos = ip->ip_tos;
|
so->so_iptos = ip->ip_tos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXXXX Here, check if it's in udpexec_list,
|
* XXXXX Here, check if it's in udpexec_list,
|
||||||
* and if it is, do the fork_exec() etc.
|
* and if it is, do the fork_exec() etc.
|
||||||
|
@ -238,7 +230,7 @@ udp_input(m, iphlen)
|
||||||
m->m_data -= iphlen;
|
m->m_data -= iphlen;
|
||||||
*ip=save_ip;
|
*ip=save_ip;
|
||||||
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
|
DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
|
||||||
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
|
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
|
||||||
|
@ -256,7 +248,7 @@ bad:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int udp_output2(struct socket *so, struct mbuf *m,
|
int udp_output2(struct socket *so, struct mbuf *m,
|
||||||
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
||||||
int iptos)
|
int iptos)
|
||||||
{
|
{
|
||||||
|
@ -274,16 +266,19 @@ int udp_output2(struct socket *so, struct mbuf *m,
|
||||||
*/
|
*/
|
||||||
m->m_data -= sizeof(struct udpiphdr);
|
m->m_data -= sizeof(struct udpiphdr);
|
||||||
m->m_len += sizeof(struct udpiphdr);
|
m->m_len += sizeof(struct udpiphdr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in mbuf with extended UDP header
|
* Fill in mbuf with extended UDP header
|
||||||
* and addresses and length put into network format.
|
* and addresses and length put into network format.
|
||||||
*/
|
*/
|
||||||
ui = mtod(m, struct udpiphdr *);
|
ui = mtod(m, struct udpiphdr *);
|
||||||
ui->ui_next = ui->ui_prev = 0;
|
//ui->ui_next = ui->ui_prev = 0;
|
||||||
|
|
||||||
|
memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
|
||||||
|
|
||||||
ui->ui_x1 = 0;
|
ui->ui_x1 = 0;
|
||||||
ui->ui_pr = IPPROTO_UDP;
|
ui->ui_pr = IPPROTO_UDP;
|
||||||
ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
|
ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */
|
||||||
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
|
/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
|
||||||
ui->ui_src = saddr->sin_addr;
|
ui->ui_src = saddr->sin_addr;
|
||||||
ui->ui_dst = daddr->sin_addr;
|
ui->ui_dst = daddr->sin_addr;
|
||||||
|
@ -295,23 +290,23 @@ int udp_output2(struct socket *so, struct mbuf *m,
|
||||||
* Stuff checksum and output datagram.
|
* Stuff checksum and output datagram.
|
||||||
*/
|
*/
|
||||||
ui->ui_sum = 0;
|
ui->ui_sum = 0;
|
||||||
if (UDPCKSUM) {
|
if (udpcksum) {
|
||||||
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
|
if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
|
||||||
ui->ui_sum = 0xffff;
|
ui->ui_sum = 0xffff;
|
||||||
}
|
}
|
||||||
((struct ip *)ui)->ip_len = m->m_len;
|
((struct ip *)ui)->ip_len = (u_int16_t) m->m_len;
|
||||||
|
|
||||||
((struct ip *)ui)->ip_ttl = IPDEFTTL;
|
((struct ip *)ui)->ip_ttl = ip_defttl;
|
||||||
((struct ip *)ui)->ip_tos = iptos;
|
((struct ip *)ui)->ip_tos = iptos;
|
||||||
|
|
||||||
STAT(udpstat.udps_opackets++);
|
udpstat.udps_opackets++;
|
||||||
|
|
||||||
error = ip_output(so, m);
|
error = ip_output(so, m);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int udp_output(struct socket *so, struct mbuf *m,
|
int udp_output(struct socket *so, struct mbuf *m,
|
||||||
struct sockaddr_in *addr)
|
struct sockaddr_in *addr)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -325,7 +320,7 @@ int udp_output(struct socket *so, struct mbuf *m,
|
||||||
}
|
}
|
||||||
daddr.sin_addr = so->so_laddr;
|
daddr.sin_addr = so->so_laddr;
|
||||||
daddr.sin_port = so->so_lport;
|
daddr.sin_port = so->so_lport;
|
||||||
|
|
||||||
return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
|
return udp_output2(so, m, &saddr, &daddr, so->so_iptos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,25 +329,22 @@ udp_attach(so)
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
|
|
||||||
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
|
if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {
|
||||||
/*
|
/*
|
||||||
* Here, we bind() the socket. Although not really needed
|
* Here, we bind() the socket. Although not really needed
|
||||||
* (sendto() on an unbound socket will bind it), it's done
|
* (sendto() on an unbound socket will bind it), it's done
|
||||||
* here so that emulation of ytalk etc. don't have to do it
|
* here so that emulation of ytalk etc. don't have to do it
|
||||||
*/
|
*/
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = 0;
|
addr.sin_port = 0;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
|
if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {
|
||||||
int lasterrno=errno;
|
int error = WSAGetLastError();
|
||||||
closesocket(so->s);
|
closesocket(so->s);
|
||||||
so->s=-1;
|
so->s=-1;
|
||||||
#ifdef _WIN32
|
WSASetLastError(error);
|
||||||
WSASetLastError(lasterrno);
|
|
||||||
#else
|
|
||||||
errno=lasterrno;
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* success, insert in queue */
|
/* success, insert in queue */
|
||||||
so->so_expire = curtime + SO_EXPIRE;
|
so->so_expire = curtime + SO_EXPIRE;
|
||||||
|
@ -372,7 +364,7 @@ udp_detach(so)
|
||||||
sofree(so);
|
sofree(so);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct tos_t udptos[] = {
|
struct tos_t udptos[] = {
|
||||||
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
|
{0, 53, IPTOS_LOWDELAY, 0}, /* DNS */
|
||||||
{517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
|
{517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */
|
||||||
{518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
|
{518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */
|
||||||
|
@ -380,11 +372,12 @@ static const struct tos_t udptos[] = {
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static u_int8_t
|
u_int8_t
|
||||||
udp_tos(struct socket *so)
|
udp_tos(so)
|
||||||
|
struct socket *so;
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
while(udptos[i].tos) {
|
while(udptos[i].tos) {
|
||||||
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
|
if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) ||
|
||||||
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
|
(udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) {
|
||||||
|
@ -393,7 +386,7 @@ udp_tos(struct socket *so)
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,27 +397,29 @@ udp_tos(struct socket *so)
|
||||||
/*
|
/*
|
||||||
* Here, talk/ytalk/ntalk requests must be emulated
|
* Here, talk/ytalk/ntalk requests must be emulated
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
udp_emu(struct socket *so, struct mbuf *m)
|
udp_emu(so, m)
|
||||||
|
struct socket *so;
|
||||||
|
struct mbuf *m;
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
#ifdef EMULATE_TALK
|
#ifdef EMULATE_TALK
|
||||||
CTL_MSG_OLD *omsg;
|
CTL_MSG_OLD *omsg;
|
||||||
CTL_MSG *nmsg;
|
CTL_MSG *nmsg;
|
||||||
char buff[sizeof(CTL_MSG)];
|
char buff[sizeof(CTL_MSG)];
|
||||||
u_char type;
|
u_char type;
|
||||||
|
|
||||||
struct talk_request {
|
struct talk_request {
|
||||||
struct talk_request *next;
|
struct talk_request *next;
|
||||||
struct socket *udp_so;
|
struct socket *udp_so;
|
||||||
struct socket *tcp_so;
|
struct socket *tcp_so;
|
||||||
} *req;
|
} *req;
|
||||||
|
|
||||||
static struct talk_request *req_tbl = 0;
|
static struct talk_request *req_tbl = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cu_header {
|
struct cu_header {
|
||||||
uint16_t d_family; // destination family
|
uint16_t d_family; // destination family
|
||||||
uint16_t d_port; // destination port
|
uint16_t d_port; // destination port
|
||||||
|
@ -451,7 +446,7 @@ struct cu_header {
|
||||||
*/
|
*/
|
||||||
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#define IS_OLD (so->so_emu == EMU_TALK)
|
#define IS_OLD (so->so_emu == EMU_TALK)
|
||||||
|
|
||||||
#define COPY_MSG(dest, src) { dest->type = src->type; \
|
#define COPY_MSG(dest, src) { dest->type = src->type; \
|
||||||
|
@ -474,7 +469,7 @@ struct cu_header {
|
||||||
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
|
OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port;
|
||||||
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
|
OTOSIN(omsg, ctl_addr)->sin_addr = our_addr;
|
||||||
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
|
strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD);
|
||||||
} else { /* new talk */
|
} else { /* new talk */
|
||||||
omsg = (CTL_MSG_OLD *) buff;
|
omsg = (CTL_MSG_OLD *) buff;
|
||||||
nmsg = mtod(m, CTL_MSG *);
|
nmsg = mtod(m, CTL_MSG *);
|
||||||
type = nmsg->type;
|
type = nmsg->type;
|
||||||
|
@ -482,10 +477,10 @@ struct cu_header {
|
||||||
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
|
OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr;
|
||||||
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
|
strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == LOOK_UP)
|
if (type == LOOK_UP)
|
||||||
return; /* for LOOK_UP this is enough */
|
return; /* for LOOK_UP this is enough */
|
||||||
|
|
||||||
if (IS_OLD) { /* make a copy of the message */
|
if (IS_OLD) { /* make a copy of the message */
|
||||||
COPY_MSG(nmsg, omsg);
|
COPY_MSG(nmsg, omsg);
|
||||||
nmsg->vers = 1;
|
nmsg->vers = 1;
|
||||||
|
@ -504,75 +499,75 @@ struct cu_header {
|
||||||
* ports, 517 and 518. This is why we have two copies
|
* ports, 517 and 518. This is why we have two copies
|
||||||
* of the message, one in old talk and one in new talk
|
* of the message, one in old talk and one in new talk
|
||||||
* format.
|
* format.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (type == ANNOUNCE) {
|
if (type == ANNOUNCE) {
|
||||||
int s;
|
int s;
|
||||||
u_short temp_port;
|
u_short temp_port;
|
||||||
|
|
||||||
for(req = req_tbl; req; req = req->next)
|
for(req = req_tbl; req; req = req->next)
|
||||||
if (so == req->udp_so)
|
if (so == req->udp_so)
|
||||||
break; /* found it */
|
break; /* found it */
|
||||||
|
|
||||||
if (!req) { /* no entry for so, create new */
|
if (!req) { /* no entry for so, create new */
|
||||||
req = (struct talk_request *)
|
req = (struct talk_request *)
|
||||||
malloc(sizeof(struct talk_request));
|
malloc(sizeof(struct talk_request));
|
||||||
req->udp_so = so;
|
req->udp_so = so;
|
||||||
req->tcp_so = solisten(0,
|
req->tcp_so = solisten(0,
|
||||||
OTOSIN(omsg, addr)->sin_addr.s_addr,
|
OTOSIN(omsg, addr)->sin_addr.s_addr,
|
||||||
OTOSIN(omsg, addr)->sin_port,
|
OTOSIN(omsg, addr)->sin_port,
|
||||||
SS_FACCEPTONCE);
|
SS_FACCEPTONCE);
|
||||||
req->next = req_tbl;
|
req->next = req_tbl;
|
||||||
req_tbl = req;
|
req_tbl = req;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* replace port number in addr field */
|
/* replace port number in addr field */
|
||||||
addrlen = sizeof(addr);
|
addrlen = sizeof(addr);
|
||||||
getsockname(req->tcp_so->s,
|
getsockname(req->tcp_so->s,
|
||||||
(struct sockaddr *) &addr,
|
(struct sockaddr *) &addr,
|
||||||
&addrlen);
|
&addrlen);
|
||||||
OTOSIN(omsg, addr)->sin_port = addr.sin_port;
|
OTOSIN(omsg, addr)->sin_port = addr.sin_port;
|
||||||
OTOSIN(omsg, addr)->sin_addr = our_addr;
|
OTOSIN(omsg, addr)->sin_addr = our_addr;
|
||||||
OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
|
OTOSIN(nmsg, addr)->sin_port = addr.sin_port;
|
||||||
OTOSIN(nmsg, addr)->sin_addr = our_addr;
|
OTOSIN(nmsg, addr)->sin_addr = our_addr;
|
||||||
|
|
||||||
/* send LEAVE_INVITEs */
|
/* send LEAVE_INVITEs */
|
||||||
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
||||||
OTOSIN(omsg, ctl_addr)->sin_port = 0;
|
OTOSIN(omsg, ctl_addr)->sin_port = 0;
|
||||||
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
|
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
|
||||||
omsg->type = nmsg->type = LEAVE_INVITE;
|
omsg->type = nmsg->type = LEAVE_INVITE;
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
addr.sin_addr = our_addr;
|
addr.sin_addr = our_addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons(517);
|
addr.sin_port = htons(517);
|
||||||
sendto(s, (char *)omsg, sizeof(*omsg), 0,
|
sendto(s, (char *)omsg, sizeof(*omsg), 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr));
|
(struct sockaddr *)&addr, sizeof(addr));
|
||||||
addr.sin_port = htons(518);
|
addr.sin_port = htons(518);
|
||||||
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
||||||
(struct sockaddr *) &addr, sizeof(addr));
|
(struct sockaddr *) &addr, sizeof(addr));
|
||||||
closesocket(s) ;
|
closesocket(s) ;
|
||||||
|
|
||||||
omsg->type = nmsg->type = ANNOUNCE;
|
omsg->type = nmsg->type = ANNOUNCE;
|
||||||
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
|
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
|
||||||
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
|
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it is a DELETE message, we send a copy to the
|
* If it is a DELETE message, we send a copy to the
|
||||||
* local daemons. Then we delete the entry corresponding
|
* local daemons. Then we delete the entry corresponding
|
||||||
* to our socket from the request table.
|
* to our socket from the request table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (type == DELETE) {
|
if (type == DELETE) {
|
||||||
struct talk_request *temp_req, *req_next;
|
struct talk_request *temp_req, *req_next;
|
||||||
int s;
|
int s;
|
||||||
u_short temp_port;
|
u_short temp_port;
|
||||||
|
|
||||||
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
temp_port = OTOSIN(omsg, ctl_addr)->sin_port;
|
||||||
OTOSIN(omsg, ctl_addr)->sin_port = 0;
|
OTOSIN(omsg, ctl_addr)->sin_port = 0;
|
||||||
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
|
OTOSIN(nmsg, ctl_addr)->sin_port = 0;
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
addr.sin_addr = our_addr;
|
addr.sin_addr = our_addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
|
@ -583,7 +578,7 @@ struct cu_header {
|
||||||
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
sendto(s, (char *)nmsg, sizeof(*nmsg), 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr));
|
(struct sockaddr *)&addr, sizeof(addr));
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
|
|
||||||
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
|
OTOSIN(omsg, ctl_addr)->sin_port = temp_port;
|
||||||
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
|
OTOSIN(nmsg, ctl_addr)->sin_port = temp_port;
|
||||||
|
|
||||||
|
@ -606,18 +601,18 @@ struct cu_header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case EMU_CUSEEME:
|
case EMU_CUSEEME:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cu-SeeMe emulation.
|
* Cu-SeeMe emulation.
|
||||||
* Hopefully the packet is more that 16 bytes long. We don't
|
* Hopefully the packet is more that 16 bytes long. We don't
|
||||||
* do any other tests, just replace the address and port
|
* do any other tests, just replace the address and port
|
||||||
* fields.
|
* fields.
|
||||||
*/
|
*/
|
||||||
if (m->m_len >= sizeof (*cu_head)) {
|
if (m->m_len >= sizeof (*cu_head)) {
|
||||||
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0)
|
||||||
return;
|
return;
|
||||||
|
@ -625,7 +620,7 @@ struct cu_header {
|
||||||
cu_head->s_port = addr.sin_port;
|
cu_head->s_port = addr.sin_port;
|
||||||
cu_head->so_addr = our_addr.s_addr;
|
cu_head->so_addr = our_addr.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,8 +634,9 @@ udp_listen(port, laddr, lport, flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
struct socket *so;
|
struct socket *so;
|
||||||
int addrlen = sizeof(struct sockaddr_in), opt = 1;
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||||||
|
int opt = 1;
|
||||||
|
|
||||||
if ((so = socreate()) == NULL) {
|
if ((so = socreate()) == NULL) {
|
||||||
free(so);
|
free(so);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -649,6 +645,7 @@ udp_listen(port, laddr, lport, flags)
|
||||||
so->so_expire = curtime + SO_EXPIRE;
|
so->so_expire = curtime + SO_EXPIRE;
|
||||||
insque(so,&udb);
|
insque(so,&udb);
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_in));
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_addr.s_addr = INADDR_ANY;
|
addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
addr.sin_port = port;
|
addr.sin_port = port;
|
||||||
|
@ -659,20 +656,20 @@ udp_listen(port, laddr, lport, flags)
|
||||||
}
|
}
|
||||||
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
|
||||||
/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
|
/* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */
|
||||||
|
|
||||||
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
|
||||||
so->so_fport = addr.sin_port;
|
so->so_fport = addr.sin_port;
|
||||||
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
|
if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
|
||||||
so->so_faddr = alias_addr;
|
so->so_faddr = alias_addr;
|
||||||
else
|
else
|
||||||
so->so_faddr = addr.sin_addr;
|
so->so_faddr = addr.sin_addr;
|
||||||
|
|
||||||
so->so_lport = lport;
|
so->so_lport = lport;
|
||||||
so->so_laddr.s_addr = laddr;
|
so->so_laddr.s_addr = laddr;
|
||||||
if (flags != SS_FACCEPTONCE)
|
if (flags != SS_FACCEPTONCE)
|
||||||
so->so_expire = 0;
|
so->so_expire = 0;
|
||||||
|
|
||||||
so->so_state = SS_ISFCONNECTED;
|
so->so_state = SS_ISFCONNECTED;
|
||||||
|
|
||||||
return so;
|
return so;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* documentation and/or other materials provided with the distribution.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
* may be used to endorse or promote products derived from this software
|
||||||
* without specific prior written permission.
|
* without specific prior written permission.
|
||||||
*
|
*
|
||||||
|
@ -46,12 +42,20 @@ extern struct socket *udp_last_so;
|
||||||
* Udp protocol header.
|
* Udp protocol header.
|
||||||
* Per RFC 768, September, 1981.
|
* Per RFC 768, September, 1981.
|
||||||
*/
|
*/
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(1)
|
||||||
|
#endif
|
||||||
|
|
||||||
struct udphdr {
|
struct udphdr {
|
||||||
u_int16_t uh_sport; /* source port */
|
u_int16_t uh_sport; /* source port */
|
||||||
u_int16_t uh_dport; /* destination port */
|
u_int16_t uh_dport; /* destination port */
|
||||||
int16_t uh_ulen; /* udp length */
|
int16_t uh_ulen; /* udp length */
|
||||||
u_int16_t uh_sum; /* udp checksum */
|
u_int16_t uh_sum; /* udp checksum */
|
||||||
};
|
} PACKED__;
|
||||||
|
|
||||||
|
#ifdef PRAGMA_PACK_SUPPORTED
|
||||||
|
#pragma pack(PACK_RESET)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UDP kernel structures and variables.
|
* UDP kernel structures and variables.
|
||||||
|
@ -72,7 +76,6 @@ struct udpiphdr {
|
||||||
#define ui_ulen ui_u.uh_ulen
|
#define ui_ulen ui_u.uh_ulen
|
||||||
#define ui_sum ui_u.uh_sum
|
#define ui_sum ui_u.uh_sum
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
struct udpstat {
|
struct udpstat {
|
||||||
/* input statistics: */
|
/* input statistics: */
|
||||||
u_long udps_ipackets; /* total input packets */
|
u_long udps_ipackets; /* total input packets */
|
||||||
|
@ -86,7 +89,6 @@ struct udpstat {
|
||||||
/* output statistics: */
|
/* output statistics: */
|
||||||
u_long udps_opackets; /* total output packets */
|
u_long udps_opackets; /* total output packets */
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Names for UDP sysctl objects
|
* Names for UDP sysctl objects
|
||||||
|
@ -94,20 +96,19 @@ struct udpstat {
|
||||||
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
|
#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
|
||||||
#define UDPCTL_MAXID 2
|
#define UDPCTL_MAXID 2
|
||||||
|
|
||||||
#ifdef LOG_ENABLED
|
|
||||||
extern struct udpstat udpstat;
|
extern struct udpstat udpstat;
|
||||||
#endif
|
|
||||||
|
|
||||||
extern struct socket udb;
|
extern struct socket udb;
|
||||||
struct mbuf;
|
struct mbuf;
|
||||||
|
|
||||||
void udp_init _P((void));
|
void udp_init(void);
|
||||||
void udp_input _P((register struct mbuf *, int));
|
void udp_input(register struct mbuf *, int);
|
||||||
int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *));
|
int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *);
|
||||||
int udp_attach _P((struct socket *));
|
int udp_attach(struct socket *);
|
||||||
void udp_detach _P((struct socket *));
|
void udp_detach(struct socket *);
|
||||||
struct socket * udp_listen _P((u_int, u_int32_t, u_int, int));
|
u_int8_t udp_tos(struct socket *);
|
||||||
int udp_output2(struct socket *so, struct mbuf *m,
|
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,
|
||||||
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
struct sockaddr_in *saddr, struct sockaddr_in *daddr,
|
||||||
int iptos);
|
int iptos);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user