Revert "SLIRP 0.9.1"

This reverts commit 4682bb80a1.
This commit is contained in:
jvernet 2017-10-04 18:22:48 +02:00
parent c20d9d3c52
commit 605c811a4a
39 changed files with 2006 additions and 2299 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 1995 Danny Gasparovski.
*
* Please read the file COPYRIGHT for the
*
* Please read the file COPYRIGHT for the
* terms and conditions of the copyright.
*/
@ -36,5 +36,15 @@ extern int slirp_debug;
#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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -10,11 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following 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
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@ -126,12 +122,17 @@ char *tcptimers[] =
(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;
void tcp_fasttimo _P((void));
void tcp_slowtimo _P((void));
void tcp_canceltimers _P((struct tcpcb *));
void tcp_fasttimo(void);
void tcp_slowtimo(void);
void tcp_canceltimers(struct tcpcb *);
struct tcpcb * tcp_timers(register struct tcpcb *, int);
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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