diff --git a/BasiliskII/src/slirp/COPYRIGHT b/BasiliskII/src/slirp/COPYRIGHT index b7d6568e..3f331ee0 100644 --- a/BasiliskII/src/slirp/COPYRIGHT +++ b/BasiliskII/src/slirp/COPYRIGHT @@ -16,7 +16,7 @@ The copyright terms and conditions: ---BEGIN--- Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -25,6 +25,9 @@ The copyright terms and conditions: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgment: + This product includes software developed by Danny Gasparovski. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY diff --git a/BasiliskII/src/slirp/bootp.c b/BasiliskII/src/slirp/bootp.c index a51b80c9..3ae3db20 100644 --- a/BasiliskII/src/slirp/bootp.c +++ b/BasiliskII/src/slirp/bootp.c @@ -1,8 +1,8 @@ /* * QEMU BOOTP/DHCP server - * + * * Copyright (c) 2004 Fabrice Bellard - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -38,8 +38,17 @@ typedef struct { BOOTPClient bootp_clients[NB_ADDR]; +const char *bootp_filename; + static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE }; +#ifdef DEBUG +#define dprintf(fmt, args...) \ +if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); } +#else +#define dprintf(fmt, args...) +#endif + static BOOTPClient *get_new_addr(struct in_addr *paddr) { BOOTPClient *bc; @@ -80,7 +89,7 @@ static void dhcp_decode(const uint8_t *buf, int size, const uint8_t *p, *p_end; int len, tag; - *pmsg_type = 0; + *pmsg_type = 0; p = buf; p_end = buf + size; @@ -92,7 +101,7 @@ static void dhcp_decode(const uint8_t *buf, int size, while (p < p_end) { tag = p[0]; if (tag == RFC1533_PAD) { - p++; + p++; } else if (tag == RFC1533_END) { break; } else { @@ -100,6 +109,7 @@ static void dhcp_decode(const uint8_t *buf, int size, if (p >= p_end) break; len = *p++; + dprintf("dhcp: tag=0x%02x len=%d\n", tag, len); switch(tag) { case RFC2132_MSG_TYPE: @@ -126,19 +136,20 @@ static void bootp_reply(struct bootp_t *bp) /* extract exact DHCP msg type */ dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type); - + dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type); + if (dhcp_msg_type == 0) dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */ - - if (dhcp_msg_type != DHCPDISCOVER && + + if (dhcp_msg_type != DHCPDISCOVER && dhcp_msg_type != DHCPREQUEST) return; /* XXX: this is a hack to get the client mac address */ memcpy(client_ethaddr, bp->bp_hwaddr, 6); - + if ((m = m_get()) == NULL) return; - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; rbp = (struct bootp_t *)m->m_data; m->m_data += sizeof(struct udpiphdr); memset(rbp, 0, sizeof(struct bootp_t)); @@ -146,8 +157,10 @@ static void bootp_reply(struct bootp_t *bp) if (dhcp_msg_type == DHCPDISCOVER) { new_addr: bc = get_new_addr(&daddr.sin_addr); - if (!bc) + if (!bc) { + dprintf("no address left\n"); return; + } memcpy(bc->macaddr, client_ethaddr, 6); } else { bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr); @@ -158,6 +171,11 @@ static void bootp_reply(struct bootp_t *bp) } } + if (bootp_filename) + snprintf(rbp->bp_file, sizeof(rbp->bp_file), "%s", bootp_filename); + + dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr)); + saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS); saddr.sin_port = htons(BOOTP_SERVER); @@ -185,7 +203,7 @@ static void bootp_reply(struct bootp_t *bp) *q++ = 1; *q++ = DHCPACK; } - + if (dhcp_msg_type == DHCPDISCOVER || dhcp_msg_type == DHCPREQUEST) { *q++ = RFC2132_SRV_ID; @@ -199,12 +217,12 @@ static void bootp_reply(struct bootp_t *bp) *q++ = 0xff; *q++ = 0xff; *q++ = 0x00; - + *q++ = RFC1533_GATEWAY; *q++ = 4; memcpy(q, &saddr.sin_addr, 4); q += 4; - + *q++ = RFC1533_DNS; *q++ = 4; dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS); @@ -226,8 +244,8 @@ static void bootp_reply(struct bootp_t *bp) } } *q++ = RFC1533_END; - - m->m_len = sizeof(struct bootp_t) - + + m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); } diff --git a/BasiliskII/src/slirp/bootp.h b/BasiliskII/src/slirp/bootp.h index 54a86ca2..e48f53f3 100644 --- a/BasiliskII/src/slirp/bootp.h +++ b/BasiliskII/src/slirp/bootp.h @@ -90,10 +90,6 @@ #define BOOTP_VENDOR_LEN 64 #define DHCP_OPT_LEN 312 -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct bootp_t { struct ip ip; struct udphdr udp; @@ -112,10 +108,6 @@ struct bootp_t { uint8_t bp_sname[64]; uint8_t bp_file[128]; uint8_t bp_vend[DHCP_OPT_LEN]; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; void bootp_input(struct mbuf *m); diff --git a/BasiliskII/src/slirp/cksum.c b/BasiliskII/src/slirp/cksum.c index 66d3f230..b98373b5 100644 --- a/BasiliskII/src/slirp/cksum.c +++ b/BasiliskII/src/slirp/cksum.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -37,7 +41,7 @@ * * This routine is very heavily used in the network * code and should be modified for each CPU to be as fast as possible. - * + * * XXX Since we will never span more than 1 mbuf, we can optimise this */ @@ -59,13 +63,13 @@ int cksum(struct mbuf *m, int len) u_int16_t s[2]; u_int32_t l; } l_util; - + if (m->m_len == 0) goto cont; w = mtod(m, u_int16_t *); - + mlen = m->m_len; - + if (len < mlen) mlen = len; len -= mlen; @@ -103,7 +107,7 @@ int cksum(struct mbuf *m, int len) while ((mlen -= 2) >= 0) { sum += *w++; } - + if (byte_swapped) { REDUCE; sum <<= 8; @@ -113,11 +117,11 @@ int cksum(struct mbuf *m, int len) sum += s_util.s; mlen = 0; } else - + mlen = -1; } else if (mlen == -1) s_util.c[0] = *(u_int8_t *)w; - + cont: #ifdef DEBUG if (len) { diff --git a/BasiliskII/src/slirp/debug.c b/BasiliskII/src/slirp/debug.c index 916b9a8e..7c8581d6 100644 --- a/BasiliskII/src/slirp/debug.c +++ b/BasiliskII/src/slirp/debug.c @@ -1,8 +1,8 @@ /* * Copyright (c) 1995 Danny Gasparovski. * Portions copyright (c) 2000 Kelly Price. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -16,8 +16,11 @@ int dostats = 0; #endif int slirp_debug = 0; -/* Carry over one item from main.c so that the tty's restored. +extern char *strerror _P((int)); + +/* Carry over one item from main.c so that the tty's restored. * Only done when the tty being used is /dev/tty --RedWolf */ +#ifndef CONFIG_QEMU extern struct termios slirp_tty_settings; extern int slirp_tty_restore; @@ -30,7 +33,7 @@ debug_init(file, dbg) /* Close the old debugging file */ if (dfd) fclose(dfd); - + dfd = fopen(file,"w"); if (dfd != NULL) { #if 0 @@ -56,7 +59,7 @@ dump_packet(dat, n) { u_char *pptr = (u_char *)dat; int j,k; - + n /= 16; n++; DEBUG_MISC((dfd, "PACKET DUMPED: \n")); @@ -68,28 +71,30 @@ dump_packet(dat, n) } } #endif +#endif +#ifdef LOG_ENABLED #if 0 /* * Statistic routines - * + * * These will print statistics to the screen, the debug file (dfd), or * a buffer, depending on "type", so that the stats can be sent over * the link as well. */ -void +static void ttystats(ttyp) struct ttys *ttyp; { struct slirp_ifstats *is = &ttyp->ifstats; char buff[512]; - + lprint(" \r\n"); - - if (if_comp & IF_COMPRESS) + + if (IF_COMP & IF_COMPRESS) strcpy(buff, "on"); - else if (if_comp & IF_NOCOMPRESS) + else if (IF_COMP & IF_NOCOMPRESS) strcpy(buff, "off"); else strcpy(buff, "off (for now)"); @@ -117,20 +122,20 @@ ttystats(ttyp) lprint(" %6d bad input packets\r\n", is->in_mbad); } -void -allttystats() +static void +allttystats(void) { struct ttys *ttyp; - + for (ttyp = ttys; ttyp; ttyp = ttyp->next) ttystats(ttyp); } #endif -void -ipstats() +static void +ipstats(void) { - lprint(" \r\n"); + lprint(" \r\n"); lprint("IP stats:\r\n"); lprint(" %6d total packets received (%d were unaligned)\r\n", @@ -151,14 +156,14 @@ ipstats() lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); } -#if 0 -void -vjstats() +#ifndef CONFIG_QEMU +static void +vjstats(void) { lprint(" \r\n"); - + lprint("VJ compression stats:\r\n"); - + lprint(" %6d outbound packets (%d compressed)\r\n", comp_s.sls_packets, comp_s.sls_compressed); lprint(" %6d searches for connection stats (%d misses)\r\n", @@ -170,13 +175,13 @@ vjstats() } #endif -void -tcpstats() +static void +tcpstats(void) { lprint(" \r\n"); lprint("TCP stats:\r\n"); - + lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); lprint(" %6d data packets (%d bytes)\r\n", tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); @@ -189,8 +194,8 @@ tcpstats() lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); - - lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); + + lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); lprint(" %6d acks (for %d bytes)\r\n", tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); @@ -199,7 +204,7 @@ tcpstats() tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); lprint(" %6d completely duplicate packets (%d bytes)\r\n", tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); - + lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); lprint(" %6d out-of-order packets (%d bytes)\r\n", @@ -212,7 +217,7 @@ tcpstats() lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); lprint(" %6d discarded for bad header offset fields\r\n", tcpstat.tcps_rcvbadoff); - + lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); @@ -231,15 +236,15 @@ tcpstats() lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); - - + + /* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ /* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */ } -void -udpstats() +static void +udpstats(void) { lprint(" \r\n"); @@ -252,8 +257,8 @@ udpstats() lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); } -void -icmpstats() +static void +icmpstats(void) { lprint(" \r\n"); lprint("ICMP stats:\r\n"); @@ -265,23 +270,23 @@ icmpstats() lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); } -void -mbufstats() +static void +mbufstats(void) { struct mbuf *m; int i; - + lprint(" \r\n"); - + lprint("Mbuf stats:\r\n"); lprint(" %6d mbufs allocated (%d max)\r\n", mbuf_alloced, mbuf_max); - + i = 0; for (m = m_freelist.m_next; m != &m_freelist; m = m->m_next) i++; lprint(" %6d mbufs on free list\r\n", i); - + i = 0; for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) i++; @@ -289,59 +294,55 @@ mbufstats() lprint(" %6d mbufs queued as packets\r\n\r\n", if_queued); } -void -sockstats() +static void +sockstats(void) { - char addr[INET_ADDRSTRLEN]; char buff[256]; int n; struct socket *so; lprint(" \r\n"); - + lprint( "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); - + for (so = tcb.so_next; so != &tcb; so = so->so_next) { - + n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); while (n < 17) buff[n++] = ' '; buff[17] = 0; lprint("%s %3d %15s %5d ", buff, so->s, - inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), - ntohs(so->so_lport)); + inet_ntoa(so->so_laddr), ntohs(so->so_lport)); lprint("%15s %5d %5d %5d\r\n", - inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), - ntohs(so->so_fport), + inet_ntoa(so->so_faddr), ntohs(so->so_fport), so->so_rcv.sb_cc, so->so_snd.sb_cc); } - + for (so = udb.so_next; so != &udb; so = so->so_next) { - + n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); while (n < 17) buff[n++] = ' '; buff[17] = 0; lprint("%s %3d %15s %5d ", buff, so->s, - inet_ntop(AF_INET, &so->so_laddr, addr, sizeof(addr)), - ntohs(so->so_lport)); + inet_ntoa(so->so_laddr), ntohs(so->so_lport)); lprint("%15s %5d %5d %5d\r\n", - inet_ntop(AF_INET, &so->so_faddr, addr, sizeof(addr)), - ntohs(so->so_fport), + inet_ntoa(so->so_faddr), ntohs(so->so_fport), so->so_rcv.sb_cc, so->so_snd.sb_cc); } } +#endif -#if 0 +#ifndef CONFIG_QEMU void slirp_exit(exit_status) int exit_status; { struct ttys *ttyp; - + DEBUG_CALL("slirp_exit"); DEBUG_ARG("exit_status = %d", exit_status); @@ -350,7 +351,7 @@ slirp_exit(exit_status) if (!dfd) debug_init("slirp_stats", 0xf); lprint_arg = (char **)&dfd; - + ipstats(); tcpstats(); udpstats(); @@ -360,20 +361,35 @@ slirp_exit(exit_status) allttystats(); vjstats(); } - + for (ttyp = ttys; ttyp; ttyp = ttyp->next) tty_detached(ttyp, 1); - + if (slirp_forked) { /* Menendez time */ if (kill(getppid(), SIGQUIT) < 0) lprint("Couldn't kill parent process %ld!\n", (long) getppid()); } - + /* Restore the terminal if we gotta */ if(slirp_tty_restore) tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */ exit(exit_status); } #endif + +void +slirp_stats(void) +{ +#ifdef LOG_ENABLED + ipstats(); + tcpstats(); + udpstats(); + icmpstats(); + mbufstats(); + sockstats(); +#else + lprint("SLIRP statistics code not compiled.\n"); +#endif +} diff --git a/BasiliskII/src/slirp/debug.h b/BasiliskII/src/slirp/debug.h index c5d42195..8a523b2e 100644 --- a/BasiliskII/src/slirp/debug.h +++ b/BasiliskII/src/slirp/debug.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -36,15 +36,5 @@ extern int slirp_debug; #endif -void debug_init(char *, int); -//void ttystats(struct ttys *); -void allttystats(void); -void ipstats(void); -void vjstats(void); -void tcpstats(void); -void udpstats(void); -void icmpstats(void); -void mbufstats(void); -void sockstats(void); -void slirp_exit(int); +void debug_init _P((char *, int)); diff --git a/BasiliskII/src/slirp/icmp_var.h b/BasiliskII/src/slirp/icmp_var.h index 9af222fb..cd865b79 100644 --- a/BasiliskII/src/slirp/icmp_var.h +++ b/BasiliskII/src/slirp/icmp_var.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -60,6 +64,8 @@ struct icmpstat { { "stats", CTLTYPE_STRUCT }, \ } +#ifdef LOG_ENABLED extern struct icmpstat icmpstat; +#endif #endif diff --git a/BasiliskII/src/slirp/if.c b/BasiliskII/src/slirp/if.c index 9185dcf6..67a7b6ff 100644 --- a/BasiliskII/src/slirp/if.c +++ b/BasiliskII/src/slirp/if.c @@ -7,12 +7,7 @@ #include -size_t if_mtu, if_mru; -int if_comp; -int if_maxlinkhdr; -int if_queued = 0; /* Number of packets queued so far */ -int if_thresh = 10; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ +int if_queued = 0; /* Number of packets queued so far */ struct mbuf if_fastq; /* fast queue (for interactive data) */ struct mbuf if_batchq; /* queue for non-interactive data */ @@ -41,23 +36,6 @@ ifs_remque(ifm) void if_init() { -#if 0 - /* - * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, - * and 8 bytes for PPP, but need to have it on an 8byte boundary - */ -#ifdef USE_PPP - if_maxlinkhdr = 48; -#else - if_maxlinkhdr = 40; -#endif -#else - /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ - if_maxlinkhdr = 2 + 14 + 40; -#endif - if_mtu = 1500; - if_mru = 1500; - if_comp = IF_AUTOCOMP; if_fastq.ifq_next = if_fastq.ifq_prev = &if_fastq; if_batchq.ifq_next = if_batchq.ifq_prev = &if_batchq; // sl_compress_init(&comp_s); @@ -77,12 +55,12 @@ writen(fd, bptr, n) { int ret; int total; - + /* This should succeed most of the time */ ret = send(fd, bptr, n,0); if (ret == n || ret <= 0) return ret; - + /* Didn't write everything, go into the loop */ total = ret; while (n > total) { @@ -97,7 +75,7 @@ writen(fd, bptr, n) /* * if_input - read() the tty, do "top level" processing (ie: check for any escapes), * and pass onto (*ttyp->if_input) - * + * * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet. */ #define INBUFF_SIZE 2048 /* XXX */ @@ -107,17 +85,16 @@ if_input(ttyp) { u_char if_inbuff[INBUFF_SIZE]; int if_n; - + DEBUG_CALL("if_input"); DEBUG_ARG("ttyp = %lx", (long)ttyp); - + if_n = recv(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE,0); - + DEBUG_MISC((dfd, " read %d bytes\n", if_n)); - + if (if_n <= 0) { - int error = WSAGetLastError(); - if (if_n == 0 || (error != WSAEINTR && error != EAGAIN)) { + if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) { if (ttyp->up) link_up--; tty_detached(ttyp, 0); @@ -139,19 +116,19 @@ if_input(ttyp) } } ttyp->ones = ttyp->zeros = 0; - + (*ttyp->if_input)(ttyp, if_inbuff, if_n); } -#endif - +#endif + /* * if_output: Queue packet into an output queue. - * There are 2 output queue's, if_fastq and if_batchq. + * There are 2 output queue's, if_fastq and if_batchq. * Each output queue is a doubly linked list of double linked lists * of mbufs, each list belonging to one "session" (socket). This * way, we can output packets fairly by sending one packet from each * session, instead of all the packets from one session, then all packets - * from the next session, etc. Packets on the if_fastq get absolute + * from the next session, etc. Packets on the if_fastq get absolute * priority, but if one session hogs the link, it gets "downgraded" * to the batchq until it runs out of packets, then it'll return * to the fastq (eg. if the user does an ls -alR in a telnet session, @@ -164,11 +141,11 @@ if_output(so, ifm) { struct mbuf *ifq; int on_fastq = 1; - + DEBUG_CALL("if_output"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("ifm = %lx", (long)ifm); - + /* * First remove the mbuf from m_usedlist, * since we're gonna use m_next and m_prev ourselves @@ -178,9 +155,9 @@ if_output(so, ifm) remque(ifm); ifm->m_flags &= ~M_USEDLIST; } - + /* - * See if there's already a batchq list for this session. + * See if there's already a batchq list for this session. * This can include an interactive session, which should go on fastq, * but gets too greedy... hence it'll be downgraded from fastq to batchq. * We mustn't put this packet back on the fastq (or we'll send it out of order) @@ -194,7 +171,7 @@ if_output(so, ifm) goto diddit; } } - + /* No match, check which queue to put it on */ if (so && (so->so_iptos & IPTOS_LOWDELAY)) { ifq = if_fastq.ifq_prev; @@ -210,15 +187,15 @@ if_output(so, ifm) } } else ifq = if_batchq.ifq_prev; - + /* Create a new doubly linked list for this session */ ifm->ifq_so = so; ifs_init(ifm); insque(ifm, ifq); - + diddit: ++if_queued; - + if (so) { /* Update *_queued */ so->so_queued++; @@ -230,12 +207,12 @@ diddit: * have been sent over the link * (XXX These are arbitrary numbers, probably not optimal..) */ - if (on_fastq && ((so->so_nqueued >= 6) && + if (on_fastq && ((so->so_nqueued >= 6) && (so->so_nqueued - so->so_queued) >= 3)) { - + /* Remove from current queue... */ remque(ifm->ifs_next); - + /* ...And insert in the new. That'll teach ya! */ insque(ifm->ifs_next, &if_batchq); } @@ -268,16 +245,16 @@ void if_start(void) { struct mbuf *ifm, *ifqt; - + DEBUG_CALL("if_start"); - + if (if_queued == 0) return; /* Nothing to do */ - + again: - /* check if we can really output */ - if (!slirp_can_output()) - return; + /* check if we can really output */ + if (!slirp_can_output()) + return; /* * See which queue to get next packet from @@ -291,7 +268,7 @@ if_start(void) ifm = next_m; else ifm = if_batchq.ifq_next; - + /* Set which packet to send on next iteration */ next_m = ifm->ifq_next; } @@ -299,24 +276,24 @@ if_start(void) ifqt = ifm->ifq_prev; remque(ifm); --if_queued; - + /* If there are more packets for this session, re-queue them */ if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { insque(ifm->ifs_next, ifqt); ifs_remque(ifm); } - + /* Update so_queued */ if (ifm->ifq_so) { if (--ifm->ifq_so->so_queued == 0) /* If there's no more queued, reset nqueued */ ifm->ifq_so->so_nqueued = 0; } - - /* Encapsulate the packet for sending */ - if_encap((uint8_t*)ifm->m_data, ifm->m_len); - m_free(ifm); + /* Encapsulate the packet for sending */ + if_encap(ifm->m_data, ifm->m_len); + + m_free(ifm); if (if_queued) goto again; diff --git a/BasiliskII/src/slirp/if.h b/BasiliskII/src/slirp/if.h index a2564ab1..bed7152f 100644 --- a/BasiliskII/src/slirp/if.h +++ b/BasiliskII/src/slirp/if.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -13,15 +13,26 @@ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_NOCIDCOMP 0x08 /* CID compression */ -/* Needed for FreeBSD */ -#undef if_mtu -extern size_t if_mtu; -extern size_t if_mru; /* MTU and MRU */ -extern int if_comp; /* Flags for compression */ -extern int if_maxlinkhdr; +#define IF_MTU 1500 +#define IF_MRU 1500 +#define IF_COMP IF_AUTOCOMP /* Flags for compression */ + +#if 0 +/* + * Set if_maxlinkhdr to 48 because it's 40 bytes for TCP/IP, + * and 8 bytes for PPP, but need to have it on an 8byte boundary + */ +#ifdef USE_PPP +#define IF_MAXLINKHDR 48 +#else +#define IF_MAXLINKHDR 40 +#endif +#else + /* 2 for alignment, 14 for ethernet, 40 for TCP/IP */ +#define IF_MAXLINKHDR (2 + 14 + 40) +#endif + extern int if_queued; /* Number of packets queued so far */ -extern int if_thresh; /* Number of packets queued before we start sending - * (to prevent allocing too many mbufs) */ extern struct mbuf if_fastq; /* fast queue (for interactive data) */ extern struct mbuf if_batchq; /* queue for non-interactive data */ @@ -29,6 +40,7 @@ extern struct mbuf *next_m; #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) +#ifdef LOG_ENABLED /* Interface statistics */ struct slirp_ifstats { u_int out_pkts; /* Output packets */ @@ -39,12 +51,13 @@ struct slirp_ifstats { u_int in_bytes; /* Input bytes */ u_int in_errpkts; /* Input Error Packets */ u_int in_errbytes; /* Input Error Bytes */ - + u_int bytes_saved; /* Number of bytes that compression "saved" */ /* ie: number of bytes that didn't need to be sent over the link * because of compression */ - + u_int in_mbad; /* Bad incoming packets */ }; +#endif #endif diff --git a/BasiliskII/src/slirp/ip.h b/BasiliskII/src/slirp/ip.h index e0c7de96..a8cdb0d3 100644 --- a/BasiliskII/src/slirp/ip.h +++ b/BasiliskII/src/slirp/ip.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -72,16 +76,12 @@ typedef u_int32_t n_long; /* long as received from the net */ /* * Structure of an internet header, naked of options. */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct ip { #ifdef WORDS_BIGENDIAN - u_char ip_v:4, /* version */ + u_int ip_v:4, /* version */ ip_hl:4; /* header length */ #else - u_char ip_hl:4, /* header length */ + u_int ip_hl:4, /* header length */ ip_v:4; /* version */ #endif u_int8_t ip_tos; /* type of service */ @@ -95,11 +95,7 @@ struct ip { u_int8_t ip_p; /* protocol */ u_int16_t ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; #define IP_MAXPACKET 65535 /* maximum packet size */ @@ -143,19 +139,15 @@ struct ip { /* * Time stamp option structure. */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct ip_timestamp { u_int8_t ipt_code; /* IPOPT_TS */ u_int8_t ipt_len; /* size of structure (variable) */ u_int8_t ipt_ptr; /* index of current entry */ #ifdef WORDS_BIGENDIAN - u_char ipt_oflw:4, /* overflow counter */ + u_int ipt_oflw:4, /* overflow counter */ ipt_flg:4; /* flags, see below */ #else - u_char ipt_flg:4, /* flags, see below */ + u_int ipt_flg:4, /* flags, see below */ ipt_oflw:4; /* overflow counter */ #endif union ipt_timestamp { @@ -165,11 +157,7 @@ struct ip_timestamp { n_long ipt_time; } ipt_ta[1]; } ipt_timestamp; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; /* flag bits for ipt_flg */ #define IPOPT_TS_TSONLY 0 /* timestamps only */ @@ -216,10 +204,6 @@ typedef caddr32_t ipasfragp_32; /* * Overlay for ip header used by other protocols (tcp, udp). */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct ipovly { caddr32_t ih_next, ih_prev; /* for protocol sequence q's */ u_int8_t ih_x1; /* (unused) */ @@ -227,11 +211,7 @@ struct ipovly { u_int16_t ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ struct in_addr ih_dst; /* destination internet address */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; /* * Ip reassembly queue structure. Each fragment @@ -257,10 +237,10 @@ struct ipq { */ struct ipasfrag { #ifdef WORDS_BIGENDIAN - u_char ip_v:4, + u_int ip_v:4, ip_hl:4; #else - u_char ip_hl:4, + u_int ip_hl:4, ip_v:4; #endif /* BUG : u_int changed to u_int8_t. @@ -292,6 +272,7 @@ struct ipoption { int8_t ipopt_list[MAX_IPOPTLEN]; /* options proper */ }; +#ifdef LOG_ENABLED /* * Structure attached to inpcb.ip_moptions and * passed to ip_output when IP multicast options are in use. @@ -326,8 +307,9 @@ struct ipstat { }; extern struct ipstat ipstat; +#endif + extern struct ipq ipq; /* ip reass. queue */ extern u_int16_t ip_id; /* ip packet ctr, for ids */ -extern int ip_defttl; /* default IP ttl */ #endif diff --git a/BasiliskII/src/slirp/ip_icmp.c b/BasiliskII/src/slirp/ip_icmp.c index 55376a8b..d1da0a2f 100644 --- a/BasiliskII/src/slirp/ip_icmp.c +++ b/BasiliskII/src/slirp/ip_icmp.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,14 +37,16 @@ #include "slirp.h" #include "ip_icmp.h" +#ifdef LOG_ENABLED struct icmpstat icmpstat; +#endif /* The message sent when emulating PING */ -/* Be nice and tell them it's just a psuedo-ping packet */ -char icmp_ping_msg[] = "This is a psuedo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; +/* Be nice and tell them it's just a pseudo-ping packet */ +const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n"; /* list of actions for icmp_error() on RX of an icmp message */ -static int icmp_flush[19] = { +static const int icmp_flush[19] = { /* ECHO REPLY (0) */ 0, 1, 1, @@ -59,7 +65,7 @@ static int icmp_flush[19] = { /* INFO (15) */ 0, /* INFO REPLY (16) */ 0, /* ADDR MASK (17) */ 0, -/* ADDR MASK REPLY (18) */ 0 +/* ADDR MASK REPLY (18) */ 0 }; /* @@ -74,19 +80,19 @@ icmp_input(m, hlen) register struct ip *ip=mtod(m, struct ip *); int icmplen=ip->ip_len; /* int code; */ - + DEBUG_CALL("icmp_input"); DEBUG_ARG("m = %lx", (long )m); - DEBUG_ARG("m_len = %zu", m->m_len); + DEBUG_ARG("m_len = %d", m->m_len); + + STAT(icmpstat.icps_received++); - icmpstat.icps_received++; - /* * Locate icmp structure in mbuf, and check * that its not corrupted and of at least minimum length. */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ - icmpstat.icps_tooshort++; + STAT(icmpstat.icps_tooshort++); freeit: m_freem(m); goto end_error; @@ -96,12 +102,12 @@ icmp_input(m, hlen) m->m_data += hlen; icp = mtod(m, struct icmp *); if (cksum(m, icmplen)) { - icmpstat.icps_checksum++; + STAT(icmpstat.icps_checksum++); goto freeit; } m->m_len += hlen; m->m_data -= hlen; - + /* icmpstat.icps_inhist[icp->icmp_type]++; */ /* code = icp->icmp_code; */ @@ -117,7 +123,7 @@ icmp_input(m, hlen) struct sockaddr_in addr; if ((so = socreate()) == NULL) goto freeit; if(udp_attach(so) == -1) { - DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", + DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", errno,strerror(errno))); sofree(so); m_free(m); @@ -131,7 +137,7 @@ icmp_input(m, hlen) so->so_iptos = ip->ip_tos; so->so_type = IPPROTO_ICMP; so->so_state = SS_ISFCONNECTED; - + /* Send the packet */ addr.sin_family = AF_INET; if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { @@ -153,7 +159,7 @@ icmp_input(m, hlen) (struct sockaddr *)&addr, sizeof(addr)) == -1) { DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); udp_detach(so); } } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ @@ -166,12 +172,12 @@ icmp_input(m, hlen) case ICMP_TSTAMP: case ICMP_MASKREQ: case ICMP_REDIRECT: - icmpstat.icps_notsupp++; + STAT(icmpstat.icps_notsupp++); m_freem(m); break; - + default: - icmpstat.icps_badtype++; + STAT(icmpstat.icps_badtype++); m_freem(m); } /* swith */ @@ -195,18 +201,18 @@ end_error: * mbuf *msrc is used as a template, but is NOT m_free()'d. * It is reported as the bad ip packet. The header should * be fully correct and in host byte order. - * ICMP fragmentation is illegal. All machines must accept 576 bytes in one + * ICMP fragmentation is illegal. All machines must accept 576 bytes in one * packet. The maximum payload is 576-20(ip hdr)-8(icmp hdr)=548 */ #define ICMP_MAXDATALEN (IP_MSS-28) void -icmp_error( - struct mbuf *msrc, - u_char type, - u_char code, - int minsize, - char *message) +icmp_error(msrc, type, code, minsize, message) + struct mbuf *msrc; + u_char type; + u_char code; + int minsize; + char *message; { unsigned hlen, shlen, s_ip_len; register struct ip *ip; @@ -215,17 +221,17 @@ icmp_error( DEBUG_CALL("icmp_error"); DEBUG_ARG("msrc = %lx", (long )msrc); - DEBUG_ARG("msrc_len = %zu", msrc->m_len); + DEBUG_ARG("msrc_len = %d", msrc->m_len); if(type!=ICMP_UNREACH && type!=ICMP_TIMXCEED) goto end_error; /* check msrc */ if(!msrc) goto end_error; ip = mtod(msrc, struct ip *); -#if DEBUG - { char bufa[INET_ADDRSTRLEN], bufb[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &ip->ip_src, bufa, sizeof(bufa)); - inet_ntop(AF_INET, &ip->ip_dst, bufb, sizeof(bufb)); +#if DEBUG + { char bufa[20], bufb[20]; + strcpy(bufa, inet_ntoa(ip->ip_src)); + strcpy(bufb, inet_ntoa(ip->ip_dst)); DEBUG_MISC((dfd, " %.16s to %.16s\n", bufa, bufb)); } #endif @@ -244,7 +250,7 @@ icmp_error( /* make a copy */ if(!(m=m_get())) goto end_error; /* get mbuf */ - { u_int new_m_size; + { int new_m_size; new_m_size=sizeof(struct ip )+ICMP_MINLEN+msrc->m_len+ICMP_MAXDATALEN; if(new_m_size>m->m_size) m_inc(m, new_m_size); } @@ -254,9 +260,9 @@ icmp_error( /* make the header of the reply packet */ ip = mtod(m, struct ip *); hlen= sizeof(struct ip ); /* no options in reply */ - + /* fill in icmp */ - m->m_data += hlen; + m->m_data += hlen; m->m_len -= hlen; icp = mtod(m, struct icmp *); @@ -265,7 +271,7 @@ icmp_error( else if(s_ip_len>ICMP_MAXDATALEN) /* maximum size */ s_ip_len=ICMP_MAXDATALEN; - m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */ + m->m_len=ICMP_MINLEN+s_ip_len; /* 8 bytes ICMP header */ /* min. size = 8+sizeof(struct ip)+8 */ @@ -299,8 +305,8 @@ icmp_error( /* fill in ip */ ip->ip_hl = hlen >> 2; - ip->ip_len = (u_int16_t)m->m_len; - + ip->ip_len = m->m_len; + ip->ip_tos=((ip->ip_tos & 0x1E) | 0xC0); /* high priority for errors */ ip->ip_ttl = MAXTTL; @@ -309,8 +315,8 @@ icmp_error( ip->ip_src = alias_addr; (void ) ip_output((struct socket *)NULL, m); - - icmpstat.icps_reflect++; + + STAT(icmpstat.icps_reflect++); end_error: return; @@ -367,5 +373,5 @@ icmp_reflect(m) (void ) ip_output((struct socket *)NULL, m); - icmpstat.icps_reflect++; + STAT(icmpstat.icps_reflect++); } diff --git a/BasiliskII/src/slirp/ip_icmp.h b/BasiliskII/src/slirp/ip_icmp.h index 683dc87f..8c9b5a1b 100644 --- a/BasiliskII/src/slirp/ip_icmp.h +++ b/BasiliskII/src/slirp/ip_icmp.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -43,10 +47,6 @@ typedef u_int32_t n_time; /* * Structure of an icmp header. */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct icmp { u_char icmp_type; /* type of message, see below */ u_char icmp_code; /* type sub code */ @@ -92,11 +92,7 @@ struct icmp { #define icmp_ip icmp_dun.id_ip.idi_ip #define icmp_mask icmp_dun.id_mask #define icmp_data icmp_dun.id_data -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; /* * Lower bounds on packet lengths for various types. @@ -161,8 +157,8 @@ struct icmp { (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) -void icmp_input(struct mbuf *, int); -void icmp_error(struct mbuf *, u_char, u_char, int, char *); -void icmp_reflect(struct mbuf *); +void icmp_input _P((struct mbuf *, int)); +void icmp_error _P((struct mbuf *, u_char, u_char, int, char *)); +void icmp_reflect _P((struct mbuf *)); #endif diff --git a/BasiliskII/src/slirp/ip_input.c b/BasiliskII/src/slirp/ip_input.c index cac8493b..b0468402 100644 --- a/BasiliskII/src/slirp/ip_input.c +++ b/BasiliskII/src/slirp/ip_input.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,7 +37,7 @@ /* * Changes and additions relating to SLiRP are * Copyright (c) 1995 Danny Gasparovski. - * + * * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -41,10 +45,19 @@ #include #include "ip_icmp.h" -int ip_defttl; +#ifdef LOG_ENABLED struct ipstat ipstat; +#endif + struct ipq ipq; +static struct ip *ip_reass(register struct ipasfrag *ip, + register struct ipq *fp); +static void ip_freef(struct ipq *fp); +static void ip_enq(register struct ipasfrag *p, + register struct ipasfrag *prev); +static void ip_deq(register struct ipasfrag *p); + /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. @@ -56,7 +69,6 @@ ip_init() ip_id = tt.tv_sec & 0xffff; udp_init(); tcp_init(); - ip_defttl = IPDEFTTL; } /* @@ -68,38 +80,38 @@ ip_input(m) struct mbuf *m; { register struct ip *ip; - u_int hlen; - + int hlen; + DEBUG_CALL("ip_input"); DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("m_len = %zu", m->m_len); + DEBUG_ARG("m_len = %d", m->m_len); + + STAT(ipstat.ips_total++); - ipstat.ips_total++; - if (m->m_len < sizeof (struct ip)) { - ipstat.ips_toosmall++; + STAT(ipstat.ips_toosmall++); return; } - + ip = mtod(m, struct ip *); - + if (ip->ip_v != IPVERSION) { - ipstat.ips_badvers++; + STAT(ipstat.ips_badvers++); goto bad; } hlen = ip->ip_hl << 2; if (hlenm->m_len) {/* min header length */ - ipstat.ips_badhlen++; /* or packet too short */ + STAT(ipstat.ips_badhlen++); /* or packet too short */ goto bad; } /* keep ip header intact for ICMP reply - * ip->ip_sum = cksum(m, hlen); - * if (ip->ip_sum) { + * ip->ip_sum = cksum(m, hlen); + * if (ip->ip_sum) { */ if(cksum(m,hlen)) { - ipstat.ips_badsum++; + STAT(ipstat.ips_badsum++); goto bad; } @@ -108,7 +120,7 @@ ip_input(m) */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { - ipstat.ips_badlen++; + STAT(ipstat.ips_badlen++); goto bad; } NTOHS(ip->ip_id); @@ -121,7 +133,7 @@ ip_input(m) * Drop packet if shorter than we expect. */ if (m->m_len < ip->ip_len) { - ipstat.ips_tooshort++; + STAT(ipstat.ips_tooshort++); goto bad; } /* Should drop packet if mbuf too long? hmmm... */ @@ -150,7 +162,7 @@ ip_input(m) * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) - * + * * XXX This should fail, don't fragment yet */ if (ip->ip_off &~ IP_DF) { @@ -177,7 +189,7 @@ ip_input(m) ip->ip_len -= hlen; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff |= 1; - else + else ((struct ipasfrag *)ip)->ipf_mff &= ~1; ip->ip_off <<= 3; @@ -188,11 +200,11 @@ ip_input(m) * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { - ipstat.ips_fragments++; + STAT(ipstat.ips_fragments++); ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) return; - ipstat.ips_reassembled++; + STAT(ipstat.ips_reassembled++); m = dtom(ip); } else if (fp) @@ -204,7 +216,7 @@ ip_input(m) /* * Switch out to protocol's input routine. */ - ipstat.ips_delivered++; + STAT(ipstat.ips_delivered++); switch (ip->ip_p) { case IPPROTO_TCP: tcp_input(m, hlen, (struct socket *)NULL); @@ -216,7 +228,7 @@ ip_input(m) icmp_input(m, hlen); break; default: - ipstat.ips_noproto++; + STAT(ipstat.ips_noproto++); m_free(m); } return; @@ -231,16 +243,14 @@ bad: * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * -ip_reass(ip, fp) - register struct ipasfrag *ip; - register struct ipq *fp; +static struct ip * +ip_reass(register struct ipasfrag *ip, register struct ipq *fp) { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; int hlen = ip->ip_hl << 2; int i, next; - + DEBUG_CALL("ip_reass"); DEBUG_ARG("ip = %lx", (long)ip); DEBUG_ARG("fp = %lx", (long)fp); @@ -271,7 +281,7 @@ ip_reass(ip, fp) q = (struct ipasfrag *)fp; goto insert; } - + /* * Find a segment which begins after this one does. */ @@ -365,7 +375,7 @@ insert: ip = (struct ipasfrag *)(m->m_ext + delta); } - /* DEBUG_ARG("ip = %lx", (long)ip); + /* DEBUG_ARG("ip = %lx", (long)ip); * ip=(struct ipasfrag *)m->m_data; */ ip->ip_len = next; @@ -381,7 +391,7 @@ insert: return ((struct ip *)ip); dropfrag: - ipstat.ips_fragdropped++; + STAT(ipstat.ips_fragdropped++); m_freem(m); return (0); } @@ -390,9 +400,8 @@ dropfrag: * Free a fragment reassembly header and all * associated datagrams. */ -void -ip_freef(fp) - struct ipq *fp; +static void +ip_freef(struct ipq *fp) { register struct ipasfrag *q, *p; @@ -410,9 +419,8 @@ ip_freef(fp) * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ -void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; +static void +ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); @@ -425,9 +433,8 @@ ip_enq(p, prev) /* * To ip_enq as remque is to insque. */ -void -ip_deq(p) - register struct ipasfrag *p; +static void +ip_deq(register struct ipasfrag *p) { ((struct ipasfrag *)(p->ipf_prev))->ipf_next = p->ipf_next; ((struct ipasfrag *)(p->ipf_next))->ipf_prev = p->ipf_prev; @@ -442,9 +449,9 @@ void ip_slowtimo() { register struct ipq *fp; - + DEBUG_CALL("ip_slowtimo"); - + fp = (struct ipq *) ipq.next; if (fp == 0) return; @@ -453,7 +460,7 @@ ip_slowtimo() --fp->ipq_ttl; fp = (struct ipq *) fp->next; if (((struct ipq *)(fp->prev))->ipq_ttl == 0) { - ipstat.ips_fragtimeout++; + STAT(ipstat.ips_fragtimeout++); ip_freef((struct ipq *) fp->prev); } } @@ -660,7 +667,7 @@ bad: /* Not yet */ icmp_error(m, type, code, 0, 0); - ipstat.ips_badoptions++; + STAT(ipstat.ips_badoptions++); return (1); } @@ -688,6 +695,6 @@ ip_stripoptions(m, mopt) i = m->m_len - (sizeof (struct ip) + olen); memcpy(opts, opts + olen, (unsigned)i); m->m_len -= olen; - + ip->ip_hl = sizeof(struct ip) >> 2; } diff --git a/BasiliskII/src/slirp/ip_output.c b/BasiliskII/src/slirp/ip_output.c index fb9a9420..a8a6067b 100644 --- a/BasiliskII/src/slirp/ip_output.c +++ b/BasiliskII/src/slirp/ip_output.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -42,6 +46,10 @@ u_int16_t ip_id; +/* Number of packets queued before we start sending + * (to prevent allocing too many mbufs) */ +#define IF_THRESH 10 + /* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). @@ -55,14 +63,13 @@ ip_output(so, m0) { register struct ip *ip; register struct mbuf *m = m0; - register u_int hlen = sizeof(struct ip); - u_int len, off; - int error = 0; + register int hlen = sizeof(struct ip ); + int len, off, error = 0; DEBUG_CALL("ip_output"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m0 = %lx", (long)m0); - + /* We do no options */ /* if (opt) { * m = ip_insertoptions(m, opt, &len); @@ -77,23 +84,23 @@ ip_output(so, m0) ip->ip_off &= IP_DF; ip->ip_id = htons(ip_id++); ip->ip_hl = hlen >> 2; - ipstat.ips_localout++; + STAT(ipstat.ips_localout++); /* * Verify that we have any chance at all of being able to queue * the packet or packet fragments */ /* XXX Hmmm... */ -/* if (if_queued > if_thresh && towrite <= 0) { +/* if (if_queued > IF_THRESH && towrite <= 0) { * error = ENOBUFS; * goto bad; * } */ - + /* * If small enough for interface, can just send directly. */ - if ((u_int16_t)ip->ip_len <= if_mtu) { + if ((u_int16_t)ip->ip_len <= IF_MTU) { ip->ip_len = htons((u_int16_t)ip->ip_len); ip->ip_off = htons((u_int16_t)ip->ip_off); ip->ip_sum = 0; @@ -109,11 +116,11 @@ ip_output(so, m0) */ if (ip->ip_off & IP_DF) { error = -1; - ipstat.ips_cantfrag++; + STAT(ipstat.ips_cantfrag++); goto bad; } - - len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ + + len = (IF_MTU - hlen) &~ 7; /* ip databytes per packet */ if (len < 8) { error = -1; goto bad; @@ -129,18 +136,18 @@ ip_output(so, m0) */ m0 = m; mhlen = sizeof (struct ip); - for (off = hlen + len; off < ip->ip_len; off += len) { + for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { register struct ip *mhip; m = m_get(); if (m == 0) { error = -1; - ipstat.ips_odropped++; + STAT(ipstat.ips_odropped++); goto sendorfree; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; mhip = mtod(m, struct ip *); *mhip = *ip; - + /* No options */ /* if (hlen > sizeof (struct ip)) { * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); @@ -153,28 +160,28 @@ ip_output(so, m0) mhip->ip_off |= IP_MF; if (off + len >= (u_int16_t)ip->ip_len) len = (u_int16_t)ip->ip_len - off; - else + else mhip->ip_off |= IP_MF; mhip->ip_len = htons((u_int16_t)(len + mhlen)); - + if (m_copy(m, m0, off, len) < 0) { error = -1; goto sendorfree; } - + mhip->ip_off = htons((u_int16_t)mhip->ip_off); mhip->ip_sum = 0; mhip->ip_sum = cksum(m, mhlen); *mnext = m; mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; + STAT(ipstat.ips_ofragments++); } /* * Update first fragment by trimming what's been copied out * and updating header, then send each fragment (in order). */ m = m0; - m_adj(m, hlen + firstlen - ip->ip_len); + m_adj(m, hlen + firstlen - (u_int16_t)ip->ip_len); ip->ip_len = htons((u_int16_t)m->m_len); ip->ip_off = htons((u_int16_t)(ip->ip_off | IP_MF)); ip->ip_sum = 0; @@ -190,7 +197,7 @@ sendorfree: } if (error == 0) - ipstat.ips_fragmented++; + STAT(ipstat.ips_fragmented++); } done: diff --git a/BasiliskII/src/slirp/libslirp.h b/BasiliskII/src/slirp/libslirp.h index 8a1aa31e..7e4cfa98 100644 --- a/BasiliskII/src/slirp/libslirp.h +++ b/BasiliskII/src/slirp/libslirp.h @@ -1,39 +1,33 @@ #ifndef _LIBSLIRP_H #define _LIBSLIRP_H -#ifdef _WIN32 -#include -int inet_aton(const char *cp, struct in_addr *ia); -#else -#include -#include -#endif - #ifdef __cplusplus extern "C" { #endif -int slirp_init(void); +void slirp_init(void); -int slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds); +void slirp_select_fill(int *pnfds, + fd_set *readfds, fd_set *writefds, fd_set *xfds); void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds); -void slirp_input(const uint8 *pkt, int pkt_len); +void slirp_input(const uint8_t *pkt, int pkt_len); /* you must provide the following functions: */ int slirp_can_output(void); -void slirp_output(const uint8 *pkt, int pkt_len); +void slirp_output(const uint8_t *pkt, int pkt_len); -int slirp_redir(int is_udp, int host_port, +int slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, int guest_port); -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int guest_port); extern const char *tftp_prefix; extern char slirp_hostname[33]; +void slirp_stats(void); + #ifdef __cplusplus } #endif diff --git a/BasiliskII/src/slirp/main.h b/BasiliskII/src/slirp/main.h index 181b6ae8..c01addac 100644 --- a/BasiliskII/src/slirp/main.h +++ b/BasiliskII/src/slirp/main.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -42,7 +42,6 @@ extern char *username; extern char *socket_path; extern int towrite_max; extern int ppp_exit; -extern int so_options; extern int tcp_keepintvl; extern uint8_t client_ethaddr[6]; diff --git a/BasiliskII/src/slirp/mbuf.c b/BasiliskII/src/slirp/mbuf.c index 5a16fab8..5d125542 100644 --- a/BasiliskII/src/slirp/mbuf.c +++ b/BasiliskII/src/slirp/mbuf.c @@ -15,54 +15,49 @@ * the flags */ -#include #include struct mbuf *mbutl; char *mclrefcnt; int mbuf_alloced = 0; struct mbuf m_freelist, m_usedlist; -int mbuf_thresh = 30; +#define MBUF_THRESH 30 int mbuf_max = 0; -size_t msize; -void m_init() +/* + * Find a nice value for msize + * XXX if_maxlinkhdr already in mtu + */ +#define MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6) + +void +m_init() { m_freelist.m_next = m_freelist.m_prev = &m_freelist; m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; - msize_init(); -} - -void msize_init() -{ - /* - * Find a nice value for msize - * XXX if_maxlinkhdr already in mtu - */ - msize = (if_mtu>if_mru?if_mtu:if_mru) + - if_maxlinkhdr + sizeof(struct m_hdr ) + 6; } /* * Get an mbuf from the free list, if there are none * malloc one - * + * * Because fragmentation can occur if we alloc new mbufs and * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE, * which tells m_free to actually free() it */ -struct mbuf *m_get() +struct mbuf * +m_get() { register struct mbuf *m; int flags = 0; - + DEBUG_CALL("m_get"); - + if (m_freelist.m_next == &m_freelist) { - m = (struct mbuf *)malloc(msize); + m = (struct mbuf *)malloc(MSIZE); if (m == NULL) goto end_error; mbuf_alloced++; - if (mbuf_alloced > mbuf_thresh) + if (mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; if (mbuf_alloced > mbuf_max) mbuf_max = mbuf_alloced; @@ -70,13 +65,13 @@ struct mbuf *m_get() m = m_freelist.m_next; remque(m); } - + /* Insert it in the used list */ insque(m,&m_usedlist); m->m_flags = (flags | M_USEDLIST); - + /* Initialise it */ - m->m_size = msize - sizeof(struct m_hdr); + m->m_size = MSIZE - sizeof(struct m_hdr); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = 0; @@ -86,17 +81,19 @@ end_error: return m; } -void m_free(struct mbuf *m) +void +m_free(m) + struct mbuf *m; { - + DEBUG_CALL("m_free"); DEBUG_ARG("m = %lx", (long )m); - + if(m) { /* Remove from m_usedlist */ if (m->m_flags & M_USEDLIST) remque(m); - + /* If it's M_EXT, free() it */ if (m->m_flags & M_EXT) free(m->m_ext); @@ -119,14 +116,16 @@ void m_free(struct mbuf *m) * the other.. if result is too big for one mbuf, malloc() * an M_EXT data segment */ -void m_cat(register struct mbuf *m, register struct mbuf *n) +void +m_cat(m, n) + register struct mbuf *m, *n; { /* * If there's no room, realloc */ if (M_FREEROOM(m) < n->m_len) m_inc(m,m->m_size+MINCSIZE); - + memcpy(m->m_data+m->m_len, n->m_data, n->m_len); m->m_len += n->m_len; @@ -135,20 +134,23 @@ void m_cat(register struct mbuf *m, register struct mbuf *n) /* make m size bytes large */ -void m_inc(struct mbuf *m, u_int size) +void +m_inc(m, size) + struct mbuf *m; + int size; { - int datasize; + int datasize; /* some compiles throw up on gotos. This one we can fake. */ if(m->m_size>size) return; if (m->m_flags & M_EXT) { - datasize = m->m_data - m->m_ext; + datasize = m->m_data - m->m_ext; m->m_ext = (char *)realloc(m->m_ext,size); /* if (m->m_ext == NULL) * return (struct mbuf *)NULL; - */ - m->m_data = m->m_ext + datasize; + */ + m->m_data = m->m_ext + datasize; } else { char *dat; datasize = m->m_data - m->m_dat; @@ -157,19 +159,22 @@ void m_inc(struct mbuf *m, u_int size) * return (struct mbuf *)NULL; */ memcpy(dat, m->m_dat, m->m_size); - + m->m_ext = dat; m->m_data = m->m_ext + datasize; m->m_flags |= M_EXT; } - + m->m_size = size; } -void m_adj(struct mbuf *m, int len) +void +m_adj(m, len) + struct mbuf *m; + int len; { if (m == NULL) return; @@ -189,7 +194,9 @@ void m_adj(struct mbuf *m, int len) * Copy len bytes from m, starting off bytes into n */ int -m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len) +m_copy(n, m, off, len) + struct mbuf *n, *m; + int off, len; { if (len > M_FREEROOM(n)) return -1; @@ -205,10 +212,12 @@ m_copy(struct mbuf *n, struct mbuf *m, u_int off, u_int len) * XXX This is a kludge, I should eliminate the need for it * Fortunately, it's not used often */ -struct mbuf *dtom(void *dat) +struct mbuf * +dtom(dat) + void *dat; { struct mbuf *m; - + DEBUG_CALL("dtom"); DEBUG_ARG("dat = %lx", (long )dat); @@ -222,9 +231,9 @@ struct mbuf *dtom(void *dat) return m; } } - + DEBUG_ERROR((dfd, "dtom failed")); - + return (struct mbuf *)0; } diff --git a/BasiliskII/src/slirp/mbuf.h b/BasiliskII/src/slirp/mbuf.h index 11b252bb..f9f21325 100644 --- a/BasiliskII/src/slirp/mbuf.h +++ b/BasiliskII/src/slirp/mbuf.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -63,14 +67,14 @@ struct m_hdr { struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ int mh_flags; /* Misc flags */ - size_t mh_size; /* Size of data */ + int mh_size; /* Size of data */ struct socket *mh_so; - + caddr_t mh_data; /* Location of data */ - size_t mh_len; /* Amount of data in this mbuf */ + int mh_len; /* Amount of data in this mbuf */ }; -/* +/* * How much room is in the mbuf, from m_data to the end of the mbuf */ #define M_ROOM(m) ((m->m_flags & M_EXT)? \ @@ -122,7 +126,7 @@ struct mbuf { struct mbstat { int mbs_alloced; /* Number of mbufs allocated */ - + }; extern struct mbstat mbstat; @@ -130,14 +134,13 @@ extern int mbuf_alloced; extern struct mbuf m_freelist, m_usedlist; extern int mbuf_max; -void m_init(void); -void msize_init(void); -struct mbuf * m_get(void); -void m_free(struct mbuf *); -void m_cat(register struct mbuf *, register struct mbuf *); -void m_inc(struct mbuf *, u_int); -void m_adj(struct mbuf *, int); -int m_copy(struct mbuf *, struct mbuf *, u_int, u_int); -struct mbuf * dtom(void *); +void m_init _P((void)); +struct mbuf * m_get _P((void)); +void m_free _P((struct mbuf *)); +void m_cat _P((register struct mbuf *, register struct mbuf *)); +void m_inc _P((struct mbuf *, int)); +void m_adj _P((struct mbuf *, int)); +int m_copy _P((struct mbuf *, struct mbuf *, int, int)); +struct mbuf * dtom _P((void *)); #endif diff --git a/BasiliskII/src/slirp/misc.c b/BasiliskII/src/slirp/misc.c index b80caf66..14808fe2 100644 --- a/BasiliskII/src/slirp/misc.c +++ b/BasiliskII/src/slirp/misc.c @@ -1,23 +1,24 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * + * * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ #define WANT_SYS_IOCTL_H -#include #include -u_int curtime, time_fasttimo, last_slowtimo, detach_time; -u_int detach_wait = 600000; /* 10 minutes */ +u_int curtime, time_fasttimo, last_slowtimo; #if 0 int x_port = -1; int x_display = 0; int x_screen = 0; -int show_x(char *buff, struct socket *inso) +int +show_x(buff, inso) + char *buff; + struct socket *inso; { if (x_port < 0) { lprint("X Redir: X not being redirected.\r\n"); @@ -29,7 +30,7 @@ int show_x(char *buff, struct socket *inso) if (x_display) lprint("X Redir: Redirecting to display %d\r\n", x_display); } - + return CFG_OK; } @@ -37,10 +38,15 @@ int show_x(char *buff, struct socket *inso) /* * XXX Allow more than one X redirection? */ -void redir_x(u_int32_t inaddr, int start_port, int display, int screen) +void +redir_x(inaddr, start_port, display, screen) + u_int32_t inaddr; + int start_port; + int display; + int screen; { int i; - + if (x_port >= 0) { lprint("X Redir: X already being redirected.\r\n"); show_x(0, 0); @@ -61,33 +67,34 @@ void redir_x(u_int32_t inaddr, int start_port, int display, int screen) #endif #ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia) +int +inet_aton(cp, ia) + const char *cp; + struct in_addr *ia; { - return inet_pton(AF_INET, cp, &ia->s_addr); + u_int32_t addr = inet_addr(cp); + if (addr == 0xffffffff) + return 0; + ia->s_addr = addr; + return 1; } #endif /* * Get our IP address and put it in our_addr */ -void getouraddr() +void +getouraddr() { char buff[256]; + struct hostent *he = NULL; - if (gethostname(buff, sizeof(buff)) == 0) - { - struct addrinfo hints = { 0 }; - hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = AF_INET; - struct addrinfo* ai; - if (getaddrinfo(buff, NULL, &hints, &ai) == 0) - { - our_addr = *(struct in_addr *)ai->ai_addr->sa_data; - freeaddrinfo(ai); - } - } - if (our_addr.s_addr == 0) - our_addr.s_addr = loopback_addr.s_addr; + if (gethostname(buff,256) == 0) + he = gethostbyname(buff); + if (he) + our_addr = *(struct in_addr *)he->h_addr; + if (our_addr.s_addr == 0) + our_addr.s_addr = loopback_addr.s_addr; } #if SIZEOF_CHAR_P == 8 @@ -97,7 +104,10 @@ struct quehead_32 { u_int32_t qh_rlink; }; -inline void insque_32(void *a, void *b) +inline void +insque_32(a, b) + void *a; + void *b; { register struct quehead_32 *element = (struct quehead_32 *) a; register struct quehead_32 *head = (struct quehead_32 *) b; @@ -108,7 +118,9 @@ inline void insque_32(void *a, void *b) = (u_int32_t)element; } -inline void remque_32(void *a) +inline void +remque_32(a) + void *a; { register struct quehead_32 *element = (struct quehead_32 *) a; ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -123,7 +135,9 @@ struct quehead { struct quehead *qh_rlink; }; -void insque(void *a, void *b) +inline void +insque(a, b) + void *a, *b; { register struct quehead *element = (struct quehead *) a; register struct quehead *head = (struct quehead *) b; @@ -134,7 +148,9 @@ void insque(void *a, void *b) = (struct quehead *)element; } -void remque(void *a) +inline void +remque(a) + void *a; { register struct quehead *element = (struct quehead *) a; ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; @@ -146,16 +162,22 @@ void remque(void *a) /* #endif */ -int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) +int +add_exec(ex_ptr, do_pty, exec, addr, port) + struct ex_list **ex_ptr; + int do_pty; + char *exec; + int addr; + int port; { struct ex_list *tmp_ptr; - + /* First, check if the port is "bound" */ for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) return -1; } - + tmp_ptr = *ex_ptr; *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); (*ex_ptr)->ex_fport = port; @@ -175,7 +197,9 @@ int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port extern int sys_nerr; extern char *sys_errlist[]; -char *strerror(int error) +char * +strerror(error) + int error; { if (error < sys_nerr) return sys_errlist[error]; @@ -188,7 +212,8 @@ char *strerror(int error) #ifdef _WIN32 -int fork_exec(struct socket *so, char *ex, int do_pty) +int +fork_exec(struct socket *so, const char *ex, int do_pty) { /* not implemented */ return 0; @@ -196,13 +221,16 @@ int fork_exec(struct socket *so, char *ex, int do_pty) #else -int slirp_openpty(int *amaster, int *aslave) +#ifndef CONFIG_QEMU +int +slirp_openpty(amaster, aslave) + int *amaster, *aslave; { register int master, slave; #ifdef HAVE_GRANTPT char *ptr; - + if ((master = open("/dev/ptmx", O_RDWR)) < 0 || grantpt(master) < 0 || unlockpt(master) < 0 || @@ -210,7 +238,7 @@ int slirp_openpty(int *amaster, int *aslave) close(master); return -1; } - + if ((slave = open(ptr, O_RDWR)) < 0 || ioctl(slave, I_PUSH, "ptem") < 0 || ioctl(slave, I_PUSH, "ldterm") < 0 || @@ -219,16 +247,16 @@ int slirp_openpty(int *amaster, int *aslave) close(slave); return -1; } - + *amaster = master; *aslave = slave; return 0; - + #else - + static char line[] = "/dev/ptyXX"; register const char *cp1, *cp2; - + for (cp1 = "pqrsPQRS"; *cp1; cp1++) { line[8] = *cp1; for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { @@ -258,6 +286,7 @@ int slirp_openpty(int *amaster, int *aslave) return (-1); #endif } +#endif /* * XXX This is ugly @@ -265,53 +294,57 @@ int slirp_openpty(int *amaster, int *aslave) * process, which connects to this socket, after which we * exec the wanted program. If something (strange) happens, * the accept() call could block us forever. - * + * * do_pty = 0 Fork/exec inetd style * do_pty = 1 Fork/exec using slirp.telnetd * do_ptr = 2 Fork/exec using pty */ -int fork_exec(struct socket *so, char *ex, int do_pty) +int +fork_exec(struct socket *so, const char *ex, int do_pty) { int s; struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); + int addrlen = sizeof(addr); int opt; - int master; + int master = -1; char *argv[256]; #if 0 char buff[256]; #endif /* don't want to clobber the original */ char *bptr; - char *curarg; + const char *curarg; int c, i, ret; - + DEBUG_CALL("fork_exec"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("ex = %lx", (long)ex); DEBUG_ARG("do_pty = %lx", (long)do_pty); - + if (do_pty == 2) { +#if 0 if (slirp_openpty(&master, &s) == -1) { lprint("Error: openpty failed: %s\n", strerror(errno)); return 0; } +#else + return 0; +#endif } else { - memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; - + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 || listen(s, 1) < 0) { lprint("Error: inet socket: %s\n", strerror(errno)); closesocket(s); - + return 0; } } - + switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); @@ -319,7 +352,7 @@ int fork_exec(struct socket *so, char *ex, int do_pty) if (do_pty == 2) close(master); return 0; - + case 0: /* Set the DISPLAY */ if (do_pty == 2) { @@ -341,7 +374,7 @@ int fork_exec(struct socket *so, char *ex, int do_pty) ret = connect(s, (struct sockaddr *)&addr, addrlen); } while (ret < 0 && errno == EINTR); } - + #if 0 if (x_port >= 0) { #ifdef HAVE_SETENV @@ -352,13 +385,13 @@ int fork_exec(struct socket *so, char *ex, int do_pty) putenv(buff); #endif } -#endif +#endif dup2(s, 0); dup2(s, 1); dup2(s, 2); - for (s = 3; s <= 255; s++) + for (s = getdtablesize() - 1; s >= 3; s--) close(s); - + i = 0; bptr = strdup(ex); /* No need to free() this */ if (do_pty == 1) { @@ -376,21 +409,21 @@ int fork_exec(struct socket *so, char *ex, int do_pty) *bptr++ = (char)0; argv[i++] = strdup(curarg); } while (c); - + argv[i] = 0; execvp(argv[0], argv); - + /* Ooops, failed, let's tell the user why */ { char buff[256]; - - sprintf(buff, "Error: execvp of %s failed: %s\n", + + sprintf(buff, "Error: execvp of %s failed: %s\n", argv[0], strerror(errno)); write(2, buff, strlen(buff)+1); } close(0); close(1); close(2); /* XXX */ exit(1); - + default: if (do_pty == 2) { close(s); @@ -413,32 +446,36 @@ int fork_exec(struct socket *so, char *ex, int do_pty) setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); } fd_nonblock(so->s); - + /* Append the telnet options now */ if (so->so_m != 0 && do_pty == 1) { sbappend(so, so->so_m); so->so_m = 0; } - + return 1; } } #endif #ifndef HAVE_STRDUP -char *strdup(const char *str) +char * +strdup(str) + const char *str; { char *bptr; - + bptr = (char *)malloc(strlen(str)+1); strcpy(bptr, str); - + return bptr; } #endif #if 0 -void snooze_hup(int num) +void +snooze_hup(num) + int num; { int s, ret; #ifndef NO_UNIX_SOCKETS @@ -446,7 +483,7 @@ void snooze_hup(int num) #endif struct sockaddr_in sock_in; char buff[256]; - + ret = -1; if (slirp_socket_passwd) { s = socket(AF_INET, SOCK_STREAM, 0); @@ -476,48 +513,51 @@ void snooze_hup(int num) #endif slirp_exit(0); } - - -void snooze() + + +void +snooze() { sigset_t s; int i; - + /* Don't need our data anymore */ /* XXX This makes SunOS barf */ /* brk(0); */ - + /* Close all fd's */ for (i = 255; i >= 0; i--) close(i); - + signal(SIGQUIT, slirp_exit); signal(SIGHUP, snooze_hup); sigemptyset(&s); - + /* Wait for any signal */ sigsuspend(&s); - + /* Just in case ... */ exit(255); } -void relay(int s) +void +relay(s) + int s; { char buf[8192]; int n; fd_set readfds; struct ttys *ttyp; - + /* Don't need our data anymore */ /* XXX This makes SunOS barf */ /* brk(0); */ - + signal(SIGQUIT, slirp_exit); signal(SIGHUP, slirp_exit); signal(SIGINT, slirp_exit); signal(SIGTERM, slirp_exit); - + /* Fudge to get term_raw and term_restore to work */ if (NULL == (ttyp = tty_attach (0, slirp_tty))) { lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); @@ -526,18 +566,18 @@ void relay(int s) ttyp->fd = 0; ttyp->flags |= TTY_CTTY; term_raw(ttyp); - + while (1) { FD_ZERO(&readfds); - + FD_SET(0, &readfds); FD_SET(s, &readfds); - + n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); - + if (n <= 0) slirp_exit(0); - + if (FD_ISSET(0, &readfds)) { n = read(0, buf, 8192); if (n <= 0) @@ -546,7 +586,7 @@ void relay(int s) if (n <= 0) slirp_exit(0); } - + if (FD_ISSET(s, &readfds)) { n = read(s, buf, 8192); if (n <= 0) @@ -556,20 +596,43 @@ void relay(int s) slirp_exit(0); } } - + /* Just in case.... */ exit(1); } #endif -int (*lprint_print)(void *, const char *, va_list); -char *lprint_ptr, *lprint_ptr2, **lprint_arg; +#ifdef CONFIG_QEMU +extern void term_vprintf(const char *fmt, va_list ap); void lprint(const char *format, ...) { - va_list args; - + va_list args; + va_start(args, format); + term_vprintf(format, args); + va_end(args); +} +#else +int (*lprint_print) _P((void *, const char *, va_list)); +char *lprint_ptr, *lprint_ptr2, **lprint_arg; + +void +#ifdef __STDC__ +lprint(const char *format, ...) +#else +lprint(va_alist) va_dcl +#endif +{ + va_list args; + +#ifdef __STDC__ + va_start(args, format); +#else + char *format; + va_start(args); + format = va_arg(args, char *); +#endif #if 0 /* If we're printing to an sbuf, make sure there's enough room */ /* XXX +100? */ @@ -579,33 +642,33 @@ void lprint(const char *format, ...) int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; int deltap = lprint_ptr - lprint_sb->sb_data; - + lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, lprint_sb->sb_datalen + TCP_SNDSPACE); - + /* Adjust all values */ lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; lprint_ptr = lprint_sb->sb_data + deltap; - + lprint_sb->sb_datalen += TCP_SNDSPACE; } } -#endif +#endif if (lprint_print) lprint_ptr += (*lprint_print)(*lprint_arg, format, args); - + /* Check if they want output to be logged to file as well */ if (lfd) { - /* + /* * Remove \r's * otherwise you'll get ^M all over the file */ int len = strlen(format); char *bptr1, *bptr2; - + bptr1 = bptr2 = strdup(format); - + while (len--) { if (*bptr1 == '\r') memcpy(bptr1, bptr1+1, len+1); @@ -618,7 +681,9 @@ void lprint(const char *format, ...) va_end(args); } -void add_emu(char *buff) +void +add_emu(buff) + char *buff; { u_int lport, fport; u_int8_t tos = 0, emu = 0; @@ -626,12 +691,12 @@ void add_emu(char *buff) char *buff3 = buff4; struct emu_t *emup; struct socket *so; - + if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { lprint("Error: Bad arguments\r\n"); return; } - + if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { lport = 0; if (sscanf(buff1, "%d", &fport) != 1) { @@ -639,7 +704,7 @@ void add_emu(char *buff) return; } } - + if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { buff3 = 0; if (sscanf(buff2, "%256s", buff1) != 1) { @@ -647,7 +712,7 @@ void add_emu(char *buff) return; } } - + if (buff3) { if (strcmp(buff3, "lowdelay") == 0) tos = IPTOS_LOWDELAY; @@ -658,7 +723,7 @@ void add_emu(char *buff) return; } } - + if (strcmp(buff1, "ftp") == 0) emu = EMU_FTP; else if (strcmp(buff1, "irc") == 0) @@ -669,7 +734,7 @@ void add_emu(char *buff) lprint("Error: Unknown service\r\n"); return; } - + /* First, check that it isn't already emulated */ for (emup = tcpemu; emup; emup = emup->next) { if (emup->lport == lport && emup->fport == fport) { @@ -677,7 +742,7 @@ void add_emu(char *buff) return; } } - + /* link it */ emup = (struct emu_t *)malloc(sizeof (struct emu_t)); emup->lport = (u_int16_t)lport; @@ -686,7 +751,7 @@ void add_emu(char *buff) emup->emu = emu; emup->next = tcpemu; tcpemu = emup; - + /* And finally, mark all current sessions, if any, as being emulated */ for (so = tcb.so_next; so != &tcb; so = so->so_next) { if ((lport && lport == ntohs(so->so_lport)) || @@ -697,9 +762,10 @@ void add_emu(char *buff) so->so_iptos = tos; } } - + lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); } +#endif #ifdef BAD_SPRINTF @@ -710,33 +776,51 @@ void add_emu(char *buff) * Some BSD-derived systems have a sprintf which returns char * */ -int vsprintf_len(char *string, const char *format, va_list args) +int +vsprintf_len(string, format, args) + char *string; + const char *format; + va_list args; { vsprintf(string, format, args); return strlen(string); } -int sprintf_len(char *string, const char *format, ...) +int +#ifdef __STDC__ +sprintf_len(char *string, const char *format, ...) +#else +sprintf_len(va_alist) va_dcl +#endif { va_list args; +#ifdef __STDC__ va_start(args, format); +#else + char *string; + char *format; + va_start(args); + string = va_arg(args, char *); + format = va_arg(args, char *); +#endif vsprintf(string, format, args); - va_end(args); return strlen(string); } #endif -void u_sleep(int usec) +void +u_sleep(usec) + int usec; { struct timeval t; fd_set fdset; - + FD_ZERO(&fdset); - + t.tv_sec = 0; t.tv_usec = usec * 1000; - + select(0, &fdset, &fdset, &fdset, &t); } @@ -744,30 +828,34 @@ void u_sleep(int usec) * Set fd blocking and non-blocking */ -void fd_nonblock(int fd) +void +fd_nonblock(fd) + int fd; { -#if defined USE_FIONBIO && defined FIONBIO - ioctlsockopt_t opt = 1; - +#ifdef FIONBIO + int opt = 1; + ioctlsocket(fd, FIONBIO, &opt); #else int opt; - + opt = fcntl(fd, F_GETFL, 0); opt |= O_NONBLOCK; fcntl(fd, F_SETFL, opt); #endif } -void fd_block(int fd) +void +fd_block(fd) + int fd; { -#if defined USE_FIONBIO && defined FIONBIO - ioctlsockopt_t opt = 0; - +#ifdef FIONBIO + int opt = 0; + ioctlsocket(fd, FIONBIO, &opt); #else int opt; - + opt = fcntl(fd, F_GETFL, 0); opt &= ~O_NONBLOCK; fcntl(fd, F_SETFL, opt); @@ -779,17 +867,22 @@ void fd_block(int fd) /* * invoke RSH */ -int rsh_exec(struct socket *so, struct socket *ns, - char *user, char *host, char *args) +int +rsh_exec(so,ns, user, host, args) + struct socket *so; + struct socket *ns; + char *user; + char *host; + char *args; { int fd[2]; int fd0[2]; int s; char buff[256]; - + DEBUG_CALL("rsh_exec"); DEBUG_ARG("so = %lx", (long)so); - + if (pipe(fd)<0) { lprint("Error: pipe failed: %s\n", strerror(errno)); return 0; @@ -810,7 +903,7 @@ int rsh_exec(struct socket *so, struct socket *ns, return 0; } #endif - + switch(fork()) { case -1: lprint("Error: fork failed: %s\n", strerror(errno)); @@ -819,11 +912,11 @@ int rsh_exec(struct socket *so, struct socket *ns, close(fd0[0]); close(fd0[1]); return 0; - + case 0: close(fd[0]); close(fd0[0]); - + /* Set the DISPLAY */ if (x_port >= 0) { #ifdef HAVE_SETENV @@ -834,29 +927,29 @@ int rsh_exec(struct socket *so, struct socket *ns, putenv(buff); #endif } - + dup2(fd0[1], 0); dup2(fd0[1], 1); dup2(fd[1], 2); for (s = 3; s <= 255; s++) close(s); - + execlp("rsh","rsh","-l", user, host, args, NULL); - + /* Ooops, failed, let's tell the user why */ - - sprintf(buff, "Error: execlp of %s failed: %s\n", + + sprintf(buff, "Error: execlp of %s failed: %s\n", "rsh", strerror(errno)); write(2, buff, strlen(buff)+1); close(0); close(1); close(2); /* XXX */ exit(1); - + default: close(fd[1]); close(fd0[1]); ns->s=fd[0]; so->s=fd0[0]; - + return 1; } } diff --git a/BasiliskII/src/slirp/misc.h b/BasiliskII/src/slirp/misc.h index 381f5f3e..e405e38d 100644 --- a/BasiliskII/src/slirp/misc.h +++ b/BasiliskII/src/slirp/misc.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -12,22 +12,22 @@ struct ex_list { int ex_pty; /* Do we want a pty? */ int ex_addr; /* The last byte of the address */ int ex_fport; /* Port to telnet to */ - char *ex_exec; /* Command line of what to exec */ + const char *ex_exec; /* Command line of what to exec */ struct ex_list *ex_next; }; extern struct ex_list *exec_list; -extern u_int curtime, time_fasttimo, last_slowtimo, detach_time, detach_wait; +extern u_int curtime, time_fasttimo, last_slowtimo; -extern int (*lprint_print)(void *, const char *, va_list); +extern int (*lprint_print) _P((void *, const char *, va_list)); extern char *lprint_ptr, *lprint_ptr2, **lprint_arg; extern struct sbuf *lprint_sb; #ifndef HAVE_STRDUP -char *strdup(const char *); +char *strdup _P((const char *)); #endif -void do_wait(int); +void do_wait _P((int)); #define EMU_NONE 0x0 @@ -63,25 +63,27 @@ struct emu_t { struct emu_t *next; }; +#ifndef CONFIG_QEMU extern struct emu_t *tcpemu; +#endif extern int x_port, x_server, x_display; -int show_x(char *, struct socket *); -void redir_x(u_int32_t, int, int, int); -void getouraddr(void); -void slirp_insque(void *, void *); -void slirp_remque(void *); -int add_exec(struct ex_list **, int, char *, int, int); -int slirp_openpty(int *, int *); -int fork_exec(struct socket *, char *, int); -void snooze_hup(int); -void snooze(void); -void relay(int); -void add_emu(char *); -void u_sleep(int); -void fd_nonblock(int); -void fd_block(int); -int rsh_exec(struct socket *, struct socket *, char *, char *, char *); +int show_x _P((char *, struct socket *)); +void redir_x _P((u_int32_t, int, int, int)); +void getouraddr _P((void)); +inline void slirp_insque _P((void *, void *)); +inline void slirp_remque _P((void *)); +int add_exec _P((struct ex_list **, int, char *, int, int)); +int slirp_openpty _P((int *, int *)); +int fork_exec(struct socket *so, const char *ex, int do_pty); +void snooze_hup _P((int)); +void snooze _P((void)); +void relay _P((int)); +void add_emu _P((char *)); +void u_sleep _P((int)); +void fd_nonblock _P((int)); +void fd_block _P((int)); +int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *)); #endif diff --git a/BasiliskII/src/slirp/sbuf.c b/BasiliskII/src/slirp/sbuf.c index 278e3687..02c5fce0 100644 --- a/BasiliskII/src/slirp/sbuf.c +++ b/BasiliskII/src/slirp/sbuf.c @@ -1,31 +1,37 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ -#include #include +static void sbappendsb(struct sbuf *sb, struct mbuf *m); + /* Done as a macro in socket.h */ /* int - * sbspace(struct sockbuff *sb) + * sbspace(struct sockbuff *sb) * { * return SB_DATALEN - sb->sb_cc; * } */ -void sbfree(struct sbuf *sb) +void +sbfree(sb) + struct sbuf *sb; { free(sb->sb_data); } -void sbdrop(struct sbuf *sb, u_int num) +void +sbdrop(sb, num) + struct sbuf *sb; + int num; { - /* + /* * We can only drop how much we have - * This should never succeed + * This should never succeed */ if(num > sb->sb_cc) num = sb->sb_cc; @@ -33,10 +39,13 @@ void sbdrop(struct sbuf *sb, u_int num) sb->sb_rptr += num; if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) sb->sb_rptr -= sb->sb_datalen; - + } -void sbreserve(struct sbuf *sb, size_t size) +void +sbreserve(sb, size) + struct sbuf *sb; + int size; { if (sb->sb_data) { /* Already alloced, realloc if necessary */ @@ -64,21 +73,24 @@ void sbreserve(struct sbuf *sb, size_t size) * this prevents an unnecessary copy of the data * (the socket is non-blocking, so we won't hang) */ -void sbappend(struct socket *so, struct mbuf *m) +void +sbappend(so, m) + struct socket *so; + struct mbuf *m; { int ret = 0; - + DEBUG_CALL("sbappend"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); - DEBUG_ARG("m->m_len = %zu", m->m_len); - + DEBUG_ARG("m->m_len = %d", m->m_len); + /* Shouldn't happen, but... e.g. foreign host closes connection */ if (m->m_len <= 0) { m_free(m); return; } - + /* * If there is urgent data, call sosendoob * if not all was sent, sowrite will take care of the rest @@ -90,16 +102,16 @@ void sbappend(struct socket *so, struct mbuf *m) sosendoob(so); return; } - + /* * We only write if there's nothing in the buffer, * ottherwise it'll arrive out of order, and hence corrupt */ if (!so->so_rcv.sb_cc) ret = send(so->s, m->m_data, m->m_len, 0); - + if (ret <= 0) { - /* + /* * Nothing was written * It's possible that the socket has closed, but * we don't need to check because if it has closed, @@ -123,10 +135,11 @@ void sbappend(struct socket *so, struct mbuf *m) * Copy the data from m into sb * The caller is responsible to make sure there's enough room */ -void sbappendsb(struct sbuf *sb, struct mbuf *m) +static void +sbappendsb(struct sbuf *sb, struct mbuf *m) { int len, n, nn; - + len = m->m_len; if (sb->sb_wptr < sb->sb_rptr) { @@ -159,10 +172,15 @@ void sbappendsb(struct sbuf *sb, struct mbuf *m) * Don't update the sbuf rptr, this will be * done in sbdrop when the data is acked */ -void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to) +void +sbcopy(sb, off, len, to) + struct sbuf *sb; + int off; + int len; + char *to; { char *from; - + from = sb->sb_rptr + off; if (from >= sb->sb_data + sb->sb_datalen) from -= sb->sb_datalen; @@ -180,4 +198,4 @@ void sbcopy(struct sbuf *sb, u_int off, u_int len, char *to) memcpy(to+off,sb->sb_data,len); } } - + diff --git a/BasiliskII/src/slirp/sbuf.h b/BasiliskII/src/slirp/sbuf.h index 04f7981c..a4f10362 100644 --- a/BasiliskII/src/slirp/sbuf.h +++ b/BasiliskII/src/slirp/sbuf.h @@ -1,15 +1,13 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ #ifndef _SBUF_H_ #define _SBUF_H_ -#include - #define sbflush(sb) sbdrop((sb),(sb)->sb_cc) #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) @@ -23,11 +21,10 @@ struct sbuf { char *sb_data; /* Actual data */ }; -void sbfree(struct sbuf *); -void sbdrop(struct sbuf *, u_int); -void sbreserve(struct sbuf *, size_t); -void sbappend(struct socket *, struct mbuf *); -void sbappendsb(struct sbuf *, struct mbuf *); -void sbcopy(struct sbuf *, u_int, u_int, char *); +void sbfree _P((struct sbuf *)); +void sbdrop _P((struct sbuf *, int)); +void sbreserve _P((struct sbuf *, int)); +void sbappend _P((struct socket *, struct mbuf *)); +void sbcopy _P((struct sbuf *, int, int, char *)); #endif diff --git a/BasiliskII/src/slirp/slirp.c b/BasiliskII/src/slirp/slirp.c index dc2fdc65..303f4825 100644 --- a/BasiliskII/src/slirp/slirp.c +++ b/BasiliskII/src/slirp/slirp.c @@ -12,7 +12,7 @@ struct in_addr special_addr; /* virtual address alias for host */ struct in_addr alias_addr; -const uint8_t special_ethaddr[6] = { +static const uint8_t special_ethaddr[6] = { 0x52, 0x54, 0x00, 0x12, 0x35, 0x00 }; @@ -38,10 +38,10 @@ static int get_dns_addr(struct in_addr *pdns_addr) DWORD ret; IP_ADDR_STRING *pIPAddr; struct in_addr tmp_addr; - + FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); BufLen = sizeof(FIXED_INFO); - + if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { if (FixedInfo) { GlobalFree(FixedInfo); @@ -49,7 +49,7 @@ static int get_dns_addr(struct in_addr *pdns_addr) } FixedInfo = GlobalAlloc(GPTR, BufLen); } - + if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); if (FixedInfo) { @@ -58,14 +58,14 @@ static int get_dns_addr(struct in_addr *pdns_addr) } return -1; } - + pIPAddr = &(FixedInfo->DnsServerList); inet_aton(pIPAddr->IpAddress.String, &tmp_addr); *pdns_addr = tmp_addr; #if 0 printf( "DNS Servers:\n" ); printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String ); - + pIPAddr = FixedInfo -> DnsServerList.Next; while ( pIPAddr ) { printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String ); @@ -84,16 +84,18 @@ static int get_dns_addr(struct in_addr *pdns_addr) static int get_dns_addr(struct in_addr *pdns_addr) { char buff[512]; - char buff2[256+1]; + char buff2[256]; FILE *f; int found = 0; struct in_addr tmp_addr; - + f = fopen("/etc/resolv.conf", "r"); if (!f) return -1; +#ifdef DEBUG lprint("IP address of your DNS(s): "); +#endif while (fgets(buff, 512, f) != NULL) { if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) { if (!inet_aton(buff2, &tmp_addr)) @@ -103,13 +105,20 @@ static int get_dns_addr(struct in_addr *pdns_addr) /* If it's the first one, set it to dns_addr */ if (!found) *pdns_addr = tmp_addr; +#ifdef DEBUG else lprint(", "); +#endif if (++found > 3) { +#ifdef DEBUG lprint("(more)"); +#endif break; - } else + } +#ifdef DEBUG + else lprint("%s", inet_ntoa(tmp_addr)); +#endif } } fclose(f); @@ -121,16 +130,16 @@ static int get_dns_addr(struct in_addr *pdns_addr) #endif #ifdef _WIN32 -void slirp_cleanup(void) +static void slirp_cleanup(void) { WSACleanup(); } #endif -int slirp_init(void) +void slirp_init(void) { // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); - + #ifdef _WIN32 { WSADATA Data; @@ -150,13 +159,14 @@ int slirp_init(void) /* set default addresses */ inet_aton("127.0.0.1", &loopback_addr); - if (get_dns_addr(&dns_addr) < 0) - return -1; + if (get_dns_addr(&dns_addr) < 0) { + dns_addr = loopback_addr; + fprintf (stderr, "Warning: No DNS servers found\n"); + } inet_aton(CTL_SPECIAL, &special_addr); - alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); - getouraddr(); - return 0; + alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); + getouraddr(); } #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) @@ -179,56 +189,57 @@ static void updtime(void) static void updtime(void) { gettimeofday(&tt, 0); - + curtime = (u_int)tt.tv_sec * (u_int)1000; curtime += (u_int)tt.tv_usec / (u_int)1000; - + if ((tt.tv_usec % 1000) >= 500) curtime++; } #endif -int slirp_select_fill(int *pnfds, - fd_set *readfds, fd_set *writefds, fd_set *xfds) +void slirp_select_fill(int *pnfds, + fd_set *readfds, fd_set *writefds, fd_set *xfds) { struct socket *so, *so_next; + struct timeval timeout; int nfds; - int timeout, tmp_time; + int tmp_time; /* fail safe */ global_readfds = NULL; global_writefds = NULL; global_xfds = NULL; - + nfds = *pnfds; /* * First, TCP sockets */ do_slowtimo = 0; if (link_up) { - /* + /* * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ do_slowtimo = ((tcb.so_next != &tcb) || ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); - + for (so = tcb.so_next; so != &tcb; so = so_next) { so_next = so->so_next; - + /* * See if we need a tcp_fasttimo */ if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) - time_fasttimo = curtime; /* Flag when we want a fasttimo */ - + time_fasttimo = curtime; /* Flag when we want a fasttimo */ + /* * NOFDREF can include still connecting to local-host, * newly socreated() sockets etc. Don't want to select these. */ if (so->so_state & SS_NOFDREF || so->s == -1) - continue; - + continue; + /* * Set for reading sockets which are accepting */ @@ -237,7 +248,7 @@ int slirp_select_fill(int *pnfds, UPD_NFDS(so->s); continue; } - + /* * Set for writing sockets which are connecting */ @@ -246,7 +257,7 @@ int slirp_select_fill(int *pnfds, UPD_NFDS(so->s); continue; } - + /* * Set for writing if we are connected, can send more, and * we have something to send @@ -255,7 +266,7 @@ int slirp_select_fill(int *pnfds, FD_SET(so->s, writefds); UPD_NFDS(so->s); } - + /* * Set for reading (and urgent data) if we are connected, can * receive more, and we have room for it XXX /2 ? @@ -266,13 +277,13 @@ int slirp_select_fill(int *pnfds, UPD_NFDS(so->s); } } - + /* * UDP sockets */ for (so = udb.so_next; so != &udb; so = so_next) { so_next = so->so_next; - + /* * See if it's timed out */ @@ -283,7 +294,7 @@ int slirp_select_fill(int *pnfds, } else do_slowtimo = 1; /* Let socket expire */ } - + /* * When UDP packets are received from over the * link, they're sendto()'d straight away, so @@ -300,58 +311,51 @@ int slirp_select_fill(int *pnfds, } } } - + /* * Setup timeout to use minimum CPU usage, especially when idle */ - timeout = -1; - /* - * If a slowtimo is needed, set timeout to 5ms from the last - * slow timeout. If a fast timeout is needed, set timeout within - * 2ms of when it was requested. + * First, see the timeout needed by *timo + */ + timeout.tv_sec = 0; + timeout.tv_usec = -1; + /* + * If a slowtimo is needed, set timeout to 500ms from the last + * slow timeout. If a fast timeout is needed, set timeout within + * 200ms of when it was requested. */ -# define SLOW_TIMO 5 -# define FAST_TIMO 2 if (do_slowtimo) { - timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000; - if (timeout < 0) - timeout = 0; - else if (timeout > (SLOW_TIMO * 1000)) - timeout = SLOW_TIMO * 1000; - + /* XXX + 10000 because some select()'s aren't that accurate */ + timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000; + if (timeout.tv_usec < 0) + timeout.tv_usec = 0; + else if (timeout.tv_usec > 510000) + timeout.tv_usec = 510000; + /* Can only fasttimo if we also slowtimo */ if (time_fasttimo) { - tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000; + tmp_time = (200 - (curtime - time_fasttimo)) * 1000; if (tmp_time < 0) - tmp_time = 0; - + tmp_time = 0; + /* Choose the smallest of the 2 */ - if (tmp_time < timeout) - timeout = tmp_time; + if (tmp_time < timeout.tv_usec) + timeout.tv_usec = (u_int)tmp_time; } } - *pnfds = nfds; - - /* - * Adjust the timeout to make the minimum timeout - * 2ms (XXX?) to lessen the CPU load - */ - if (timeout < (FAST_TIMO * 1000)) - timeout = FAST_TIMO * 1000; - - return timeout; -} + *pnfds = nfds; +} void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) { - struct socket *so, *so_next; - int ret; + struct socket *so, *so_next; + int ret; - global_readfds = readfds; - global_writefds = writefds; - global_xfds = xfds; + global_readfds = readfds; + global_writefds = writefds; + global_xfds = xfds; /* Update time */ updtime(); @@ -360,11 +364,11 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) * See if anything has timed out */ if (link_up) { - if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) { + if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { tcp_fasttimo(); time_fasttimo = 0; } - if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) { + if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { ip_slowtimo(); tcp_slowtimo(); last_slowtimo = curtime; @@ -386,7 +390,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) * (and they can crash the program) */ if (so->so_state & SS_NOFDREF || so->s == -1) - continue; + continue; /* * Check for URG data @@ -394,7 +398,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) * test for readfds below if this succeeds */ if (FD_ISSET(so->s, xfds)) - sorecvoob(so); + sorecvoob(so); /* * Check sockets for reading */ @@ -410,88 +414,82 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) /* Output it if we read something */ if (ret > 0) - tcp_output(sototcpcb(so)); + tcp_output(sototcpcb(so)); } /* * Check sockets for writing */ if (FD_ISSET(so->s, writefds)) { - /* - * Check for non-blocking, still-connecting sockets - */ - if (so->so_state & SS_ISFCONNECTING) { - /* Connected */ - so->so_state &= ~SS_ISFCONNECTING; + /* + * Check for non-blocking, still-connecting sockets + */ + if (so->so_state & SS_ISFCONNECTING) { + /* Connected */ + so->so_state &= ~SS_ISFCONNECTING; - ret = send(so->s, (char*)&ret, 0, 0); - if (ret < 0) { - /* XXXXX Must fix, zero bytes is a NOP */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; + ret = send(so->s, &ret, 0, 0); + if (ret < 0) { + /* XXXXX Must fix, zero bytes is a NOP */ + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == EINPROGRESS || errno == ENOTCONN) + continue; - /* else failed */ - so->so_state = SS_NOFDREF; - } - /* else so->so_state &= ~SS_ISFCONNECTING; */ + /* else failed */ + so->so_state = SS_NOFDREF; + } + /* else so->so_state &= ~SS_ISFCONNECTING; */ - /* - * Continue tcp_input - */ - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); - /* continue; */ - } - else - ret = sowrite(so); - /* - * XXXXX If we wrote something (a lot), there - * could be a need for a window update. - * In the worst case, the remote will send - * a window probe to get things going again - */ + /* + * Continue tcp_input + */ + tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); + /* continue; */ + } else + ret = sowrite(so); + /* + * XXXXX If we wrote something (a lot), there + * could be a need for a window update. + * In the worst case, the remote will send + * a window probe to get things going again + */ } /* * Probe a still-connecting, non-blocking socket * to check if it's still alive - */ + */ #ifdef PROBE_CONN if (so->so_state & SS_ISFCONNECTING) { - ret = recv(so->s, (char *)&ret, 0, 0); + ret = recv(so->s, (char *)&ret, 0,0); - if (ret < 0) { - /* XXX */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; /* Still connecting, continue */ + if (ret < 0) { + /* XXX */ + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == EINPROGRESS || errno == ENOTCONN) + continue; /* Still connecting, continue */ - /* else failed */ - so->so_state = SS_NOFDREF; + /* else failed */ + so->so_state = SS_NOFDREF; - /* tcp_input will take care of it */ - } - else { - ret = send(so->s, &ret, 0, 0); - if (ret < 0) { - /* XXX */ - int error = WSAGetLastError(); - if (error == EAGAIN || error == WSAEWOULDBLOCK || - error == WSAEINPROGRESS || error == WSAENOTCONN) - continue; - /* else failed */ - so->so_state = SS_NOFDREF; - } - else - so->so_state &= ~SS_ISFCONNECTING; + /* tcp_input will take care of it */ + } else { + ret = send(so->s, &ret, 0,0); + if (ret < 0) { + /* XXX */ + if (errno == EAGAIN || errno == EWOULDBLOCK || + errno == EINPROGRESS || errno == ENOTCONN) + continue; + /* else failed */ + so->so_state = SS_NOFDREF; + } else + so->so_state &= ~SS_ISFCONNECTING; - } - tcp_input((struct mbuf *)NULL, sizeof(struct ip), so); - } /* SS_ISFCONNECTING */ + } + tcp_input((struct mbuf *)NULL, sizeof(struct ip),so); + } /* SS_ISFCONNECTING */ #endif - } + } /* * Now UDP sockets. @@ -502,25 +500,25 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) so_next = so->so_next; if (so->s != -1 && FD_ISSET(so->s, readfds)) { - sorecvfrom(so); - } + sorecvfrom(so); + } } -} + } /* * See if we can start outputting */ if (if_queued && link_up) - if_start(); + if_start(); /* clear global file descriptor sets. * these reside on the stack in vl.c * so they're unusable if we're not in * slirp_select_fill or slirp_select_poll. */ - global_readfds = NULL; - global_writefds = NULL; - global_xfds = NULL; + global_readfds = NULL; + global_writefds = NULL; + global_xfds = NULL; } #define ETH_ALEN 6 @@ -532,7 +530,7 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) #define ARPOP_REQUEST 1 /* ARP request */ #define ARPOP_REPLY 2 /* ARP reply */ -struct ethhdr +struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ @@ -570,7 +568,7 @@ void arp_input(const uint8_t *pkt, int pkt_len) switch(ar_op) { case ARPOP_REQUEST: if (!memcmp(ah->ar_tip, &special_addr, 3)) { - if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) + if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) goto arp_ok; for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { if (ex_ptr->ex_addr == ah->ar_tip[3]) @@ -611,8 +609,8 @@ void slirp_input(const uint8_t *pkt, int pkt_len) if (pkt_len < ETH_HLEN) return; - - proto = (pkt[12] << 8) | pkt[13]; + + proto = ntohs(*(uint16_t *)(pkt + 12)); switch(proto) { case ETH_P_ARP: arp_input(pkt, pkt_len); @@ -653,24 +651,24 @@ void if_encap(const uint8_t *ip_data, int ip_data_len) slirp_output(buf, ip_data_len + ETH_HLEN); } -int slirp_redir(int is_udp, int host_port, +int slirp_redir(int is_udp, int host_port, struct in_addr guest_addr, int guest_port) { if (is_udp) { - if (!udp_listen(htons(host_port), guest_addr.s_addr, + if (!udp_listen(htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } else { - if (!solisten(htons(host_port), guest_addr.s_addr, + if (!solisten(htons(host_port), guest_addr.s_addr, htons(guest_port), 0)) return -1; } return 0; } -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, +int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, int guest_port) { - return add_exec(&exec_list, do_pty, (char *)args, + return add_exec(&exec_list, do_pty, (char *)args, addr_low_byte, htons(guest_port)); } diff --git a/BasiliskII/src/slirp/slirp.h b/BasiliskII/src/slirp/slirp.h index b845caa7..b8d756e5 100644 --- a/BasiliskII/src/slirp/slirp.h +++ b/BasiliskII/src/slirp/slirp.h @@ -3,12 +3,21 @@ #define CONFIG_QEMU -#define DEBUG 1 +//#define DEBUG 1 + +// Uncomment the following line to enable SLIRP statistics printing in Qemu +//#define LOG_ENABLED + +#ifdef LOG_ENABLED +#define STAT(expr) expr +#else +#define STAT(expr) do { } while(0) +#endif #ifndef CONFIG_QEMU #include "version.h" #endif -#include "config.h" +#include "config-host.h" #include "slirp_config.h" #ifdef _WIN32 @@ -19,31 +28,20 @@ typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; typedef uint64_t u_int64_t; typedef char *caddr_t; -typedef int socklen_t; -typedef unsigned long ioctlsockopt_t; +#define WIN32_LEAN_AND_MEAN +# include # include -# include # include # include -# define USE_FIONBIO 1 - -/* Basilisk II Router defines those */ -# define udp_read_completion slirp_udp_read_completion -# define write_udp slirp_write_udp -# define init_udp slirp_init_udp -# define final_udp slirp_final_udp +# define EWOULDBLOCK WSAEWOULDBLOCK +# define EINPROGRESS WSAEINPROGRESS +# define ENOTCONN WSAENOTCONN +# define EHOSTUNREACH WSAEHOSTUNREACH +# define ENETUNREACH WSAENETUNREACH +# define ECONNREFUSED WSAECONNREFUSED #else -# define WSAGetLastError() (int)(errno) -# define WSASetLastError(e) (void)(errno = (e)) -# define WSAEWOULDBLOCK EWOULDBLOCK -# define WSAEINPROGRESS EINPROGRESS -# define WSAENOTCONN ENOTCONN -# define WSAEHOSTUNREACH EHOSTUNREACH -# define WSAENETUNREACH ENETUNREACH -# define WSAECONNREFUSED ECONNREFUSED -typedef int ioctlsockopt_t; # define ioctlsocket ioctl # define closesocket(s) close(s) # define O_BINARY 0 @@ -53,13 +51,8 @@ typedef int ioctlsockopt_t; #ifdef HAVE_SYS_BITYPES_H # include #endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifndef _WIN32 #include -#endif #ifdef NEED_TYPEDEFS typedef char int8_t; @@ -90,11 +83,6 @@ typedef unsigned char u_int8_t; # endif #endif /* NEED_TYPEDEFS */ -/* Basilisk II types glue */ -typedef u_int8_t uint8; -typedef u_int16_t uint16; -typedef u_int32_t uint32; - #ifdef HAVE_UNISTD_H # include #endif @@ -129,6 +117,17 @@ typedef u_int32_t uint32; #ifndef _WIN32 #include +#endif + +#ifndef _P +#ifndef NO_PROTOTYPES +# define _P(x) x +#else +# define _P(x) () +#endif +#endif + +#ifndef _WIN32 #include #include #endif @@ -139,23 +138,20 @@ typedef u_int32_t uint32; /* Systems lacking strdup() definition in . */ #if defined(ultrix) -char *strdup(const char *); +char *strdup _P((const char *)); #endif /* Systems lacking malloc() definition in . */ #if defined(ultrix) || defined(hcx) -void *malloc(size_t arg); -void free(void *ptr); +void *malloc _P((size_t arg)); +void free _P((void *ptr)); #endif #ifndef HAVE_INET_ATON -int inet_aton(const char *cp, struct in_addr *ia); +int inet_aton _P((const char *cp, struct in_addr *ia)); #endif #include -#ifdef _WIN32 -#include -#endif #ifndef NO_UNIX_SOCKETS #include #endif @@ -187,7 +183,11 @@ int inet_aton(const char *cp, struct in_addr *ia); #include #endif +#ifdef __STDC__ #include +#else +#include +#endif #include @@ -202,20 +202,6 @@ int inet_aton(const char *cp, struct in_addr *ia); #include "debug.h" -#if defined __GNUC__ -#define PACKED__ __attribute__ ((packed)) -#elif defined _MSC_VER -#define PRAGMA_PACK_SUPPORTED 1 -#define PACK_RESET -#define PACKED__ -#elif defined __sgi -#define PRAGMA_PACK_SUPPORTED 1 -#define PACK_RESET 0 -#define PACKED__ -#else -#error "Packed attribute or pragma shall be supported" -#endif - #include "ip.h" #include "tcp.h" #include "tcp_timer.h" @@ -246,47 +232,45 @@ extern struct ttys *ttys_unit[MAX_INTERFACES]; #endif #ifndef FULL_BOLT -void if_start(void); +void if_start _P((void)); #else -void if_start(struct ttys *); +void if_start _P((struct ttys *)); #endif #ifdef BAD_SPRINTF # define vsprintf vsprintf_len # define sprintf sprintf_len - extern int vsprintf_len(char *, const char *, va_list); - extern int sprintf_len(char *, const char *, ...); + extern int vsprintf_len _P((char *, const char *, va_list)); + extern int sprintf_len _P((char *, const char *, ...)); #endif #ifdef DECLARE_SPRINTF # ifndef BAD_SPRINTF - extern int vsprintf(char *, const char *, va_list); + extern int vsprintf _P((char *, const char *, va_list)); # endif - extern int vfprintf(FILE *, const char *, va_list); + extern int vfprintf _P((FILE *, const char *, va_list)); #endif #ifndef HAVE_STRERROR - extern char *strerror(int error); + extern char *strerror _P((int error)); #endif #ifndef HAVE_INDEX - char *index(const char *, int); + char *index _P((const char *, int)); #endif #ifndef HAVE_GETHOSTID - long gethostid(void); + long gethostid _P((void)); #endif -void lprint(const char *, ...); - -extern int do_echo; +void lprint _P((const char *, ...)); #if SIZEOF_CHAR_P == 4 # define insque_32 insque # define remque_32 remque #else - extern inline void insque_32(void *, void *); - extern inline void remque_32(void *); + inline void insque_32 _P((void *, void *)); + inline void remque_32 _P((void *)); #endif #ifndef _WIN32 @@ -295,51 +279,46 @@ extern int do_echo; #define DEFAULT_BAUD 115200 +#define SO_OPTIONS DO_KEEPALIVE +#define TCP_MAXIDLE (TCPTV_KEEPCNT * TCPTV_KEEPINTVL) + /* cksum.c */ int cksum(struct mbuf *m, int len); /* if.c */ -void if_init(void); -void if_output(struct socket *, struct mbuf *); +void if_init _P((void)); +void if_output _P((struct socket *, struct mbuf *)); /* ip_input.c */ -void ip_init(void); -void ip_input(struct mbuf *); -struct ip * ip_reass(register struct ipasfrag *, register struct ipq *); -void ip_freef(struct ipq *); -void ip_enq(register struct ipasfrag *, register struct ipasfrag *); -void ip_deq(register struct ipasfrag *); -void ip_slowtimo(void); -void ip_stripoptions(register struct mbuf *, struct mbuf *); +void ip_init _P((void)); +void ip_input _P((struct mbuf *)); +void ip_slowtimo _P((void)); +void ip_stripoptions _P((register struct mbuf *, struct mbuf *)); /* ip_output.c */ -int ip_output(struct socket *, struct mbuf *); +int ip_output _P((struct socket *, struct mbuf *)); /* tcp_input.c */ -int tcp_reass(register struct tcpcb *, register struct tcpiphdr *, struct mbuf *); -void tcp_input(register struct mbuf *, int, struct socket *); -void tcp_dooptions(struct tcpcb *, u_char *, int, struct tcpiphdr *); -void tcp_xmit_timer(register struct tcpcb *, int); -u_int tcp_mss(register struct tcpcb *, u_int); +void tcp_input _P((register struct mbuf *, int, struct socket *)); +int tcp_mss _P((register struct tcpcb *, u_int)); /* tcp_output.c */ -int tcp_output(register struct tcpcb *); -void tcp_setpersist(register struct tcpcb *); +int tcp_output _P((register struct tcpcb *)); +void tcp_setpersist _P((register struct tcpcb *)); /* tcp_subr.c */ -void tcp_init(void); -void tcp_template(struct tcpcb *); -void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int); -struct tcpcb * tcp_newtcpcb(struct socket *); -struct tcpcb * tcp_close(register struct tcpcb *); -void tcp_drain(void); -void tcp_sockclosed(struct tcpcb *); -int tcp_fconnect(struct socket *); -void tcp_connect(struct socket *); -int tcp_attach(struct socket *); -u_int8_t tcp_tos(struct socket *); -int tcp_emu(struct socket *, struct mbuf *); -int tcp_ctl(struct socket *); +void tcp_init _P((void)); +void tcp_template _P((struct tcpcb *)); +void tcp_respond _P((struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int)); +struct tcpcb * tcp_newtcpcb _P((struct socket *)); +struct tcpcb * tcp_close _P((register struct tcpcb *)); +void tcp_sockclosed _P((struct tcpcb *)); +int tcp_fconnect _P((struct socket *)); +void tcp_connect _P((struct socket *)); +int tcp_attach _P((struct socket *)); +u_int8_t tcp_tos _P((struct socket *)); +int tcp_emu _P((struct socket *, struct mbuf *)); +int tcp_ctl _P((struct socket *)); struct tcpcb *tcp_drop(struct tcpcb *tp, int err); #ifdef USE_PPP @@ -355,4 +334,9 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err); #define max(x,y) ((x) > (y) ? (x) : (y)) #endif +#ifdef _WIN32 +#undef errno +#define errno (WSAGetLastError()) +#endif + #endif diff --git a/BasiliskII/src/slirp/slirp_config.h b/BasiliskII/src/slirp/slirp_config.h index 237268fa..e7e95dd5 100644 --- a/BasiliskII/src/slirp/slirp_config.h +++ b/BasiliskII/src/slirp/slirp_config.h @@ -40,6 +40,11 @@ */ #undef USE_LOWCPU +/* Define this if your compiler doesn't like prototypes */ +#ifndef __STDC__ +#define NO_PROTOTYPES +#endif + /*********************************************************/ /* * Autoconf defined configuration options @@ -49,11 +54,40 @@ /* Ignore this */ #undef DUMMY_PPP -/* XXX: Define according to how time.h should be included */ -#undef TIME_WITH_SYS_TIME +/* Define if you have unistd.h */ +#define HAVE_UNISTD_H + +/* Define if you have stdlib.h */ +#define HAVE_STDLIB_H + +/* Define if you have sys/ioctl.h */ +#undef HAVE_SYS_IOCTL_H +#ifndef _WIN32 +#define HAVE_SYS_IOCTL_H +#endif + +/* Define if you have sys/filio.h */ +#undef HAVE_SYS_FILIO_H +#ifdef __APPLE__ +#define HAVE_SYS_FILIO_H +#endif + +/* Define if you have strerror */ +#define HAVE_STRERROR + +/* Define if you have strdup() */ +#define HAVE_STRDUP + +/* Define according to how time.h should be included */ #define TIME_WITH_SYS_TIME 0 #undef HAVE_SYS_TIME_H +/* Define if you have sys/bitypes.h */ +#undef HAVE_SYS_BITYPES_H + +/* Define if the machine is big endian */ +//#undef WORDS_BIGENDIAN + /* Define if your sprintf returns char * instead of int */ #undef BAD_SPRINTF @@ -69,17 +103,56 @@ /* Define if a declaration of sprintf/fprintf is needed */ #undef DECLARE_SPRINTF +/* Define if you have a POSIX.1 sys/wait.h */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have sys/select.h */ +#undef HAVE_SYS_SELECT_H +#ifndef _WIN32 +#define HAVE_SYS_SELECT_H +#endif + +/* Define if you have strings.h */ +#define HAVE_STRING_H + +/* Define if you have arpa/inet.h */ +#undef HAVE_ARPA_INET_H +#ifndef _WIN32 +#define HAVE_ARPA_INET_H +#endif + +/* Define if you have sys/signal.h */ +#undef HAVE_SYS_SIGNAL_H + /* Define if you have sys/stropts.h */ #undef HAVE_SYS_STROPTS_H +/* Define to whatever your compiler thinks inline should be */ +#define inline inline + +/* Define to whatever your compiler thinks const should be */ +#define const const + +/* Define if your compiler doesn't like prototypes */ +#undef NO_PROTOTYPES + /* Define if you don't have u_int32_t etc. typedef'd */ #undef NEED_TYPEDEFS #ifdef __sun__ #define NEED_TYPEDEFS #endif +/* Define to sizeof(char) */ +#define SIZEOF_CHAR 1 + +/* Define to sizeof(short) */ +#define SIZEOF_SHORT 2 + +/* Define to sizeof(int) */ +#define SIZEOF_INT 4 + /* Define to sizeof(char *) */ -#define SIZEOF_CHAR_P SIZEOF_VOID_P +#define SIZEOF_CHAR_P (HOST_LONG_BITS / 8) /* Define if you have random() */ #undef HAVE_RANDOM @@ -87,6 +160,12 @@ /* Define if you have srandom() */ #undef HAVE_SRANDOM +/* Define if you have inet_aton */ +#undef HAVE_INET_ATON +#ifndef _WIN32 +#define HAVE_INET_ATON +#endif + /* Define if you have setenv */ #undef HAVE_SETENV diff --git a/BasiliskII/src/slirp/socket.c b/BasiliskII/src/slirp/socket.c index 42ba31b2..0c15132e 100644 --- a/BasiliskII/src/slirp/socket.c +++ b/BasiliskII/src/slirp/socket.c @@ -1,12 +1,11 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ #define WANT_SYS_IOCTL_H -#include #include #include "ip_icmp.h" #include "main.h" @@ -14,18 +13,16 @@ #include #endif -#ifdef _WIN32 -#define IS_EAGAIN(e) ((e) == WSAEINTR || (e) == EAGAIN) -#else -#define IS_EAGAIN(e) ((e) == EAGAIN) -#endif +static void sofcantrcvmore(struct socket *so); +static void sofcantsendmore(struct socket *so); -void +#if 0 +static void so_init() { /* Nothing yet */ } - +#endif struct socket * solookup(head, laddr, lport, faddr, fport) @@ -36,19 +33,19 @@ solookup(head, laddr, lport, faddr, fport) u_int fport; { struct socket *so; - + for (so = head->so_next; so != head; so = so->so_next) { - if (so->so_lport == lport && + if (so->so_lport == lport && so->so_laddr.s_addr == laddr.s_addr && so->so_faddr.s_addr == faddr.s_addr && so->so_fport == fport) break; } - + if (so == head) return (struct socket *)NULL; return so; - + } /* @@ -60,7 +57,7 @@ struct socket * socreate() { struct socket *so; - + so = (struct socket *)malloc(sizeof(struct socket)); if(so) { memset(so, 0, sizeof(struct socket)); @@ -85,10 +82,10 @@ sofree(so) tcp_last_so = &tcb; else if (so == udp_last_so) udp_last_so = &udb; - + m_free(so->so_m); - - if(so->so_next && so->so_prev) + + if(so->so_next && so->so_prev) remque(so); /* crashes if so is not in a queue */ free(so); @@ -103,23 +100,22 @@ int soread(so) struct socket *so; { - int n, nn; - u_int lss, total; + int n, nn, lss, total; struct sbuf *sb = &so->so_snd; - u_int len = sb->sb_datalen - sb->sb_cc; + int len = sb->sb_datalen - sb->sb_cc; struct iovec iov[2]; - u_int mss = so->so_tcpcb->t_maxseg; - + int mss = so->so_tcpcb->t_maxseg; + DEBUG_CALL("soread"); DEBUG_ARG("so = %lx", (long )so); - - /* + + /* * No need to check if there's enough room to read. * soread wouldn't have been called if there weren't */ - + len = sb->sb_datalen - sb->sb_cc; - + iov[0].iov_base = sb->sb_wptr; if (sb->sb_wptr < sb->sb_rptr) { iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; @@ -158,16 +154,15 @@ soread(so) n = 1; } } - + #ifdef HAVE_READV nn = readv(so->s, (struct iovec *)iov, n); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); #else nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); -#endif +#endif if (nn <= 0) { - int error = WSAGetLastError(); - if (nn < 0 && IS_EAGAIN(error)) + if (nn < 0 && (errno == EINTR || errno == EAGAIN)) return 0; else { DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); @@ -176,7 +171,7 @@ soread(so) return -1; } } - + #ifndef HAVE_READV /* * If there was no error, try and read the second time round @@ -193,10 +188,10 @@ soread(so) if (ret > 0) nn += ret; } - + DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); #endif - + /* Update fields */ sb->sb_cc += nn; sb->sb_wptr += nn; @@ -204,10 +199,10 @@ soread(so) sb->sb_wptr -= sb->sb_datalen; return nn; } - + /* * Get urgent data - * + * * When the socket is created, we set it SO_OOBINLINE, * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data @@ -220,13 +215,13 @@ sorecvoob(so) DEBUG_CALL("sorecvoob"); DEBUG_ARG("so = %lx", (long)so); - + /* * We take a guess at how much urgent data has arrived. * In most situations, when urgent data arrives, the next * read() should get all the urgent data. This guess will * be wrong however if more data arrives just after the - * urgent data, or the read() doesn't return all the + * urgent data, or the read() doesn't return all the * urgent data. */ soread(so); @@ -246,24 +241,24 @@ sosendoob(so) { struct sbuf *sb = &so->so_rcv; char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ - + int n, len; - + DEBUG_CALL("sosendoob"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); - + if (so->so_urgc > 2048) so->so_urgc = 2048; /* XXXX */ - + if (sb->sb_rptr < sb->sb_wptr) { /* We can send it directly */ n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ so->so_urgc -= n; - + DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); } else { - /* + /* * Since there's no sendv or sendtov like writev, * we must copy all data to a linear buffer then * send it all @@ -283,20 +278,20 @@ sosendoob(so) #ifdef DEBUG if (n != len) DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); -#endif +#endif DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); } - + sb->sb_cc -= n; sb->sb_rptr += n; if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) sb->sb_rptr -= sb->sb_datalen; - + return n; } /* - * Write data from so_rcv to so's socket, + * Write data from so_rcv to so's socket, * updating all sbuf field as necessary */ int @@ -305,12 +300,12 @@ sowrite(so) { int n,nn; struct sbuf *sb = &so->so_rcv; - u_int len = sb->sb_cc; + int len = sb->sb_cc; struct iovec iov[2]; - + DEBUG_CALL("sowrite"); DEBUG_ARG("so = %lx", (long)so); - + if (so->so_urgc) { sosendoob(so); if (sb->sb_cc == 0) @@ -321,9 +316,9 @@ sowrite(so) * No need to check if there's something to write, * sowrite wouldn't have been called otherwise */ - + len = sb->sb_cc; - + iov[0].iov_base = sb->sb_rptr; if (sb->sb_rptr < sb->sb_wptr) { iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; @@ -346,17 +341,14 @@ sowrite(so) #ifdef HAVE_READV nn = writev(so->s, (const struct iovec *)iov, n); - + DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); #else nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); #endif /* This should never happen, but people tell me it does *shrug* */ - if (nn < 0) { - int error = WSAGetLastError(); - if (IS_EAGAIN(error)) - return 0; - } + if (nn < 0 && (errno == EAGAIN || errno == EINTR)) + return 0; if (nn <= 0) { DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", @@ -365,7 +357,7 @@ sowrite(so) tcp_sockclosed(sototcpcb(so)); return -1; } - + #ifndef HAVE_READV if (n == 2 && nn == iov[0].iov_len) { int ret; @@ -375,20 +367,20 @@ sowrite(so) } DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); #endif - + /* Update sbuf */ sb->sb_cc -= nn; sb->sb_rptr += nn; if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) sb->sb_rptr -= sb->sb_datalen; - + /* * If in DRAIN mode, and there's no more data, set * it CANTSENDMORE */ if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) sofcantsendmore(so); - + return nn; } @@ -400,26 +392,25 @@ sorecvfrom(so) struct socket *so; { struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); - + int addrlen = sizeof(struct sockaddr_in); + DEBUG_CALL("sorecvfrom"); DEBUG_ARG("so = %lx", (long)so); - + if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ char buff[256]; int len; - - len = recvfrom(so->s, buff, 256, 0, + + len = recvfrom(so->s, buff, 256, 0, (struct sockaddr *)&addr, &addrlen); /* XXX Check if reply is "correct"? */ - + if(len == -1 || len == 0) { u_char code=ICMP_UNREACH_PORT; - int error = WSAGetLastError(); - if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET; - + if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; + else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; + DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", errno,strerror(errno))); icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); @@ -431,38 +422,36 @@ sorecvfrom(so) udp_detach(so); } else { /* A "normal" UDP packet */ struct mbuf *m; - u_int len; - ioctlsockopt_t n; + int len, n; if (!(m = m_get())) return; - m->m_data += if_maxlinkhdr; - - /* + m->m_data += IF_MAXLINKHDR; + + /* * XXX Shouldn't FIONREAD packets destined for port 53, * but I don't know the max packet size for DNS lookups */ len = M_FREEROOM(m); /* if (so->so_fport != htons(53)) { */ ioctlsocket(so->s, FIONREAD, &n); - + if (n > len) { n = (m->m_data - m->m_dat) + m->m_len + n + 1; m_inc(m, n); len = M_FREEROOM(m); } /* } */ - + m->m_len = recvfrom(so->s, m->m_data, len, 0, (struct sockaddr *)&addr, &addrlen); - DEBUG_MISC((dfd, " did recvfrom %zu, errno = %d-%s\n", + DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", m->m_len, errno,strerror(errno))); if(m->m_len<0) { u_char code=ICMP_UNREACH_PORT; - int error = WSAGetLastError(); - if(error == WSAEHOSTUNREACH) code=ICMP_UNREACH_HOST; - else if(error == WSAENETUNREACH) code=ICMP_UNREACH_NET; - + if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; + else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; + DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); m_free(m); @@ -485,8 +474,8 @@ sorecvfrom(so) * m->m_len = 0; * } */ - - /* + + /* * If this packet was destined for CTL_ADDR, * make it look like that's where it came from, done by udp_output */ @@ -509,7 +498,7 @@ sosendto(so, m) DEBUG_CALL("sosendto"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); - + addr.sin_family = AF_INET; if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { /* It's an alias */ @@ -526,16 +515,14 @@ sosendto(so, m) addr.sin_addr = so->so_faddr; addr.sin_port = so->so_fport; - char addrstr[INET_ADDRSTRLEN]; - DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", - ntohs(addr.sin_port), inet_ntop(AF_INET, &addr.sin_addr, addrstr, sizeof(addrstr)))); - + DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); + /* Don't care what port we get */ ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, sizeof (struct sockaddr)); if (ret < 0) return -1; - + /* * Kill the socket if there's no reply in 4 minutes, * but only if it's an expirable socket @@ -558,57 +545,58 @@ solisten(port, laddr, lport, flags) { struct sockaddr_in addr; struct socket *so; - int s; - socklen_t addrlen = sizeof(addr); - int opt = 1; + int s, addrlen = sizeof(addr), opt = 1; DEBUG_CALL("solisten"); DEBUG_ARG("port = %d", port); DEBUG_ARG("laddr = %x", laddr); DEBUG_ARG("lport = %d", lport); DEBUG_ARG("flags = %x", flags); - + if ((so = socreate()) == NULL) { /* free(so); Not sofree() ??? free(NULL) == NOP */ return NULL; } - + /* Don't tcp_attach... we don't need so_snd nor so_rcv */ if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { free(so); return NULL; } insque(so,&tcb); - - /* + + /* * SS_FACCEPTONCE sockets must time out. */ if (flags & SS_FACCEPTONCE) so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; - + so->so_state = (SS_FACCEPTCONN|flags); so->so_lport = lport; /* Kept in network format */ so->so_laddr.s_addr = laddr; /* Ditto */ - - memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; - + if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || (listen(s,1) < 0)) { - int error = WSAGetLastError(); /* Don't clobber the real reason we failed */ - + int tmperrno = errno; /* Don't clobber the real reason we failed */ + close(s); sofree(so); /* Restore the real errno */ - WSASetLastError(error); +#ifdef _WIN32 + WSASetLastError(tmperrno); +#else + errno = tmperrno; +#endif return NULL; } setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); - + getsockname(s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) @@ -620,30 +608,32 @@ solisten(port, laddr, lport, flags) return so; } -/* +#if 0 +/* * Data is available in so_rcv * Just write() the data to the socket * XXX not yet... */ -void +static void sorwakeup(so) struct socket *so; { /* sowrite(so); */ /* FD_CLR(so->s,&writefds); */ } - + /* * Data has been freed in so_snd * We have room for a read() if we want to * For now, don't read, it'll be done in the main loop */ -void +static void sowwakeup(so) struct socket *so; { /* Nothing, yet */ } +#endif /* * Various session state calls @@ -668,9 +658,8 @@ soisfconnected(so) so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ } -void -sofcantrcvmore(so) - struct socket *so; +static void +sofcantrcvmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,0); @@ -685,9 +674,8 @@ sofcantrcvmore(so) so->so_state |= SS_FCANTRCVMORE; } -void -sofcantsendmore(so) - struct socket *so; +static void +sofcantsendmore(struct socket *so) { if ((so->so_state & SS_NOFDREF) == 0) { shutdown(so->s,1); /* send FIN to fhost */ diff --git a/BasiliskII/src/slirp/socket.h b/BasiliskII/src/slirp/socket.h index 3b0fee16..94fb8d8c 100644 --- a/BasiliskII/src/slirp/socket.h +++ b/BasiliskII/src/slirp/socket.h @@ -1,7 +1,7 @@ /* * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -33,21 +33,21 @@ struct socket { struct in_addr so_laddr; /* local host table entry */ u_int16_t so_fport; /* foreign port */ u_int16_t so_lport; /* local port */ - + u_int8_t so_iptos; /* Type of service */ u_int8_t so_emu; /* Is the socket emulated? */ - + u_char so_type; /* Type of socket, UDP or TCP */ int so_state; /* internal state flags SS_*, below */ - + struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ u_int so_expire; /* When the socket will expire */ - + int so_queued; /* Number of packets queued from this socket */ int so_nqueued; /* Number of packets queued in a row * Used to determine when to "downgrade" a session * from fastq to batchq */ - + struct sbuf so_rcv; /* Receive buffer */ struct sbuf so_snd; /* Send buffer */ void * extra; /* Extra pointer */ @@ -81,24 +81,19 @@ struct iovec { }; #endif -void so_init(void); -struct socket * solookup(struct socket *, struct in_addr, u_int, struct in_addr, u_int); -struct socket * socreate(void); -void sofree(struct socket *); -int soread(struct socket *); -void sorecvoob(struct socket *); -int sosendoob(struct socket *); -int sowrite(struct socket *); -void sorecvfrom(struct socket *); -int sosendto(struct socket *, struct mbuf *); -struct socket * solisten(u_int, u_int32_t, u_int, int); -void sorwakeup(struct socket *); -void sowwakeup(struct socket *); -void soisfconnecting(register struct socket *); -void soisfconnected(register struct socket *); -void sofcantrcvmore(struct socket *); -void sofcantsendmore(struct socket *); -void soisfdisconnected(struct socket *); -void sofwdrain(struct socket *); +struct socket * solookup _P((struct socket *, struct in_addr, u_int, struct in_addr, u_int)); +struct socket * socreate _P((void)); +void sofree _P((struct socket *)); +int soread _P((struct socket *)); +void sorecvoob _P((struct socket *)); +int sosendoob _P((struct socket *)); +int sowrite _P((struct socket *)); +void sorecvfrom _P((struct socket *)); +int sosendto _P((struct socket *, struct mbuf *)); +struct socket * solisten _P((u_int, u_int32_t, u_int, int)); +void soisfconnecting _P((register struct socket *)); +void soisfconnected _P((register struct socket *)); +void soisfdisconnected _P((struct socket *)); +void sofwdrain _P((struct socket *)); #endif /* _SOCKET_H_ */ diff --git a/BasiliskII/src/slirp/tcp.h b/BasiliskII/src/slirp/tcp.h index 24e7914a..11150766 100644 --- a/BasiliskII/src/slirp/tcp.h +++ b/BasiliskII/src/slirp/tcp.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,8 +42,6 @@ typedef u_int32_t tcp_seq; #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -extern size_t tcp_rcvspace; -extern size_t tcp_sndspace; extern struct socket *tcp_last_so; #define TCP_SNDSPACE 8192 @@ -49,20 +51,16 @@ extern struct socket *tcp_last_so; * TCP header. * Per RFC 793, September, 1981. */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct tcphdr { u_int16_t th_sport; /* source port */ u_int16_t th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #ifdef WORDS_BIGENDIAN - u_char th_off:4, /* data offset */ + u_int th_off:4, /* data offset */ th_x2:4; /* (unused) */ #else - u_char th_x2:4, /* (unused) */ + u_int th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif u_int8_t th_flags; @@ -75,11 +73,7 @@ struct tcphdr { u_int16_t th_win; /* window */ u_int16_t th_sum; /* checksum */ u_int16_t th_urp; /* urgent pointer */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; #include "tcp_var.h" @@ -176,6 +170,6 @@ struct tcphdr { extern tcp_seq tcp_iss; /* tcp initial send seq # */ -extern char *tcpstates[]; +extern const char * const tcpstates[]; #endif diff --git a/BasiliskII/src/slirp/tcp_input.c b/BasiliskII/src/slirp/tcp_input.c index 5c06f16f..17a9387f 100644 --- a/BasiliskII/src/slirp/tcp_input.c +++ b/BasiliskII/src/slirp/tcp_input.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,18 +37,17 @@ /* * 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 #include #include "ip_icmp.h" struct socket tcb; -int tcprexmtthresh = 3; +#define TCPREXMTTHRESH 3 struct socket *tcp_last_so = &tcb; tcp_seq tcp_iss; /* tcp initial send seq # */ @@ -76,8 +79,8 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ if (tcp_emu((so),(m))) sbappend((so), (m)); \ } else \ @@ -96,8 +99,8 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ tp->t_flags |= TF_DELACK; \ (tp)->rcv_nxt += (ti)->ti_len; \ flags = (ti)->ti_flags & TH_FIN; \ - tcpstat.tcps_rcvpack++;\ - tcpstat.tcps_rcvbyte += (ti)->ti_len;\ + STAT(tcpstat.tcps_rcvpack++); \ + STAT(tcpstat.tcps_rcvbyte += (ti)->ti_len); \ if (so->so_emu) { \ if (tcp_emu((so),(m))) sbappend(so, (m)); \ } else \ @@ -109,14 +112,18 @@ tcp_seq tcp_iss; /* tcp initial send seq # */ } \ } #endif +static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, + struct tcpiphdr *ti); +static void tcp_xmit_timer(register struct tcpcb *tp, int rtt); -int -tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf *m) +static int +tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, + struct mbuf *m) { register struct tcpiphdr *q; struct socket *so = tp->t_socket; int flags; - + /* * Call with ti==0 after become established to * force pre-ESTABLISHED data up to user socket. @@ -144,8 +151,8 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf * i = q->ti_seq + q->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += ti->ti_len; + STAT(tcpstat.tcps_rcvduppack++); + STAT(tcpstat.tcps_rcvdupbyte += ti->ti_len); m_freem(m); /* * Try to present any queued data @@ -161,8 +168,8 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, struct mbuf * } q = (struct tcpiphdr *)(q->ti_next); } - tcpstat.tcps_rcvoopack++; - tcpstat.tcps_rcvoobyte += ti->ti_len; + STAT(tcpstat.tcps_rcvoopack++); + STAT(tcpstat.tcps_rcvoobyte += ti->ti_len); REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ /* @@ -226,9 +233,13 @@ present: * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ -void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) +void +tcp_input(m, iphlen, inso) + register struct mbuf *m; + int iphlen; + struct socket *inso; { - struct ip save_ip, *ip; + struct ip save_ip, *ip; register struct tcpiphdr *ti; caddr_t optp = NULL; int optlen = 0; @@ -236,18 +247,16 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) register struct tcpcb *tp = 0; register int tiflags; struct socket *so = 0; - int todrop; - u_int acked; - int ourfinisacked, needoutput = 0; - /* int dropsocket = 0; */ + int todrop, acked, ourfinisacked, needoutput = 0; +/* int dropsocket = 0; */ int iss = 0; u_long tiwin; int ret; - /* int ts_present = 0; */ +/* int ts_present = 0; */ DEBUG_CALL("tcp_input"); - DEBUG_ARGS((dfd, " m = %8lx iphlen = %2d inso = %lx\n", - (long)m, iphlen, (long)inso)); + DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", + (long )m, iphlen, (long )inso )); /* * If called with m == 0, then we're continuing the connect @@ -267,15 +276,15 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) } - tcpstat.tcps_rcvtotal++; + STAT(tcpstat.tcps_rcvtotal++); /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. */ ti = mtod(m, struct tcpiphdr *); - if (iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); + if (iphlen > sizeof(struct ip )) { + ip_stripoptions(m, (struct mbuf *)0); + iphlen=sizeof(struct ip ); } /* XXX Check if too short */ @@ -284,28 +293,24 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) * Save a copy of the IP header in case we want restore it * for sending an ICMP error message in response. */ - ip = mtod(m, struct ip *); + ip=mtod(m, struct ip *); save_ip = *ip; - save_ip.ip_len += iphlen; + save_ip.ip_len+= iphlen; /* * Checksum extended TCP header and data. */ tlen = ((struct ip *)ti)->ip_len; - //ti->ti_next = ti->ti_prev = 0; - - tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0; - memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - + ti->ti_next = ti->ti_prev = 0; ti->ti_x1 = 0; ti->ti_len = htons((u_int16_t)tlen); - len = sizeof(struct ip) + tlen; + len = sizeof(struct ip ) + tlen; /* keep checksum for ICMP reply * ti->ti_sum = cksum(m, len); * if (ti->ti_sum) { */ - if (cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; - goto drop; + if(cksum(m, len)) { + STAT(tcpstat.tcps_rcvbadsum++); + goto drop; } /* @@ -313,15 +318,15 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) * pull out TCP options and adjust length. XXX */ off = ti->ti_off << 2; - if (off < sizeof(struct tcphdr) || off > tlen) { - tcpstat.tcps_rcvbadoff++; - goto drop; + if (off < sizeof (struct tcphdr) || off > tlen) { + STAT(tcpstat.tcps_rcvbadoff++); + goto drop; } tlen -= off; ti->ti_len = tlen; - if (off > sizeof(struct tcphdr)) { - optlen = off - sizeof(struct tcphdr); - optp = mtod(m, caddr_t) + sizeof(struct tcpiphdr); + if (off > sizeof (struct tcphdr)) { + optlen = off - sizeof (struct tcphdr); + optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); /* * Do quick retrieval of timestamp options ("options @@ -330,17 +335,17 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) * quickly get the values now and not bother calling * tcp_dooptions(), etc. */ - /* if ((optlen == TCPOLEN_TSTAMP_APPA || - * (optlen > TCPOLEN_TSTAMP_APPA && - * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && - * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && - * (ti->ti_flags & TH_SYN) == 0) { - * ts_present = 1; - * ts_val = ntohl(*(u_int32_t *)(optp + 4)); - * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); - * optp = NULL; / * we've parsed the options * / - * } - */ +/* if ((optlen == TCPOLEN_TSTAMP_APPA || + * (optlen > TCPOLEN_TSTAMP_APPA && + * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && + * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && + * (ti->ti_flags & TH_SYN) == 0) { + * ts_present = 1; + * ts_val = ntohl(*(u_int32_t *)(optp + 4)); + * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); + * optp = NULL; / * we've parsed the options * / + * } + */ } tiflags = ti->ti_flags; @@ -355,8 +360,8 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) /* * Drop TCP, IP headers and TCP options. */ - m->m_data += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); + m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); + m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); /* * Locate pcb for segment. @@ -364,14 +369,14 @@ void tcp_input(register struct mbuf *m, int iphlen, struct socket *inso) findso: so = tcp_last_so; if (so->so_fport != ti->ti_dport || - so->so_lport != ti->ti_sport || - so->so_laddr.s_addr != ti->ti_src.s_addr || - so->so_faddr.s_addr != ti->ti_dst.s_addr) { + so->so_lport != ti->ti_sport || + so->so_laddr.s_addr != ti->ti_src.s_addr || + so->so_faddr.s_addr != ti->ti_dst.s_addr) { so = solookup(&tcb, ti->ti_src, ti->ti_sport, - ti->ti_dst, ti->ti_dport); + ti->ti_dst, ti->ti_dport); if (so) tcp_last_so = so; - ++tcpstat.tcps_socachemiss; + STAT(tcpstat.tcps_socachemiss++); } /* @@ -388,41 +393,41 @@ findso: * as if it was LISTENING, and continue... */ if (so == 0) { - if ((tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) != TH_SYN) - goto dropwithreset; + if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) + goto dropwithreset; - if ((so = socreate()) == NULL) - goto dropwithreset; - if (tcp_attach(so) < 0) { - free(so); /* Not sofree (if it failed, it's not insqued) */ - goto dropwithreset; - } + if ((so = socreate()) == NULL) + goto dropwithreset; + if (tcp_attach(so) < 0) { + free(so); /* Not sofree (if it failed, it's not insqued) */ + goto dropwithreset; + } - sbreserve(&so->so_snd, tcp_sndspace); - sbreserve(&so->so_rcv, tcp_rcvspace); + sbreserve(&so->so_snd, TCP_SNDSPACE); + sbreserve(&so->so_rcv, TCP_RCVSPACE); - /* tcp_last_so = so; */ /* XXX ? */ - /* tp = sototcpcb(so); */ + /* tcp_last_so = so; */ /* XXX ? */ + /* tp = sototcpcb(so); */ - so->so_laddr = ti->ti_src; - so->so_lport = ti->ti_sport; - so->so_faddr = ti->ti_dst; - so->so_fport = ti->ti_dport; + so->so_laddr = ti->ti_src; + so->so_lport = ti->ti_sport; + so->so_faddr = ti->ti_dst; + so->so_fport = ti->ti_dport; - if ((so->so_iptos = tcp_tos(so)) == 0) - so->so_iptos = ((struct ip *)ti)->ip_tos; + if ((so->so_iptos = tcp_tos(so)) == 0) + so->so_iptos = ((struct ip *)ti)->ip_tos; - tp = sototcpcb(so); - tp->t_state = TCPS_LISTEN; + tp = sototcpcb(so); + tp->t_state = TCPS_LISTEN; } - /* - * If this is a still-connecting socket, this probably - * a retransmit of the SYN. Whether it's a retransmit SYN - * or something else, we nuke it. - */ - if (so->so_state & SS_ISFCONNECTING) - goto drop; + /* + * If this is a still-connecting socket, this probably + * a retransmit of the SYN. Whether it's a retransmit SYN + * or something else, we nuke it. + */ + if (so->so_state & SS_ISFCONNECTING) + goto drop; tp = sototcpcb(so); @@ -437,17 +442,17 @@ findso: * tiwin = ti->ti_win << tp->snd_scale; * else */ - tiwin = ti->ti_win; + tiwin = ti->ti_win; /* * Segment received on connection. * Reset idle time and keep-alive timer. */ tp->t_idle = 0; - if (so_options) - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + if (SO_OPTIONS) + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; /* * Process options if not in LISTEN state, @@ -455,60 +460,60 @@ findso: */ if (optp && tp->t_state != TCPS_LISTEN) tcp_dooptions(tp, (u_char *)optp, optlen, ti); - /* , */ - /* &ts_present, &ts_val, &ts_ecr); */ +/* , */ +/* &ts_present, &ts_val, &ts_ecr); */ - /* - * Header prediction: check for the two common cases - * of a uni-directional data xfer. If the packet has - * no control flags, is in-sequence, the window didn't - * change and we're not retransmitting, it's a - * candidate. If the length is zero and the ack moved - * forward, we're the sender side of the xfer. Just - * free the data acked & wake any higher level process - * that was blocked waiting for space. If the length - * is non-zero and the ack didn't move, we're the - * receiver side. If we're getting packets in-order - * (the reassembly queue is empty), add the data to - * the socket buffer and note that we need a delayed ack. - * - * XXX Some of these tests are not needed - * eg: the tiwin == tp->snd_wnd prevents many more - * predictions.. with no *real* advantage.. - */ + /* + * Header prediction: check for the two common cases + * of a uni-directional data xfer. If the packet has + * no control flags, is in-sequence, the window didn't + * change and we're not retransmitting, it's a + * candidate. If the length is zero and the ack moved + * forward, we're the sender side of the xfer. Just + * free the data acked & wake any higher level process + * that was blocked waiting for space. If the length + * is non-zero and the ack didn't move, we're the + * receiver side. If we're getting packets in-order + * (the reassembly queue is empty), add the data to + * the socket buffer and note that we need a delayed ack. + * + * XXX Some of these tests are not needed + * eg: the tiwin == tp->snd_wnd prevents many more + * predictions.. with no *real* advantage.. + */ if (tp->t_state == TCPS_ESTABLISHED && - (tiflags & (TH_SYN | TH_FIN | TH_RST | TH_URG | TH_ACK)) == TH_ACK && - /* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ - ti->ti_seq == tp->rcv_nxt && - tiwin && tiwin == tp->snd_wnd && - tp->snd_nxt == tp->snd_max) { + (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && +/* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ + ti->ti_seq == tp->rcv_nxt && + tiwin && tiwin == tp->snd_wnd && + tp->snd_nxt == tp->snd_max) { /* * If last ACK falls within this segment's sequence numbers, * record the timestamp. */ - /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && - * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { - * tp->ts_recent_age = tcp_now; - * tp->ts_recent = ts_val; - * } - */ +/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && + * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { + * tp->ts_recent_age = tcp_now; + * tp->ts_recent = ts_val; + * } + */ if (ti->ti_len == 0) { if (SEQ_GT(ti->ti_ack, tp->snd_una) && - SEQ_LEQ(ti->ti_ack, tp->snd_max) && - tp->snd_cwnd >= tp->snd_wnd) { + SEQ_LEQ(ti->ti_ack, tp->snd_max) && + tp->snd_cwnd >= tp->snd_wnd) { /* * this is a pure ack for outstanding data. */ - ++tcpstat.tcps_predack; - /* if (ts_present) - * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); - * else - */ if (tp->t_rtt && -SEQ_GT(ti->ti_ack, tp->t_rtseq)) + STAT(tcpstat.tcps_predack++); +/* if (ts_present) + * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); + * else + */ if (tp->t_rtt && + SEQ_GT(ti->ti_ack, tp->t_rtseq)) tcp_xmit_timer(tp, tp->t_rtt); acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(tcpstat.tcps_rcvackpack++); + STAT(tcpstat.tcps_rcvackbyte += acked); sbdrop(&so->so_snd, acked); tp->snd_una = ti->ti_ack; m_freem(m); @@ -531,39 +536,37 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * There's room in so_snd, sowwakup will read() * from the socket if we can */ - /* if (so->so_snd.sb_flags & SB_NOTIFY) - * sowwakeup(so); - */ - /* - * This is called because sowwakeup might have - * put data into so_snd. Since we don't so sowwakeup, - * we don't need this.. XXX??? - */ +/* if (so->so_snd.sb_flags & SB_NOTIFY) + * sowwakeup(so); + */ + /* + * This is called because sowwakeup might have + * put data into so_snd. Since we don't so sowwakeup, + * we don't need this.. XXX??? + */ if (so->so_snd.sb_cc) (void) tcp_output(tp); return; } - } - else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (tcpiphdrp_32)tp && - ti->ti_len <= sbspace(&so->so_rcv)) { + } else if (ti->ti_ack == tp->snd_una && + tp->seg_next == (tcpiphdrp_32)tp && + ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet * with nothing on the reassembly queue and * we have enough buffer space to take it. */ - ++tcpstat.tcps_preddat; + STAT(tcpstat.tcps_preddat++); tp->rcv_nxt += ti->ti_len; - tcpstat.tcps_rcvpack++; - tcpstat.tcps_rcvbyte += ti->ti_len; + STAT(tcpstat.tcps_rcvpack++); + STAT(tcpstat.tcps_rcvbyte += ti->ti_len); /* * Add data to socket buffer. */ if (so->so_emu) { - if (tcp_emu(so, m)) sbappend(so, m); - } - else + if (tcp_emu(so,m)) sbappend(so, m); + } else sbappend(so, m); /* @@ -571,16 +574,16 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * if we can actually write() to the socket * XXX Need to check? It's be NON_BLOCKING */ - /* sorwakeup(so); */ +/* sorwakeup(so); */ - /* - * If this is a short packet, then ACK now - with Nagel - * congestion avoidance sender won't send more until - * he gets an ACK. - * - * It is better to not delay acks at all to maximize - * TCP throughput. See RFC 2581. - */ + /* + * If this is a short packet, then ACK now - with Nagel + * congestion avoidance sender won't send more until + * he gets an ACK. + * + * It is better to not delay acks at all to maximize + * TCP throughput. See RFC 2581. + */ tp->t_flags |= TF_ACKNOW; tcp_output(tp); return; @@ -593,145 +596,139 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * but not less than advertised window. */ { int win; - win = sbspace(&so->so_rcv); - if (win < 0) - win = 0; - tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); + win = sbspace(&so->so_rcv); + if (win < 0) + win = 0; + tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); } switch (tp->t_state) { - /* - * If the state is LISTEN then ignore segment if it contains an RST. - * If the segment contains an ACK then it is bad and send a RST. - * If it does not contain a SYN then it is not interesting; drop it. - * Don't bother responding if the destination was a broadcast. - * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial - * tp->iss, and send a segment: - * - * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. - * Fill in remote peer address fields if not previously specified. - * Enter SYN_RECEIVED state, and process any other fields of this - * segment in this state. - */ + /* + * If the state is LISTEN then ignore segment if it contains an RST. + * If the segment contains an ACK then it is bad and send a RST. + * If it does not contain a SYN then it is not interesting; drop it. + * Don't bother responding if the destination was a broadcast. + * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial + * tp->iss, and send a segment: + * + * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. + * Fill in remote peer address fields if not previously specified. + * Enter SYN_RECEIVED state, and process any other fields of this + * segment in this state. + */ case TCPS_LISTEN: { - if (tiflags & TH_RST) - goto drop; - if (tiflags & TH_ACK) - goto dropwithreset; - if ((tiflags & TH_SYN) == 0) - goto drop; + if (tiflags & TH_RST) + goto drop; + if (tiflags & TH_ACK) + goto dropwithreset; + if ((tiflags & TH_SYN) == 0) + goto drop; - /* - * This has way too many gotos... - * But a bit of spaghetti code never hurt anybody :) - */ + /* + * This has way too many gotos... + * But a bit of spaghetti code never hurt anybody :) + */ - /* - * If this is destined for the control address, then flag to - * tcp_ctl once connected, otherwise connect - */ - if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { - int lastbyte = ntohl(so->so_faddr.s_addr) & 0xff; - if (lastbyte != CTL_ALIAS && lastbyte != CTL_DNS) { + /* + * If this is destined for the control address, then flag to + * tcp_ctl once connected, otherwise connect + */ + if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { + int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff; + if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) { #if 0 - if (lastbyte == CTL_CMD || lastbyte == CTL_EXEC) { - /* Command or exec adress */ - so->so_state |= SS_CTL; - } - else + if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) { + /* Command or exec adress */ + so->so_state |= SS_CTL; + } else #endif - { - /* May be an add exec */ - struct ex_list *ex_ptr; - for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { - if (ex_ptr->ex_fport == so->so_fport && - lastbyte == ex_ptr->ex_addr) { - so->so_state |= SS_CTL; - break; - } - } - } - if (so->so_state & SS_CTL) goto cont_input; - } - /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ + { + /* May be an add exec */ + struct ex_list *ex_ptr; + for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { + if(ex_ptr->ex_fport == so->so_fport && + lastbyte == ex_ptr->ex_addr) { + so->so_state |= SS_CTL; + break; + } } + } + if(so->so_state & SS_CTL) goto cont_input; + } + /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ + } - if (so->so_emu & EMU_NOCONNECT) { - so->so_emu &= ~EMU_NOCONNECT; - goto cont_input; - } + if (so->so_emu & EMU_NOCONNECT) { + so->so_emu &= ~EMU_NOCONNECT; + goto cont_input; + } - if (tcp_fconnect(so) == -1) { - int error = WSAGetLastError(); - if ((error != WSAEINPROGRESS) && (error != WSAEWOULDBLOCK)) { - u_char code = ICMP_UNREACH_NET; - DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n", - errno, strerror(errno))); - if (error == WSAECONNREFUSED) { - /* ACK the SYN, send RST to refuse the connection */ - tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq)0, - TH_RST | TH_ACK); - } - else { - if (error == WSAEHOSTUNREACH) code = ICMP_UNREACH_HOST; - HTONL(ti->ti_seq); /* restore tcp header */ - HTONL(ti->ti_ack); - HTONS(ti->ti_win); - HTONS(ti->ti_urp); - m->m_data -= sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - m->m_len += sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr); - *ip = save_ip; - icmp_error(m, ICMP_UNREACH, code, 0, strerror(errno)); - } - tp = tcp_close(tp); - m_free(m); - return; - } - } - - /* - * Haven't connected yet, save the current mbuf - * and ti, and return - * XXX Some OS's don't tell us whether the connect() - * succeeded or not. So we must time it out. - */ - so->so_m = m; - so->so_ti = ti; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->t_state = TCPS_SYN_RECEIVED; - return; + if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + u_char code=ICMP_UNREACH_NET; + DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", + errno,strerror(errno))); + if(errno == ECONNREFUSED) { + /* ACK the SYN, send RST to refuse the connection */ + tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, + TH_RST|TH_ACK); + } else { + if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; + HTONL(ti->ti_seq); /* restore tcp header */ + HTONL(ti->ti_ack); + HTONS(ti->ti_win); + HTONS(ti->ti_urp); + m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); + m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); + *ip=save_ip; + icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno)); + } + tp = tcp_close(tp); + m_free(m); + } else { + /* + * Haven't connected yet, save the current mbuf + * and ti, and return + * XXX Some OS's don't tell us whether the connect() + * succeeded or not. So we must time it out. + */ + so->so_m = m; + so->so_ti = ti; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; + tp->t_state = TCPS_SYN_RECEIVED; + } + return; cont_conn: - /* m==NULL - * Check if the connect succeeded - */ - if (so->so_state & SS_NOFDREF) { - tp = tcp_close(tp); - goto dropwithreset; - } + /* m==NULL + * Check if the connect succeeded + */ + if (so->so_state & SS_NOFDREF) { + tp = tcp_close(tp); + goto dropwithreset; + } cont_input: - tcp_template(tp); + tcp_template(tp); - if (optp) - tcp_dooptions(tp, (u_char *)optp, optlen, ti); - /* , */ - /* &ts_present, &ts_val, &ts_ecr); */ + if (optp) + tcp_dooptions(tp, (u_char *)optp, optlen, ti); + /* , */ + /* &ts_present, &ts_val, &ts_ecr); */ - if (iss) - tp->iss = iss; - else - tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR / 2; - tp->irs = ti->ti_seq; - tcp_sendseqinit(tp); - tcp_rcvseqinit(tp); - tp->t_flags |= TF_ACKNOW; - tp->t_state = TCPS_SYN_RECEIVED; - tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tcpstat.tcps_accepts++; - goto trimthenstep6; + if (iss) + tp->iss = iss; + else + tp->iss = tcp_iss; + tcp_iss += TCP_ISSINCR/2; + tp->irs = ti->ti_seq; + tcp_sendseqinit(tp); + tcp_rcvseqinit(tp); + tp->t_flags |= TF_ACKNOW; + tp->t_state = TCPS_SYN_RECEIVED; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; + STAT(tcpstat.tcps_accepts++); + goto trimthenstep6; } /* case TCPS_LISTEN */ /* @@ -748,13 +745,13 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) */ case TCPS_SYN_SENT: if ((tiflags & TH_ACK) && - (SEQ_LEQ(ti->ti_ack, tp->iss) || - SEQ_GT(ti->ti_ack, tp->snd_max))) + (SEQ_LEQ(ti->ti_ack, tp->iss) || + SEQ_GT(ti->ti_ack, tp->snd_max))) goto dropwithreset; if (tiflags & TH_RST) { if (tiflags & TH_ACK) - tp = tcp_drop(tp, 0); /* XXX Check t_softerror! */ + tp = tcp_drop(tp,0); /* XXX Check t_softerror! */ goto drop; } @@ -771,7 +768,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) tcp_rcvseqinit(tp); tp->t_flags |= TF_ACKNOW; if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { - tcpstat.tcps_connects++; + STAT(tcpstat.tcps_connects++); soisfconnected(so); tp->t_state = TCPS_ESTABLISHED; @@ -782,7 +779,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * tp->rcv_scale = tp->request_r_scale; * } */ - (void)tcp_reass(tp, (struct tcpiphdr *)0, + (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); /* * if we didn't have to retransmit the SYN, @@ -790,11 +787,10 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) */ if (tp->t_rtt) tcp_xmit_timer(tp, tp->t_rtt); - } - else + } else tp->t_state = TCPS_SYN_RECEIVED; - trimthenstep6: +trimthenstep6: /* * Advance ti->ti_seq to correspond to first data byte. * If data, trim to stay within window, @@ -806,8 +802,8 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) m_adj(m, -todrop); ti->ti_len = tp->rcv_wnd; tiflags &= ~TH_FIN; - tcpstat.tcps_rcvpackafterwin++; - tcpstat.tcps_rcvbyteafterwin += todrop; + STAT(tcpstat.tcps_rcvpackafterwin++); + STAT(tcpstat.tcps_rcvbyteafterwin += todrop); } tp->snd_wl1 = ti->ti_seq - 1; tp->rcv_up = ti->ti_seq; @@ -823,31 +819,31 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * RFC 1323 PAWS: If we have a timestamp reply on this segment * and it's less than ts_recent, drop it. */ - /* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && - * TSTMP_LT(ts_val, tp->ts_recent)) { - * - */ /* Check to see if ts_recent is over 24 days old. */ - /* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { - */ /* - * * Invalidate ts_recent. If this segment updates - * * ts_recent, the age will be reset later and ts_recent - * * will get a valid value. If it does not, setting - * * ts_recent to zero will at least satisfy the - * * requirement that zero be placed in the timestamp - * * echo reply when ts_recent isn't valid. The - * * age isn't reset until we get a valid ts_recent - * * because we don't want out-of-order segments to be - * * dropped when ts_recent is old. - * */ - /* tp->ts_recent = 0; - * } else { - * tcpstat.tcps_rcvduppack++; - * tcpstat.tcps_rcvdupbyte += ti->ti_len; - * tcpstat.tcps_pawsdrop++; - * goto dropafterack; - * } - * } - */ +/* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && + * TSTMP_LT(ts_val, tp->ts_recent)) { + * + */ /* Check to see if ts_recent is over 24 days old. */ +/* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { + */ /* + * * Invalidate ts_recent. If this segment updates + * * ts_recent, the age will be reset later and ts_recent + * * will get a valid value. If it does not, setting + * * ts_recent to zero will at least satisfy the + * * requirement that zero be placed in the timestamp + * * echo reply when ts_recent isn't valid. The + * * age isn't reset until we get a valid ts_recent + * * because we don't want out-of-order segments to be + * * dropped when ts_recent is old. + * */ +/* tp->ts_recent = 0; + * } else { + * tcpstat.tcps_rcvduppack++; + * tcpstat.tcps_rcvdupbyte += ti->ti_len; + * tcpstat.tcps_pawsdrop++; + * goto dropafterack; + * } + * } + */ todrop = tp->rcv_nxt - ti->ti_seq; if (todrop > 0) { @@ -864,7 +860,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * Following if statement from Stevens, vol. 2, p. 960. */ if (todrop > ti->ti_len - || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { + || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { /* * Any valid FIN must be to the left of the window. * At this point the FIN must be a duplicate or out @@ -878,12 +874,11 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) */ tp->t_flags |= TF_ACKNOW; todrop = ti->ti_len; - tcpstat.tcps_rcvduppack++; - tcpstat.tcps_rcvdupbyte += todrop; - } - else { - tcpstat.tcps_rcvpartduppack++; - tcpstat.tcps_rcvpartdupbyte += todrop; + STAT(tcpstat.tcps_rcvduppack++); + STAT(tcpstat.tcps_rcvdupbyte += todrop); + } else { + STAT(tcpstat.tcps_rcvpartduppack++); + STAT(tcpstat.tcps_rcvpartdupbyte += todrop); } m_adj(m, todrop); ti->ti_seq += todrop; @@ -900,9 +895,9 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * user processes are gone, then RST the other end. */ if ((so->so_state & SS_NOFDREF) && - tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { + tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { tp = tcp_close(tp); - tcpstat.tcps_rcvafterclose++; + STAT(tcpstat.tcps_rcvafterclose++); goto dropwithreset; } @@ -910,11 +905,11 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * If segment ends after window, drop trailing data * (and PUSH and FIN); if nothing left, just ACK. */ - todrop = (ti->ti_seq + ti->ti_len) - (tp->rcv_nxt + tp->rcv_wnd); + todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); if (todrop > 0) { - tcpstat.tcps_rcvpackafterwin++; + STAT(tcpstat.tcps_rcvpackafterwin++); if (todrop >= ti->ti_len) { - tcpstat.tcps_rcvbyteafterwin += ti->ti_len; + STAT(tcpstat.tcps_rcvbyteafterwin += ti->ti_len); /* * If a new connection request is received * while in TIME_WAIT, drop the old connection @@ -922,8 +917,8 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * are above the previous ones. */ if (tiflags & TH_SYN && - tp->t_state == TCPS_TIME_WAIT && - SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { + tp->t_state == TCPS_TIME_WAIT && + SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { iss = tp->rcv_nxt + TCP_ISSINCR; tp = tcp_close(tp); goto findso; @@ -937,56 +932,54 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) */ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_rcvwinprobe++; - } - else + STAT(tcpstat.tcps_rcvwinprobe++); + } else goto dropafterack; - } - else - tcpstat.tcps_rcvbyteafterwin += todrop; + } else + STAT(tcpstat.tcps_rcvbyteafterwin += todrop); m_adj(m, -todrop); ti->ti_len -= todrop; - tiflags &= ~(TH_PUSH | TH_FIN); + tiflags &= ~(TH_PUSH|TH_FIN); } /* * If last ACK falls within this segment's sequence numbers, * record its timestamp. */ - /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && - * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + - * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { - * tp->ts_recent_age = tcp_now; - * tp->ts_recent = ts_val; - * } - */ +/* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && + * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + + * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { + * tp->ts_recent_age = tcp_now; + * tp->ts_recent = ts_val; + * } + */ - /* - * If the RST bit is set examine the state: - * SYN_RECEIVED STATE: - * If passive open, return to LISTEN state. - * If active open, inform user that connection was refused. - * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: - * Inform user that connection was reset, and close tcb. - * CLOSING, LAST_ACK, TIME_WAIT STATES - * Close the tcb. - */ + /* + * If the RST bit is set examine the state: + * SYN_RECEIVED STATE: + * If passive open, return to LISTEN state. + * If active open, inform user that connection was refused. + * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: + * Inform user that connection was reset, and close tcb. + * CLOSING, LAST_ACK, TIME_WAIT STATES + * Close the tcb. + */ if (tiflags&TH_RST) switch (tp->t_state) { case TCPS_SYN_RECEIVED: - /* so->so_error = ECONNREFUSED; */ +/* so->so_error = ECONNREFUSED; */ goto close; case TCPS_ESTABLISHED: case TCPS_FIN_WAIT_1: case TCPS_FIN_WAIT_2: case TCPS_CLOSE_WAIT: - /* so->so_error = ECONNRESET; */ - close: - tp->t_state = TCPS_CLOSED; - tcpstat.tcps_drops++; - tp = tcp_close(tp); - goto drop; +/* so->so_error = ECONNRESET; */ + close: + tp->t_state = TCPS_CLOSED; + STAT(tcpstat.tcps_drops++); + tp = tcp_close(tp); + goto drop; case TCPS_CLOSING: case TCPS_LAST_ACK: @@ -1000,7 +993,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * error and we send an RST and drop the connection. */ if (tiflags & TH_SYN) { - tp = tcp_drop(tp, 0); + tp = tcp_drop(tp,0); goto dropwithreset; } @@ -1013,17 +1006,17 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * Ack processing. */ switch (tp->t_state) { - /* - * In SYN_RECEIVED state if the ack ACKs our SYN then enter - * ESTABLISHED state and continue processing, otherwise - * send an RST. una<=ack<=max - */ + /* + * In SYN_RECEIVED state if the ack ACKs our SYN then enter + * ESTABLISHED state and continue processing, otherwise + * send an RST. una<=ack<=max + */ case TCPS_SYN_RECEIVED: if (SEQ_GT(tp->snd_una, ti->ti_ack) || - SEQ_GT(ti->ti_ack, tp->snd_max)) + SEQ_GT(ti->ti_ack, tp->snd_max)) goto dropwithreset; - tcpstat.tcps_connects++; + STAT(tcpstat.tcps_connects++); tp->t_state = TCPS_ESTABLISHED; /* * The sent SYN is ack'ed with our sequence number +1 @@ -1032,24 +1025,21 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * SS_CTL since the buffer is empty otherwise. * tp->snd_una++; or: */ - tp->snd_una = ti->ti_ack; + tp->snd_una=ti->ti_ack; if (so->so_state & SS_CTL) { - /* So tcp_ctl reports the right state */ - ret = tcp_ctl(so); - if (ret == 1) { - soisfconnected(so); - so->so_state &= ~SS_CTL; /* success XXX */ - } - else if (ret == 2) { - so->so_state = SS_NOFDREF; /* CTL_CMD */ - } - else { - needoutput = 1; - tp->t_state = TCPS_FIN_WAIT_1; - } - } - else { - soisfconnected(so); + /* So tcp_ctl reports the right state */ + ret = tcp_ctl(so); + if (ret == 1) { + soisfconnected(so); + so->so_state &= ~SS_CTL; /* success XXX */ + } else if (ret == 2) { + so->so_state = SS_NOFDREF; /* CTL_CMD */ + } else { + needoutput = 1; + tp->t_state = TCPS_FIN_WAIT_1; + } + } else { + soisfconnected(so); } /* Do window scaling? */ @@ -1059,7 +1049,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * tp->rcv_scale = tp->request_r_scale; * } */ - (void)tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); + (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); tp->snd_wl1 = ti->ti_seq - 1; /* Avoid ack processing; snd_una==ti_ack => dup ack */ goto synrx_to_est; @@ -1083,9 +1073,9 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { - tcpstat.tcps_rcvdupack++; - DEBUG_MISC((dfd, " dup ack m = %lx so = %lx \n", - (long)m, (long)so)); + STAT(tcpstat.tcps_rcvdupack++); + DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", + (long )m, (long )so)); /* * If we have outstanding data (other than * a window probe), this is a completely @@ -1111,12 +1101,12 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * network. */ if (tp->t_timer[TCPT_REXMT] == 0 || - ti->ti_ack != tp->snd_una) + ti->ti_ack != tp->snd_una) tp->t_dupacks = 0; - else if (++tp->t_dupacks == tcprexmtthresh) { + else if (++tp->t_dupacks == TCPREXMTTHRESH) { tcp_seq onxt = tp->snd_nxt; u_int win = - min(tp->snd_wnd, tp->snd_cwnd) / 2 / + min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; if (win < 2) @@ -1126,20 +1116,18 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) tp->t_rtt = 0; tp->snd_nxt = ti->ti_ack; tp->snd_cwnd = tp->t_maxseg; - (void)tcp_output(tp); + (void) tcp_output(tp); tp->snd_cwnd = tp->snd_ssthresh + - tp->t_maxseg * tp->t_dupacks; + tp->t_maxseg * tp->t_dupacks; if (SEQ_GT(onxt, tp->snd_nxt)) tp->snd_nxt = onxt; goto drop; - } - else if (tp->t_dupacks > tcprexmtthresh) { + } else if (tp->t_dupacks > TCPREXMTTHRESH) { tp->snd_cwnd += tp->t_maxseg; - (void)tcp_output(tp); + (void) tcp_output(tp); goto drop; } - } - else + } else tp->t_dupacks = 0; break; } @@ -1148,17 +1136,17 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * If the congestion window was inflated to account * for the other side's cached packets, retract it. */ - if (tp->t_dupacks > tcprexmtthresh && - tp->snd_cwnd > tp->snd_ssthresh) + if (tp->t_dupacks > TCPREXMTTHRESH && + tp->snd_cwnd > tp->snd_ssthresh) tp->snd_cwnd = tp->snd_ssthresh; tp->t_dupacks = 0; if (SEQ_GT(ti->ti_ack, tp->snd_max)) { - tcpstat.tcps_rcvacktoomuch++; + STAT(tcpstat.tcps_rcvacktoomuch++); goto dropafterack; } acked = ti->ti_ack - tp->snd_una; - tcpstat.tcps_rcvackpack++; - tcpstat.tcps_rcvackbyte += acked; + STAT(tcpstat.tcps_rcvackpack++); + STAT(tcpstat.tcps_rcvackbyte += acked); /* * If we have a timestamp reply, update smoothed @@ -1169,12 +1157,12 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * timer backoff (cf., Phil Karn's retransmit alg.). * Recompute the initial retransmit timer. */ - /* if (ts_present) - * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); - * else - */ - if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) - tcp_xmit_timer(tp, tp->t_rtt); +/* if (ts_present) + * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); + * else + */ + if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) + tcp_xmit_timer(tp,tp->t_rtt); /* * If all outstanding data is acked, stop retransmit @@ -1185,8 +1173,7 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) if (ti->ti_ack == tp->snd_max) { tp->t_timer[TCPT_REXMT] = 0; needoutput = 1; - } - else if (tp->t_timer[TCPT_PERSIST] == 0) + } else if (tp->t_timer[TCPT_PERSIST] == 0) tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; /* * When new data is acked, open the congestion window. @@ -1196,19 +1183,18 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * (maxseg^2 / cwnd per packet). */ { - register u_int cw = tp->snd_cwnd; - register u_int incr = tp->t_maxseg; + register u_int cw = tp->snd_cwnd; + register u_int incr = tp->t_maxseg; - if (cw > tp->snd_ssthresh) - incr = incr * incr / cw; - tp->snd_cwnd = min(cw + incr, (u_int32_t) (TCP_MAXWIN << tp->snd_scale)); + if (cw > tp->snd_ssthresh) + incr = incr * incr / cw; + tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<snd_scale); } if (acked > so->so_snd.sb_cc) { tp->snd_wnd -= so->so_snd.sb_cc; - sbdrop(&so->so_snd, so->so_snd.sb_cc); + sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); ourfinisacked = 1; - } - else { + } else { sbdrop(&so->so_snd, acked); tp->snd_wnd -= acked; ourfinisacked = 0; @@ -1217,20 +1203,20 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) * XXX sowwakup is called when data is acked and there's room for * for more data... it should read() the socket */ - /* if (so->so_snd.sb_flags & SB_NOTIFY) - * sowwakeup(so); - */ +/* if (so->so_snd.sb_flags & SB_NOTIFY) + * sowwakeup(so); + */ tp->snd_una = ti->ti_ack; if (SEQ_LT(tp->snd_nxt, tp->snd_una)) tp->snd_nxt = tp->snd_una; switch (tp->t_state) { - /* - * In FIN_WAIT_1 STATE in addition to the processing - * for the ESTABLISHED state if our FIN is now acknowledged - * then enter FIN_WAIT_2. - */ + /* + * In FIN_WAIT_1 STATE in addition to the processing + * for the ESTABLISHED state if our FIN is now acknowledged + * then enter FIN_WAIT_2. + */ case TCPS_FIN_WAIT_1: if (ourfinisacked) { /* @@ -1242,18 +1228,18 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) */ if (so->so_state & SS_FCANTRCVMORE) { soisfdisconnected(so); - tp->t_timer[TCPT_2MSL] = tcp_maxidle; + tp->t_timer[TCPT_2MSL] = TCP_MAXIDLE; } tp->t_state = TCPS_FIN_WAIT_2; } break; - /* - * In CLOSING STATE in addition to the processing for - * the ESTABLISHED state if the ACK acknowledges our FIN - * then enter the TIME-WAIT state, otherwise ignore - * the segment. - */ + /* + * In CLOSING STATE in addition to the processing for + * the ESTABLISHED state if the ACK acknowledges our FIN + * then enter the TIME-WAIT state, otherwise ignore + * the segment. + */ case TCPS_CLOSING: if (ourfinisacked) { tp->t_state = TCPS_TIME_WAIT; @@ -1263,12 +1249,12 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) } break; - /* - * In LAST_ACK, we may still be waiting for data to drain - * and/or to be acked, as well as for the ack of our FIN. - * If our FIN is now acknowledged, delete the TCB, - * enter the closed state and return. - */ + /* + * In LAST_ACK, we may still be waiting for data to drain + * and/or to be acked, as well as for the ack of our FIN. + * If our FIN is now acknowledged, delete the TCB, + * enter the closed state and return. + */ case TCPS_LAST_ACK: if (ourfinisacked) { tp = tcp_close(tp); @@ -1276,11 +1262,11 @@ SEQ_GT(ti->ti_ack, tp->t_rtseq)) } break; - /* - * In TIME_WAIT state the only thing that should arrive - * is a retransmission of the remote FIN. Acknowledge - * it and restart the finack timer. - */ + /* + * In TIME_WAIT state the only thing that should arrive + * is a retransmission of the remote FIN. Acknowledge + * it and restart the finack timer. + */ case TCPS_TIME_WAIT: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; goto dropafterack; @@ -1293,13 +1279,13 @@ step6: * Don't look at window if no ACK: TAC's send garbage on first SYN. */ if ((tiflags & TH_ACK) && - (SEQ_LT(tp->snd_wl1, ti->ti_seq) || - (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || - (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { + (SEQ_LT(tp->snd_wl1, ti->ti_seq) || + (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || + (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { /* keep track of pure window updates */ if (ti->ti_len == 0 && - tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) - tcpstat.tcps_rcvwinupd++; + tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) + STAT(tcpstat.tcps_rcvwinupd++); tp->snd_wnd = tiwin; tp->snd_wl1 = ti->ti_seq; tp->snd_wl2 = ti->ti_ack; @@ -1312,7 +1298,7 @@ step6: * Process segments with URG. */ if ((tiflags & TH_URG) && ti->ti_urp && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { + TCPS_HAVERCVDFIN(tp->t_state) == 0) { /* * This is a kludge, but if we receive and accept * random urgent pointers, we'll crash in @@ -1338,22 +1324,21 @@ step6: * of data past the urgent section as the original * spec states (in one of two places). */ - if (SEQ_GT(ti->ti_seq + ti->ti_urp, tp->rcv_up)) { + if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { tp->rcv_up = ti->ti_seq + ti->ti_urp; - so->so_urgc = so->so_rcv.sb_cc + + so->so_urgc = so->so_rcv.sb_cc + (tp->rcv_up - tp->rcv_nxt); /* -1; */ tp->rcv_up = ti->ti_seq + ti->ti_urp; } - } - else + } else /* * If no out of band data is expected, * pull receive urgent pointer along * with the receive window. */ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) - tp->rcv_up = tp->rcv_nxt; + tp->rcv_up = tp->rcv_nxt; dodata: /* @@ -1365,7 +1350,7 @@ dodata: * connection then we just ignore the text. */ if ((ti->ti_len || (tiflags&TH_FIN)) && - TCPS_HAVERCVDFIN(tp->t_state) == 0) { + TCPS_HAVERCVDFIN(tp->t_state) == 0) { TCP_REASS(tp, ti, m, so, tiflags); /* * Note the amount of data that peer has sent into @@ -1373,8 +1358,7 @@ dodata: * buffer size. */ len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); - } - else { + } else { m_free(m); tiflags &= ~TH_FIN; } @@ -1388,13 +1372,13 @@ dodata: /* * If we receive a FIN we can't send more data, * set it SS_FDRAIN - * Shutdown the socket if there is no rx data in the + * Shutdown the socket if there is no rx data in the * buffer. * soread() is called on completion of shutdown() and * will got to TCPS_LAST_ACK, and use tcp_output() * to send the FIN. */ - /* sofcantrcvmore(so); */ +/* sofcantrcvmore(so); */ sofwdrain(so); tp->t_flags |= TF_ACKNOW; @@ -1402,31 +1386,31 @@ dodata: } switch (tp->t_state) { - /* - * In SYN_RECEIVED and ESTABLISHED STATES - * enter the CLOSE_WAIT state. - */ + /* + * In SYN_RECEIVED and ESTABLISHED STATES + * enter the CLOSE_WAIT state. + */ case TCPS_SYN_RECEIVED: case TCPS_ESTABLISHED: - if (so->so_emu == EMU_CTL) /* no shutdown on socket */ - tp->t_state = TCPS_LAST_ACK; - else - tp->t_state = TCPS_CLOSE_WAIT; - break; + if(so->so_emu == EMU_CTL) /* no shutdown on socket */ + tp->t_state = TCPS_LAST_ACK; + else + tp->t_state = TCPS_CLOSE_WAIT; + break; - /* - * If still in FIN_WAIT_1 STATE FIN has not been acked so - * enter the CLOSING state. - */ + /* + * If still in FIN_WAIT_1 STATE FIN has not been acked so + * enter the CLOSING state. + */ case TCPS_FIN_WAIT_1: tp->t_state = TCPS_CLOSING; break; - /* - * In FIN_WAIT_2 state enter the TIME_WAIT state, - * starting the time-wait timer, turning off the other - * standard timers. - */ + /* + * In FIN_WAIT_2 state enter the TIME_WAIT state, + * starting the time-wait timer, turning off the other + * standard timers. + */ case TCPS_FIN_WAIT_2: tp->t_state = TCPS_TIME_WAIT; tcp_canceltimers(tp); @@ -1434,9 +1418,9 @@ dodata: soisfdisconnected(so); break; - /* - * In TIME_WAIT state restart the 2 MSL time_wait timer. - */ + /* + * In TIME_WAIT state restart the 2 MSL time_wait timer. + */ case TCPS_TIME_WAIT: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; break; @@ -1450,15 +1434,15 @@ dodata: * * See above. */ - /* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { - */ - /* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && - * (so->so_iptos & IPTOS_LOWDELAY) == 0) || - * ((so->so_iptos & IPTOS_LOWDELAY) && - * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { - */ +/* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { + */ +/* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && + * (so->so_iptos & IPTOS_LOWDELAY) == 0) || + * ((so->so_iptos & IPTOS_LOWDELAY) && + * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { + */ if (ti->ti_len && (unsigned)ti->ti_len <= 5 && - ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { + ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { tp->t_flags |= TF_ACKNOW; } @@ -1466,7 +1450,7 @@ dodata: * Return any desired output. */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { - (void)tcp_output(tp); + (void) tcp_output(tp); } return; @@ -1479,7 +1463,7 @@ dropafterack: goto drop; m_freem(m); tp->t_flags |= TF_ACKNOW; - (void)tcp_output(tp); + (void) tcp_output(tp); return; dropwithreset: @@ -1488,8 +1472,8 @@ dropwithreset: tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); else { if (tiflags & TH_SYN) ti->ti_len++; - tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0, - TH_RST | TH_ACK); + tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, + TH_RST|TH_ACK); } return; @@ -1507,7 +1491,7 @@ drop: /* int *ts_present; * u_int32_t *ts_val, *ts_ecr; */ -void +static void tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) { u_int16_t mss; @@ -1539,7 +1523,7 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) continue; memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); NTOHS(mss); - tcp_mss(tp, mss); /* sets t_maxseg */ + (void) tcp_mss(tp, mss); /* sets t_maxseg */ break; /* case TCPOPT_WINDOW: @@ -1560,7 +1544,7 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) * memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); * NTOHL(*ts_ecr); * - */ /* + */ /* * * A timestamp received in a SYN makes * * it ok to send timestamp requests and replies. * */ @@ -1584,10 +1568,14 @@ tcp_dooptions(struct tcpcb *tp, u_char *cp, int cnt, struct tcpiphdr *ti) #ifdef notdef -void tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, register struct mbuf *m) +void +tcp_pulloutofband(so, ti, m) + struct socket *so; + struct tcpiphdr *ti; + register struct mbuf *m; { int cnt = ti->ti_urp - 1; - + while (cnt >= 0) { if (m->m_len > cnt) { char *cp = mtod(m, caddr_t) + cnt; @@ -1614,15 +1602,16 @@ void tcp_pulloutofband(struct socket *so, struct tcpiphdr *ti, register struct m * and update averages and current timeout. */ -void tcp_xmit_timer(register struct tcpcb *tp, int rtt) +static void +tcp_xmit_timer(register struct tcpcb *tp, int rtt) { register short delta; DEBUG_CALL("tcp_xmit_timer"); DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("rtt = %d", rtt); - - tcpstat.tcps_rttupdated++; + + STAT(tcpstat.tcps_rttupdated++); if (tp->t_srtt != 0) { /* * srtt is stored as fixed point with 3 bits after the @@ -1650,7 +1639,7 @@ void tcp_xmit_timer(register struct tcpcb *tp, int rtt) if ((tp->t_rttvar += delta) <= 0) tp->t_rttvar = 1; } else { - /* + /* * No rtt measurement yet - use the unsmoothed rtt. * Set the variance to half the rtt (so our first * retransmit happens at 3*rtt). @@ -1674,7 +1663,7 @@ void tcp_xmit_timer(register struct tcpcb *tp, int rtt) */ TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ - + /* * We received an ack for a packet that wasn't retransmitted; * it is probably safe to discard any error indications we've @@ -1701,28 +1690,35 @@ void tcp_xmit_timer(register struct tcpcb *tp, int rtt) * parameters from pre-set or cached values in the routing entry. */ -u_int tcp_mss(register struct tcpcb *tp, u_int offer) +int +tcp_mss(tp, offer) + register struct tcpcb *tp; + u_int offer; { struct socket *so = tp->t_socket; - u_int mss; - + int mss; + DEBUG_CALL("tcp_mss"); DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("offer = %d", offer); - - mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); + + mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr); if (offer) mss = min(mss, offer); mss = max(mss, 32); if (mss < tp->t_maxseg || offer != 0) tp->t_maxseg = mss; - + tp->snd_cwnd = mss; - - sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); - sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); - + + sbreserve(&so->so_snd, TCP_SNDSPACE + ((TCP_SNDSPACE % mss) ? + (mss - (TCP_SNDSPACE % mss)) : + 0)); + sbreserve(&so->so_rcv, TCP_RCVSPACE + ((TCP_RCVSPACE % mss) ? + (mss - (TCP_RCVSPACE % mss)) : + 0)); + DEBUG_MISC((dfd, " returning mss = %d\n", mss)); - + return mss; } diff --git a/BasiliskII/src/slirp/tcp_output.c b/BasiliskII/src/slirp/tcp_output.c index 01df0118..dba4ed7a 100644 --- a/BasiliskII/src/slirp/tcp_output.c +++ b/BasiliskII/src/slirp/tcp_output.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,8 +37,8 @@ /* * Changes and additions relating to SLiRP * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ @@ -44,16 +48,16 @@ * Since this is only used in "stats socket", we give meaning * names instead of the REAL names */ -char *tcpstates[] = { +const char * const tcpstates[] = { /* "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", */ "REDIRECT", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; -u_char tcp_outflags[TCP_NSTATES] = { +static const u_char tcp_outflags[TCP_NSTATES] = { TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, - TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, + TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, }; @@ -63,7 +67,9 @@ u_char tcp_outflags[TCP_NSTATES] = { /* * Tcp output routine: figure out what should be sent and send it. */ -int tcp_output(register struct tcpcb *tp) +int +tcp_output(tp) + register struct tcpcb *tp; { register struct socket *so = tp->t_socket; register long len, win; @@ -73,10 +79,10 @@ int tcp_output(register struct tcpcb *tp) u_char opt[MAX_TCPOPTLEN]; unsigned optlen, hdrlen; int idle, sendalot; - + DEBUG_CALL("tcp_output"); DEBUG_ARG("tp = %lx", (long )tp); - + /* * Determine length of data that should be transmitted, * and flags that will be used. @@ -97,9 +103,9 @@ again: win = min(tp->snd_wnd, tp->snd_cwnd); flags = tcp_outflags[tp->t_state]; - + DEBUG_MISC((dfd, " --- tcp_output flags = 0x%x\n",flags)); - + /* * If in persist timeout with window of 0, send 1 byte. * Otherwise, if window is small but nonzero @@ -124,7 +130,7 @@ again: * to send then the probe will be the FIN * itself. */ - if (off < (int)so->so_snd.sb_cc) + if (off < so->so_snd.sb_cc) flags &= ~TH_FIN; win = 1; } else { @@ -152,7 +158,7 @@ again: tp->snd_nxt = tp->snd_una; } } - + if (len > tp->t_maxseg) { len = tp->t_maxseg; sendalot = 1; @@ -194,17 +200,17 @@ again: * window, then want to send a window update to peer. */ if (win > 0) { - /* + /* * "adv" is the amount we can increase the window, * taking into account that we are limited by * TCP_MAXWIN << tp->rcv_scale. */ - long adv = min(win, TCP_MAXWIN << tp->rcv_scale) - + long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - (tp->rcv_adv - tp->rcv_nxt); - if (adv >= (long)(2 * tp->t_maxseg)) + if (adv >= (long) (2 * tp->t_maxseg)) goto send; - if (2 * adv >= (long)so->so_rcv.sb_datalen) + if (2 * adv >= (long) so->so_rcv.sb_datalen) goto send; } @@ -257,8 +263,8 @@ again: /* * No reason to send a segment, just return. */ - tcpstat.tcps_didnuttin++; - + STAT(tcpstat.tcps_didnuttin++); + return (0); send: @@ -296,9 +302,9 @@ send: */ } } - + /* - * Send a timestamp and echo-reply if this is a SYN and our side + * Send a timestamp and echo-reply if this is a SYN and our side * wants to use timestamps (TF_REQ_TSTMP is set) or both our side * and our peer have sent timestamps in our SYN's. */ @@ -316,7 +322,7 @@ send: * } */ hdrlen += optlen; - + /* * Adjust data length if insertion of options will * bump the packet length beyond the t_maxseg length. @@ -333,13 +339,13 @@ send: */ if (len) { if (tp->t_force && len == 1) - tcpstat.tcps_sndprobe++; + STAT(tcpstat.tcps_sndprobe++); else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { - tcpstat.tcps_sndrexmitpack++; - tcpstat.tcps_sndrexmitbyte += len; + STAT(tcpstat.tcps_sndrexmitpack++); + STAT(tcpstat.tcps_sndrexmitbyte += len); } else { - tcpstat.tcps_sndpack++; - tcpstat.tcps_sndbyte += len; + STAT(tcpstat.tcps_sndpack++); + STAT(tcpstat.tcps_sndbyte += len); } m = m_get(); @@ -348,16 +354,16 @@ send: error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; - - /* + + /* * This will always succeed, since we make sure our mbufs * are big enough to hold one MSS packet + header + ... etc. */ /* if (len <= MHLEN - hdrlen - max_linkhdr) { */ - sbcopy(&so->so_snd, off, len, mtod(m, caddr_t) + hdrlen); + sbcopy(&so->so_snd, off, (int) len, mtod(m, caddr_t) + hdrlen); m->m_len += len; /* } else { @@ -376,13 +382,13 @@ send: flags |= TH_PUSH; } else { if (tp->t_flags & TF_ACKNOW) - tcpstat.tcps_sndacks++; + STAT(tcpstat.tcps_sndacks++); else if (flags & (TH_SYN|TH_FIN|TH_RST)) - tcpstat.tcps_sndctrl++; + STAT(tcpstat.tcps_sndctrl++); else if (SEQ_GT(tp->snd_up, tp->snd_una)) - tcpstat.tcps_sndurg++; + STAT(tcpstat.tcps_sndurg++); else - tcpstat.tcps_sndwinup++; + STAT(tcpstat.tcps_sndwinup++); m = m_get(); if (m == NULL) { @@ -390,12 +396,12 @@ send: error = 1; goto out; } - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; m->m_len = hdrlen; } ti = mtod(m, struct tcpiphdr *); - + memcpy((caddr_t)ti, &tp->t_template, sizeof (struct tcpiphdr)); /* @@ -403,7 +409,7 @@ send: * window for use in delaying messages about window sizes. * If resending a FIN, be sure not to use a new sequence number. */ - if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && + if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && tp->snd_nxt == tp->snd_max) tp->snd_nxt--; /* @@ -433,17 +439,17 @@ send: * Calculate receive window. Don't shrink window, * but avoid silly window syndrome. */ - if (win < (so->so_rcv.sb_datalen / 4) && win < tp->t_maxseg) + if (win < (long)(so->so_rcv.sb_datalen / 4) && win < (long)tp->t_maxseg) win = 0; - if (win > (u_long) (TCP_MAXWIN << tp->rcv_scale)) - win = (u_long) (TCP_MAXWIN << tp->rcv_scale); - if (win < (tp->rcv_adv - tp->rcv_nxt)) - win = (tp->rcv_adv - tp->rcv_nxt); + if (win > (long)TCP_MAXWIN << tp->rcv_scale) + win = (long)TCP_MAXWIN << tp->rcv_scale; + if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) + win = (long)(tp->rcv_adv - tp->rcv_nxt); ti->ti_win = htons((u_int16_t) (win>>tp->rcv_scale)); - + if (SEQ_GT(tp->snd_up, tp->snd_una)) { ti->ti_urp = htons((u_int16_t)(tp->snd_up - ntohl(ti->ti_seq))); -#ifdef notdef +#ifdef notdef if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ti->ti_urp = htons((u_int16_t)(tp->snd_up - tp->snd_nxt)); #endif @@ -494,7 +500,7 @@ send: if (tp->t_rtt == 0) { tp->t_rtt = 1; tp->t_rtseq = startseq; - tcpstat.tcps_segstimed++; + STAT(tcpstat.tcps_segstimed++); } } @@ -525,14 +531,14 @@ send: * the template, but need a way to checksum without them. */ m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */ - - { - - ((struct ip *)ti)->ip_len = (u_int16_t) m->m_len; - ((struct ip *)ti)->ip_ttl = ip_defttl; + { + + ((struct ip *)ti)->ip_len = m->m_len; + + ((struct ip *)ti)->ip_ttl = IPDEFTTL; ((struct ip *)ti)->ip_tos = so->so_iptos; - + /* #if BSD >= 43 */ /* Don't do IP options... */ /* error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, @@ -541,7 +547,7 @@ send: error = ip_output(so, m); /* #else - * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, + * error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, * so->so_options & SO_DONTROUTE); * #endif */ @@ -561,7 +567,7 @@ out: */ return (error); } - tcpstat.tcps_sndtotal++; + STAT(tcpstat.tcps_sndtotal++); /* * Data sent (as far as we can tell). @@ -579,7 +585,9 @@ out: return (0); } -void tcp_setpersist(register struct tcpcb *tp) +void +tcp_setpersist(tp) + register struct tcpcb *tp; { int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; diff --git a/BasiliskII/src/slirp/tcp_subr.c b/BasiliskII/src/slirp/tcp_subr.c index 70e04b5e..ba1296d4 100644 --- a/BasiliskII/src/slirp/tcp_subr.c +++ b/BasiliskII/src/slirp/tcp_subr.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,37 +37,26 @@ /* * 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. */ #define WANT_SYS_IOCTL_H -#include #include /* patchable/settable parameters for tcp */ -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; -int tcp_do_rfc1323 = 0; /* Don't do rfc1323 performance enhancements */ -size_t tcp_rcvspace; /* You may want to change this */ -size_t tcp_sndspace; /* Keep small if you have an error prone link */ +/* Don't do rfc1323 performance enhancements */ +#define TCP_DO_RFC1323 0 /* * Tcp initialization */ -void tcp_init() +void +tcp_init() { tcp_iss = 1; /* wrong */ tcb.so_next = tcb.so_prev = &tcb; - - /* tcp_rcvspace = our Window we advertise to the remote */ - tcp_rcvspace = TCP_RCVSPACE; - tcp_sndspace = TCP_SNDSPACE; - - /* Make sure tcp_sndspace is at least 2*MSS */ - if (tcp_sndspace < 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr))) - tcp_sndspace = 2*(min(if_mtu, if_mru) - sizeof(struct tcpiphdr)); } /* @@ -73,7 +66,9 @@ void tcp_init() * necessary when the connection is used. */ /* struct tcpiphdr * */ -void tcp_template(struct tcpcb *tp) +void +tcp_template(tp) + struct tcpcb *tp; { struct socket *so = tp->t_socket; register struct tcpiphdr *n = &tp->t_template; @@ -86,7 +81,7 @@ void tcp_template(struct tcpcb *tp) n->ti_dst = so->so_laddr; n->ti_sport = so->so_fport; n->ti_dport = so->so_lport; - + n->ti_seq = 0; n->ti_ack = 0; n->ti_x2 = 0; @@ -110,8 +105,13 @@ void tcp_template(struct tcpcb *tp) * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ -void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, - register struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) +void +tcp_respond(tp, ti, m, ack, seq, flags) + struct tcpcb *tp; + register struct tcpiphdr *ti; + register struct mbuf *m; + tcp_seq ack, seq; + int flags; { register int tlen; int win = 0; @@ -123,7 +123,7 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, DEBUG_ARG("ack = %u", ack); DEBUG_ARG("seq = %u", seq); DEBUG_ARG("flags = %x", flags); - + if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == 0) { @@ -134,17 +134,17 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, #else tlen = 0; #endif - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else { - /* + /* * ti points into m so the next line is just making * the mbuf point to ti */ m->m_data = (caddr_t)ti; - + m->m_len = sizeof (struct tcpiphdr); tlen = 0; #define xchg(a,b,type) { type t; t=a; a=b; b=t; } @@ -172,11 +172,11 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, ti->ti_sum = cksum(m, tlen); ((struct ip *)ti)->ip_len = tlen; - if(flags & TH_RST) + if(flags & TH_RST) ((struct ip *)ti)->ip_ttl = MAXTTL; - else - ((struct ip *)ti)->ip_ttl = ip_defttl; - + else + ((struct ip *)ti)->ip_ttl = IPDEFTTL; + (void) ip_output((struct socket *)0, m); } @@ -185,38 +185,40 @@ void tcp_respond(struct tcpcb *tp, register struct tcpiphdr *ti, * empty reassembly queue and hooking it to the argument * protocol control block. */ -struct tcpcb *tcp_newtcpcb(struct socket *so) +struct tcpcb * +tcp_newtcpcb(so) + struct socket *so; { register struct tcpcb *tp; - + tp = (struct tcpcb *)malloc(sizeof(*tp)); if (tp == NULL) return ((struct tcpcb *)0); - + memset((char *) tp, 0, sizeof(struct tcpcb)); tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp; - tp->t_maxseg = tcp_mssdflt; - - tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; + tp->t_maxseg = TCP_MSS; + + tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0; tp->t_socket = so; - + /* * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << 2; + tp->t_rttvar = TCPTV_SRTTDFLT << 2; tp->t_rttmin = TCPTV_MIN; - TCPT_RANGESET(tp->t_rxtcur, + TCPT_RANGESET(tp->t_rxtcur, ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1, TCPTV_MIN, TCPTV_REXMTMAX); tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_state = TCPS_CLOSED; - + so->so_tcpcb = tp; return (tp); @@ -227,7 +229,7 @@ struct tcpcb *tcp_newtcpcb(struct socket *so) * the specified error. If connection is synchronized, * then send a RST to peer. */ -struct tcpcb *tcp_drop(struct tcpcb *tp, int err) +struct tcpcb *tcp_drop(struct tcpcb *tp, int err) { /* tcp_drop(tp, errno) register struct tcpcb *tp; @@ -238,13 +240,13 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err) DEBUG_CALL("tcp_drop"); DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("errno = %d", errno); - + if (TCPS_HAVERCVDSYN(tp->t_state)) { tp->t_state = TCPS_CLOSED; (void) tcp_output(tp); - tcpstat.tcps_drops++; + STAT(tcpstat.tcps_drops++); } else - tcpstat.tcps_conndrops++; + STAT(tcpstat.tcps_conndrops++); /* if (errno == ETIMEDOUT && tp->t_softerror) * errno = tp->t_softerror; */ @@ -258,7 +260,9 @@ struct tcpcb *tcp_drop(struct tcpcb *tp, int err) * discard internet protocol block * wake up any sleepers */ -struct tcpcb *tcp_close(register struct tcpcb *tp) +struct tcpcb * +tcp_close(tp) + register struct tcpcb *tp; { register struct tcpiphdr *t; struct socket *so = tp->t_socket; @@ -266,7 +270,7 @@ struct tcpcb *tcp_close(register struct tcpcb *tp) DEBUG_CALL("tcp_close"); DEBUG_ARG("tp = %lx", (long )tp); - + /* free the reassembly queue, if any */ t = (struct tcpiphdr *) tp->seg_next; while (t != (struct tcpiphdr *)tp) { @@ -290,11 +294,13 @@ struct tcpcb *tcp_close(register struct tcpcb *tp) sbfree(&so->so_rcv); sbfree(&so->so_snd); sofree(so); - tcpstat.tcps_closed++; + STAT(tcpstat.tcps_closed++); return ((struct tcpcb *)0); } -void tcp_drain() +#ifdef notdef +void +tcp_drain() { /* XXX */ } @@ -303,10 +309,10 @@ void tcp_drain() * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ +void +tcp_quench(i, errno) -#ifdef notdef - -void tcp_quench(int i, int errno) + int errno; { struct tcpcb *tp = intotcpcb(inp); @@ -330,12 +336,14 @@ void tcp_quench(int i, int errno) * for peer to send FIN or not respond to keep-alives, etc. * We can let the user exit from the close as soon as the FIN is acked. */ -void tcp_sockclosed(struct tcpcb *tp) +void +tcp_sockclosed(tp) + struct tcpcb *tp; { DEBUG_CALL("tcp_sockclosed"); DEBUG_ARG("tp = %lx", (long)tp); - + switch (tp->t_state) { case TCPS_CLOSED: @@ -361,34 +369,34 @@ void tcp_sockclosed(struct tcpcb *tp) tcp_output(tp); } -/* +/* * Connect to a host on the Internet * Called by tcp_input * Only do a connect, the tcp fields will be set in tcp_input * return 0 if there's a result of the connect, * else return -1 means we're still connecting * The return value is almost always -1 since the socket is - * nonblocking. Connect returns after the SYN is sent, and does + * nonblocking. Connect returns after the SYN is sent, and does * not wait for ACK+SYN. */ -int tcp_fconnect(struct socket *so) +int tcp_fconnect(so) + struct socket *so; { int ret=0; - + DEBUG_CALL("tcp_fconnect"); DEBUG_ARG("so = %lx", (long )so); if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) { int opt, s=so->s; struct sockaddr_in addr; - memset(&addr, 0, sizeof(struct sockaddr_in)); fd_nonblock(s); opt = 1; setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt )); opt = 1; setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt )); - + addr.sin_family = AF_INET; if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) { /* It's an alias */ @@ -405,14 +413,12 @@ int tcp_fconnect(struct socket *so) addr.sin_addr = so->so_faddr; addr.sin_port = so->so_fport; - char addrstr[INET_ADDRSTRLEN]; DEBUG_MISC((dfd, " connect()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)))); + "addr.sin_addr.s_addr=%.16s\n", + ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); /* We don't care what port we get */ ret = connect(s,(struct sockaddr *)&addr,sizeof (addr)); - + /* * If it's not in progress, it failed, so we just return 0, * without clearing SS_NOFDREF @@ -425,27 +431,29 @@ int tcp_fconnect(struct socket *so) /* * Accept the socket and connect to the local-host - * + * * We have a problem. The correct thing to do would be * to first connect to the local-host, and only if the * connection is accepted, then do an accept() here. - * But, a) we need to know who's trying to connect + * But, a) we need to know who's trying to connect * to the socket to be able to SYN the local-host, and * b) we are already connected to the foreign host by * the time it gets to accept(), so... We simply accept * here and SYN the local-host. - */ -void tcp_connect(struct socket *inso) + */ +void +tcp_connect(inso) + struct socket *inso; { struct socket *so; struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); + int addrlen = sizeof(struct sockaddr_in); struct tcpcb *tp; int s, opt; DEBUG_CALL("tcp_connect"); DEBUG_ARG("inso = %lx", (long)inso); - + /* * If it's an SS_ACCEPTONCE socket, no need to socreate() * another socket, just use the accept() socket. @@ -466,8 +474,8 @@ void tcp_connect(struct socket *inso) so->so_laddr = inso->so_laddr; so->so_lport = inso->so_lport; } - - tcp_mss(sototcpcb(so), 0); + + (void) tcp_mss(sototcpcb(so), 0); if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) { tcp_close(sototcpcb(so)); /* This will sofree() as well */ @@ -480,13 +488,13 @@ void tcp_connect(struct socket *inso) setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); opt = 1; setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int)); - + so->so_fport = addr.sin_port; so->so_faddr = addr.sin_addr; /* Translate connections from localhost to the real hostname */ if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr) so->so_faddr = alias_addr; - + /* Close the accept() socket, set right state */ if (inso->so_state & SS_FACCEPTONCE) { closesocket(so->s); /* If we only accept once, close the accept() socket */ @@ -494,12 +502,12 @@ void tcp_connect(struct socket *inso) /* if it's not FACCEPTONCE, it's already NOFDREF */ } so->s = s; - + so->so_iptos = tcp_tos(so); tp = sototcpcb(so); tcp_template(tp); - + /* Compute window scaling to request. */ /* while (tp->request_r_scale < TCP_MAX_WINSHIFT && * (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) @@ -507,11 +515,11 @@ void tcp_connect(struct socket *inso) */ /* soisconnecting(so); */ /* NOFDREF used instead */ - tcpstat.tcps_connattempt++; - + STAT(tcpstat.tcps_connattempt++); + tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; + tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); tcp_output(tp); @@ -520,11 +528,13 @@ void tcp_connect(struct socket *inso) /* * Attach a TCPCB to a socket. */ -int tcp_attach(struct socket *so) +int +tcp_attach(so) + struct socket *so; { if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) return -1; - + insque(so, &tcb); return 0; @@ -533,7 +543,7 @@ int tcp_attach(struct socket *so) /* * Set the socket's type of service field */ -struct tos_t tcptos[] = { +static const struct tos_t tcptos[] = { {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */ {21, 21, IPTOS_LOWDELAY, EMU_FTP}, /* ftp control */ {0, 23, IPTOS_LOWDELAY, 0}, /* telnet */ @@ -549,16 +559,21 @@ struct tos_t tcptos[] = { {0, 0, 0, 0} }; +#ifdef CONFIG_QEMU +static +#endif struct emu_t *tcpemu = 0; - + /* * Return TOS according to the above table */ -u_int8_t tcp_tos(struct socket *so) +u_int8_t +tcp_tos(so) + struct socket *so; { int i = 0; struct emu_t *emup; - + while(tcptos[i].tos) { if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) { @@ -567,7 +582,7 @@ u_int8_t tcp_tos(struct socket *so) } i++; } - + /* Nope, lets see if there's a user-added one */ for (emup = tcpemu; emup; emup = emup->next) { if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) || @@ -576,68 +591,73 @@ u_int8_t tcp_tos(struct socket *so) return emup->tos; } } - + return 0; } +#if 0 int do_echo = -1; +#endif /* * Emulate programs that try and connect to us * This includes ftp (the data connection is * initiated by the server) and IRC (DCC CHAT and * DCC SEND) for now - * + * * NOTE: It's possible to crash SLiRP by sending it * unstandard strings to emulate... if this is a problem, * more checks are needed here * * XXX Assumes the whole command came in one packet - * + * * XXX Some ftp clients will have their TOS set to * LOWDELAY and so Nagel will kick in. Because of this, * we'll get the first letter, followed by the rest, so * we simply scan for ORT instead of PORT... * DCC doesn't have this problem because there's other stuff * in the packet before the DCC command. - * - * Return 1 if the mbuf m is still valid and should be + * + * Return 1 if the mbuf m is still valid and should be * sbappend()ed - * + * * NOTE: if you return 0 you MUST m_free() the mbuf! */ -int tcp_emu(struct socket *so, struct mbuf *m) +int +tcp_emu(so, m) + struct socket *so; + struct mbuf *m; { u_int n1, n2, n3, n4, n5, n6; char buff[256]; u_int32_t laddr; u_int lport; char *bptr; - + DEBUG_CALL("tcp_emu"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); - + switch(so->so_emu) { int x, i; - + case EMU_IDENT: /* * Identification protocol as per rfc-1413 */ - + { struct socket *tmpso; struct sockaddr_in addr; - socklen_t addrlen = sizeof(struct sockaddr_in); + int addrlen = sizeof(struct sockaddr_in); struct sbuf *so_rcv = &so->so_rcv; - + memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); so_rcv->sb_wptr += m->m_len; so_rcv->sb_rptr += m->m_len; m->m_data[m->m_len] = 0; /* NULL terminate */ if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { - if (sscanf(so_rcv->sb_data, "%d%*[ ,]%d", &n1, &n2) == 2) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { HTONS(n1); HTONS(n2); /* n2 is the one on our host */ @@ -660,7 +680,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) m_free(m); return 0; } - + #if 0 case EMU_RLOGIN: /* @@ -675,7 +695,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) char term[100]; struct sbuf *so_snd = &so->so_snd; struct sbuf *so_rcv = &so->so_rcv; - + /* First check if they have a priveladged port, or too much data has arrived */ if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { @@ -686,13 +706,13 @@ int tcp_emu(struct socket *so, struct mbuf *m) m_free(m); return 0; } - + /* Append the current data */ memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); so_rcv->sb_wptr += m->m_len; so_rcv->sb_rptr += m->m_len; m_free(m); - + /* * Check if we have all the initial options, * and build argument list to rlogin while we're here @@ -724,10 +744,10 @@ int tcp_emu(struct socket *so, struct mbuf *m) } } } - + if (n != 4) return 0; - + /* We have it, set our term variable and fork_exec() */ #ifdef HAVE_SETENV setenv("TERM", term, 1); @@ -737,15 +757,15 @@ int tcp_emu(struct socket *so, struct mbuf *m) fork_exec(so, args, 2); term[0] = 0; so->so_emu = 0; - + /* And finally, send the client a 0 character */ so_snd->sb_wptr[0] = 0; so_snd->sb_wptr++; so_snd->sb_cc++; - + return 0; } - + case EMU_RSH: /* * rsh emulation @@ -759,7 +779,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) char *args; struct sbuf *so_snd = &so->so_snd; struct sbuf *so_rcv = &so->so_rcv; - + /* First check if they have a priveladged port, or too much data has arrived */ if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { @@ -770,13 +790,13 @@ int tcp_emu(struct socket *so, struct mbuf *m) m_free(m); return 0; } - + /* Append the current data */ memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); so_rcv->sb_wptr += m->m_len; so_rcv->sb_rptr += m->m_len; m_free(m); - + /* * Check if we have all the initial options, * and build argument list to rlogin while we're here @@ -807,20 +827,20 @@ int tcp_emu(struct socket *so, struct mbuf *m) ns->so_laddr=so->so_laddr; ns->so_lport=htons(port); - tcp_mss(sototcpcb(ns), 0); + (void) tcp_mss(sototcpcb(ns), 0); ns->so_faddr=so->so_faddr; ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */ - if (ns->so_faddr.s_addr == 0 || + if (ns->so_faddr.s_addr == 0 || ns->so_faddr.s_addr == loopback_addr.s_addr) ns->so_faddr = alias_addr; ns->so_iptos = tcp_tos(ns); tp = sototcpcb(ns); - + tcp_template(tp); - + /* Compute window scaling to request. */ /* while (tp->request_r_scale < TCP_MAX_WINSHIFT && * (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) @@ -829,11 +849,11 @@ int tcp_emu(struct socket *so, struct mbuf *m) /*soisfconnecting(ns);*/ - tcpstat.tcps_connattempt++; - + STAT(tcpstat.tcps_connattempt++); + tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; - tp->iss = tcp_iss; + tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; tcp_sendseqinit(tp); tcp_output(tp); @@ -849,19 +869,19 @@ int tcp_emu(struct socket *so, struct mbuf *m) } } } - + if (n != 4) return 0; - + rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args); so->so_emu = 0; so->extra=NULL; - + /* And finally, send the client a 0 character */ so_snd->sb_wptr[0] = 0; so_snd->sb_wptr++; so_snd->sb_cc++; - + return 0; } @@ -870,7 +890,7 @@ int tcp_emu(struct socket *so, struct mbuf *m) int num; struct sbuf *so_snd = &so->so_snd; struct sbuf *so_rcv = &so->so_rcv; - + /* * If there is binary data here, we save it in so->so_m */ @@ -885,16 +905,16 @@ int tcp_emu(struct socket *so, struct mbuf *m) } } } /* if(so->so_m==NULL) */ - + /* * Append the line */ sbappendsb(so_rcv, m); - + /* To avoid going over the edge of the buffer, we reset it */ if (so_snd->sb_cc == 0) so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data; - + /* * A bit of a hack: * If the first packet we get here is 1 byte long, then it @@ -913,13 +933,13 @@ int tcp_emu(struct socket *so, struct mbuf *m) tcp_output(sototcpcb(so)); /* XXX */ } else m_free(m); - + num = 0; while (num < so->so_rcv.sb_cc) { if (*(so->so_rcv.sb_rptr + num) == '\n' || *(so->so_rcv.sb_rptr + num) == '\r') { int n; - + *(so_rcv->sb_rptr + num) = 0; if (ctl_password && !ctl_password_ok) { /* Need a password */ @@ -956,76 +976,76 @@ do_prompt: } return 0; } -#endif +#endif case EMU_FTP: /* ftp */ *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */ if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { /* * Need to emulate the PORT command - */ - x = sscanf(bptr, "ORT %d,%d,%d,%d,%d,%d\r\n%256[^\177]", + */ + x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; - + laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - + if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; - + n6 = ntohs(so->so_fport); - + n5 = (n6 >> 8) & 0xff; n6 &= 0xff; - + laddr = ntohl(so->so_faddr.s_addr); - + n1 = ((laddr >> 24) & 0xff); n2 = ((laddr >> 16) & 0xff); n3 = ((laddr >> 8) & 0xff); n4 = (laddr & 0xff); - + m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s", + m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s", n1, n2, n3, n4, n5, n6, x==7?buff:""); return 1; } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) { /* * Need to emulate the PASV response */ - x = sscanf(bptr, "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%256[^\177]", + x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]", &n1, &n2, &n3, &n4, &n5, &n6, buff); if (x < 6) return 1; - + laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4)); lport = htons((n5 << 8) | (n6)); - + if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL) return 1; - + n6 = ntohs(so->so_fport); - + n5 = (n6 >> 8) & 0xff; n6 &= 0xff; - + laddr = ntohl(so->so_faddr.s_addr); - + n1 = ((laddr >> 24) & 0xff); n2 = ((laddr >> 16) & 0xff); n3 = ((laddr >> 8) & 0xff); n4 = (laddr & 0xff); - + m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", n1, n2, n3, n4, n5, n6, x==7?buff:""); - + return 1; } - + return 1; - + case EMU_KSH: /* * The kshell (Kerberos rsh) and shell services both pass @@ -1034,7 +1054,7 @@ do_prompt: * of the connection as a NUL-terminated decimal ASCII string. */ so->so_emu = 0; - for (lport = 0, i = 0; i < (int) (m->m_len-1); ++i) { + for (lport = 0, i = 0; i < m->m_len-1; ++i) { if (m->m_data[i] < '0' || m->m_data[i] > '9') return 1; /* invalid number */ lport *= 10; @@ -1044,7 +1064,7 @@ do_prompt: (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL) m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1; return 1; - + case EMU_IRC: /* * Need to emulate DCC CHAT, DCC SEND and DCC MOVE @@ -1052,12 +1072,12 @@ do_prompt: *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */ if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL) return 1; - + /* The %256s is for the broken mIRC */ if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) { if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; - + m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n", (unsigned long)ntohl(so->so_faddr.s_addr), @@ -1065,15 +1085,15 @@ do_prompt: } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; - + m->m_len = bptr - m->m_data; /* Adjust length */ - m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n", + m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n", buff, (unsigned long)ntohl(so->so_faddr.s_addr), ntohs(so->so_fport), n1, 1); } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) { if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL) return 1; - + m->m_len = bptr - m->m_data; /* Adjust length */ m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n", buff, (unsigned long)ntohl(so->so_faddr.s_addr), @@ -1082,7 +1102,7 @@ do_prompt: return 1; case EMU_REALAUDIO: - /* + /* * RealAudio emulation - JP. We must try to parse the incoming * data and try to find the two characters that contain the * port number. Then we redirect an udp port and replace the @@ -1090,45 +1110,45 @@ do_prompt: * * The 1.0 beta versions of the player are not supported * any more. - * + * * A typical packet for player version 1.0 (release version): - * - * 0000:50 4E 41 00 05 + * + * 0000:50 4E 41 00 05 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB - * + * * Now the port number 0x1BD7 is found at offset 0x04 of the * Now the port number 0x1BD7 is found at offset 0x04 of the * second packet. This time we received five bytes first and * then the rest. You never know how many bytes you get. * * A typical packet for player version 2.0 (beta): - * + * * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á. * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/ * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas * 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B - * + * * Port number 0x1BC1 is found at offset 0x0d. - * + * * This is just a horrible switch statement. Variable ra tells * us where we're going. */ - + bptr = m->m_data; while (bptr < m->m_data + m->m_len) { u_short p; static int ra = 0; - char ra_tbl[4]; - + char ra_tbl[4]; + ra_tbl[0] = 0x50; ra_tbl[1] = 0x4e; ra_tbl[2] = 0x41; ra_tbl[3] = 0; - + switch (ra) { case 0: case 2: @@ -1138,7 +1158,7 @@ do_prompt: continue; } break; - + case 1: /* * We may get 0x50 several times, ignore them @@ -1152,15 +1172,15 @@ do_prompt: continue; } break; - - case 4: - /* + + case 4: + /* * skip version number */ bptr++; break; - - case 5: + + case 5: /* * The difference between versions 1.0 and * 2.0 is here. For future versions of @@ -1170,19 +1190,19 @@ do_prompt: bptr += 8; else bptr += 4; - break; - + break; + case 6: /* This is the field containing the port * number that RA-player is listening to. */ - lport = (((u_char*)bptr)[0] << 8) + lport = (((u_char*)bptr)[0] << 8) + ((u_char *)bptr)[1]; - if (lport < 6970) + if (lport < 6970) lport += 256; /* don't know why */ if (lport < 6970 || lport > 7170) return 1; /* failed */ - + /* try to get udp port between 6970 - 7170 */ for (p = 6970; p < 7071; p++) { if (udp_listen( htons(p), @@ -1196,17 +1216,17 @@ do_prompt: p = 0; *(u_char *)bptr++ = (p >> 8) & 0xff; *(u_char *)bptr++ = p & 0xff; - ra = 0; + ra = 0; return 1; /* port redirected, we're done */ - break; - + break; + default: - ra = 0; + ra = 0; } ra++; } - return 1; - + return 1; + default: /* Ooops, not emulated, won't call tcp_emu again */ so->so_emu = 0; @@ -1219,17 +1239,19 @@ do_prompt: * Return 0 if this connections is to be closed, 1 otherwise, * return 2 if this is a command-line connection */ -int tcp_ctl(struct socket *so) +int +tcp_ctl(so) + struct socket *so; { struct sbuf *sb = &so->so_snd; int command; struct ex_list *ex_ptr; int do_pty; // struct socket *tmpso; - + DEBUG_CALL("tcp_ctl"); DEBUG_ARG("so = %lx", (long )so); - + #if 0 /* * Check if they're authorised @@ -1239,12 +1261,12 @@ int tcp_ctl(struct socket *so) sb->sb_wptr += sb->sb_cc; return 0; } -#endif +#endif command = (ntohl(so->so_faddr.s_addr) & 0xff); - + switch(command) { default: /* Check for exec's */ - + /* * Check if it's pty_exec */ @@ -1255,12 +1277,12 @@ int tcp_ctl(struct socket *so) goto do_exec; } } - + /* * Nothing bound.. */ /* tcp_fconnect(so); */ - + /* FALLTHROUGH */ case CTL_ALIAS: sb->sb_cc = sprintf(sb->sb_wptr, @@ -1271,12 +1293,12 @@ int tcp_ctl(struct socket *so) do_exec: DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec)); return(fork_exec(so, ex_ptr->ex_exec, do_pty)); - + #if 0 case CTL_CMD: for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) { - if (tmpso->so_emu == EMU_CTL && - !(tmpso->so_tcpcb? + if (tmpso->so_emu == EMU_CTL && + !(tmpso->so_tcpcb? (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK)) :0)) { /* Ooops, control connection already active */ diff --git a/BasiliskII/src/slirp/tcp_timer.c b/BasiliskII/src/slirp/tcp_timer.c index ab9aa580..244bad6a 100644 --- a/BasiliskII/src/slirp/tcp_timer.c +++ b/BasiliskII/src/slirp/tcp_timer.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -32,14 +36,14 @@ #include -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; -int so_options = DO_KEEPALIVE; - +#ifdef LOG_ENABLED struct tcpstat tcpstat; /* tcp statistics */ +#endif + u_int32_t tcp_now; /* for RFC 1323 timestamps */ +static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer); + /* * Fast timeout routine for processing delayed acks */ @@ -50,7 +54,7 @@ tcp_fasttimo() register struct tcpcb *tp; DEBUG_CALL("tcp_fasttimo"); - + so = tcb.so_next; if (so) for (; so != &tcb; so = so->so_next) @@ -58,7 +62,7 @@ tcp_fasttimo() (tp->t_flags & TF_DELACK)) { tp->t_flags &= ~TF_DELACK; tp->t_flags |= TF_ACKNOW; - tcpstat.tcps_delack++; + STAT(tcpstat.tcps_delack++); (void) tcp_output(tp); } } @@ -76,8 +80,7 @@ tcp_slowtimo() register int i; DEBUG_CALL("tcp_slowtimo"); - - tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl; + /* * Search through tcb's and update active timers. */ @@ -123,21 +126,19 @@ tcp_canceltimers(tp) tp->t_timer[i] = 0; } -int tcp_backoff[TCP_MAXRXTSHIFT + 1] = +const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; /* * TCP timer processing. */ -struct tcpcb * -tcp_timers(tp, timer) - register struct tcpcb *tp; - int timer; +static struct tcpcb * +tcp_timers(register struct tcpcb *tp, int timer) { register int rexmt; - + DEBUG_CALL("tcp_timers"); - + switch (timer) { /* @@ -148,8 +149,8 @@ tcp_timers(tp, timer) */ case TCPT_2MSL: if (tp->t_state != TCPS_TIME_WAIT && - tp->t_idle <= tcp_maxidle) - tp->t_timer[TCPT_2MSL] = tcp_keepintvl; + tp->t_idle <= TCP_MAXIDLE) + tp->t_timer[TCPT_2MSL] = TCPTV_KEEPINTVL; else tp = tcp_close(tp); break; @@ -160,12 +161,12 @@ tcp_timers(tp, timer) * to a longer retransmit interval and retransmit one segment. */ case TCPT_REXMT: - + /* * XXXXX If a packet has timed out, then remove all the queued * packets for that session. */ - + if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { /* * This is a hack to suit our terminal server here at the uni of canberra @@ -174,33 +175,33 @@ tcp_timers(tp, timer) * keep retransmitting it, it'll keep eating the zeroes, so we keep * retransmitting, and eventually the connection dies... * (this only happens on incoming data) - * + * * So, if we were gonna drop the connection from too many retransmits, * don't... instead halve the t_maxseg, which might break up the NULLs and * let them through - * + * * *sigh* */ - + tp->t_maxseg >>= 1; if (tp->t_maxseg < 32) { /* * We tried our best, now the connection must die! */ tp->t_rxtshift = TCP_MAXRXTSHIFT; - tcpstat.tcps_timeoutdrop++; + STAT(tcpstat.tcps_timeoutdrop++); tp = tcp_drop(tp, tp->t_softerror); /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ return (tp); /* XXX */ } - + /* * Set rxtshift to 6, which is still at the maximum * backoff time */ tp->t_rxtshift = 6; } - tcpstat.tcps_rexmttimeo++; + STAT(tcpstat.tcps_rexmttimeo++); rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ @@ -236,7 +237,7 @@ tcp_timers(tp, timer) * size increase exponentially with time. If the * window is larger than the path can handle, this * exponential growth results in dropped packet(s) - * almost immediately. To get more time between + * almost immediately. To get more time between * drops but still "push" the network to take advantage * of improving conditions, we switch from exponential * to linear window opening at some threshold size. @@ -263,7 +264,7 @@ tcp_timers(tp, timer) * Force a byte to be output, if possible. */ case TCPT_PERSIST: - tcpstat.tcps_persisttimeo++; + STAT(tcpstat.tcps_persisttimeo++); tcp_setpersist(tp); tp->t_force = 1; (void) tcp_output(tp); @@ -275,13 +276,13 @@ tcp_timers(tp, timer) * or drop connection if idle for too long. */ case TCPT_KEEP: - tcpstat.tcps_keeptimeo++; + STAT(tcpstat.tcps_keeptimeo++); if (tp->t_state < TCPS_ESTABLISHED) goto dropit; /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ - if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { - if (tp->t_idle >= tcp_keepidle + tcp_maxidle) + if ((SO_OPTIONS) && tp->t_state <= TCPS_CLOSE_WAIT) { + if (tp->t_idle >= TCPTV_KEEP_IDLE + TCP_MAXIDLE) goto dropit; /* * Send a packet designed to force a response @@ -295,7 +296,7 @@ tcp_timers(tp, timer) * by the protocol spec, this requires the * correspondent TCP to respond. */ - tcpstat.tcps_keepprobe++; + STAT(tcpstat.tcps_keepprobe++); #ifdef TCP_COMPAT_42 /* * The keepalive packet must have nonzero length @@ -307,13 +308,13 @@ tcp_timers(tp, timer) tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt, tp->snd_una - 1, 0); #endif - tp->t_timer[TCPT_KEEP] = tcp_keepintvl; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL; } else - tp->t_timer[TCPT_KEEP] = tcp_keepidle; + tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE; break; dropit: - tcpstat.tcps_keepdrops++; + STAT(tcpstat.tcps_keepdrops++); tp = tcp_drop(tp, 0); /* ETIMEDOUT); */ break; } diff --git a/BasiliskII/src/slirp/tcp_timer.h b/BasiliskII/src/slirp/tcp_timer.h index 73fe2089..f251846b 100644 --- a/BasiliskII/src/slirp/tcp_timer.h +++ b/BasiliskII/src/slirp/tcp_timer.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -122,17 +126,12 @@ char *tcptimers[] = (tv) = (tvmax); \ } -extern int tcp_keepidle; /* time before keepalive probes begin */ -extern int tcp_keepintvl; /* time between keepalive probes */ -extern int tcp_maxidle; /* time to drop after starting probes */ -extern int tcp_ttl; /* time to live for TCP segs */ -extern int tcp_backoff[]; +extern const int tcp_backoff[]; struct tcpcb; -void tcp_fasttimo(void); -void tcp_slowtimo(void); -void tcp_canceltimers(struct tcpcb *); -struct tcpcb * tcp_timers(register struct tcpcb *, int); +void tcp_fasttimo _P((void)); +void tcp_slowtimo _P((void)); +void tcp_canceltimers _P((struct tcpcb *)); #endif diff --git a/BasiliskII/src/slirp/tcp_var.h b/BasiliskII/src/slirp/tcp_var.h index c8e99ae0..82380f93 100644 --- a/BasiliskII/src/slirp/tcp_var.h +++ b/BasiliskII/src/slirp/tcp_var.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -181,6 +185,7 @@ typedef u_int32_t mbufp_32; #endif #define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t)) +#ifdef LOG_ENABLED /* * TCP statistics. * Many of these should be kept per connection, @@ -243,6 +248,8 @@ struct tcpstat { }; extern struct tcpstat tcpstat; /* tcp statistics */ +#endif + extern u_int32_t tcp_now; /* for RFC 1323 timestamps */ #endif diff --git a/BasiliskII/src/slirp/tcpip.h b/BasiliskII/src/slirp/tcpip.h index dff5a3c9..82708b09 100644 --- a/BasiliskII/src/slirp/tcpip.h +++ b/BasiliskII/src/slirp/tcpip.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * diff --git a/BasiliskII/src/slirp/tftp.c b/BasiliskII/src/slirp/tftp.c index 3ba2971c..562ae895 100644 --- a/BasiliskII/src/slirp/tftp.c +++ b/BasiliskII/src/slirp/tftp.c @@ -1,8 +1,8 @@ /* * tftp.c - a simple, read-only tftp server for qemu - * + * * Copyright (c) 2004 Magnus Damm - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -26,15 +26,15 @@ struct tftp_session { int in_use; - char filename[TFTP_FILENAME_MAX]; - + unsigned char filename[TFTP_FILENAME_MAX]; + struct in_addr client_ip; u_int16_t client_port; - + int timestamp; }; -struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; +static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; const char *tftp_prefix; @@ -102,8 +102,15 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, { int fd; int bytes_read = 0; + char buffer[1024]; + int n; - fd = open(spt->filename, O_RDONLY | O_BINARY); + n = snprintf(buffer, sizeof(buffer), "%s/%s", + tftp_prefix, spt->filename); + if (n >= sizeof(buffer)) + return -1; + + fd = open(buffer, O_RDONLY | O_BINARY); if (fd < 0) { return -1; @@ -120,13 +127,53 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, return bytes_read; } -static int tftp_send_error(struct tftp_session *spt, +static int tftp_send_oack(struct tftp_session *spt, + const char *key, uint32_t value, + struct tftp_t *recv_tp) +{ + struct sockaddr_in saddr, daddr; + struct mbuf *m; + struct tftp_t *tp; + int n = 0; + + m = m_get(); + + if (!m) + return -1; + + memset(m->m_data, 0, m->m_size); + + m->m_data += IF_MAXLINKHDR; + tp = (void *)m->m_data; + m->m_data += sizeof(struct udpiphdr); + + tp->tp_op = htons(TFTP_OACK); + n += sprintf(tp->x.tp_buf + n, "%s", key) + 1; + n += sprintf(tp->x.tp_buf + n, "%u", value) + 1; + + saddr.sin_addr = recv_tp->ip.ip_dst; + saddr.sin_port = recv_tp->udp.uh_dport; + + daddr.sin_addr = spt->client_ip; + daddr.sin_port = spt->client_port; + + m->m_len = sizeof(struct tftp_t) - 514 + n - + sizeof(struct ip) - sizeof(struct udphdr); + udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + + return 0; +} + + + +static int tftp_send_error(struct tftp_session *spt, u_int16_t errorcode, const char *msg, struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; + int nobytes; m = m_get(); @@ -136,14 +183,13 @@ static int tftp_send_error(struct tftp_session *spt, memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); - + tp->tp_op = htons(TFTP_ERROR); tp->x.tp_error.tp_error_code = htons(errorcode); - strncpy((char *)tp->x.tp_error.tp_msg, msg, sizeof(tp->x.tp_error.tp_msg)); - tp->x.tp_error.tp_msg[sizeof(tp->x.tp_error.tp_msg)-1] = 0; + strcpy(tp->x.tp_error.tp_msg, msg); saddr.sin_addr = recv_tp->ip.ip_dst; saddr.sin_port = recv_tp->udp.uh_dport; @@ -151,7 +197,9 @@ static int tftp_send_error(struct tftp_session *spt, daddr.sin_addr = spt->client_ip; daddr.sin_port = spt->client_port; - m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - + nobytes = 2; + + m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - sizeof(struct ip) - sizeof(struct udphdr); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); @@ -161,7 +209,7 @@ static int tftp_send_error(struct tftp_session *spt, return 0; } -static int tftp_send_data(struct tftp_session *spt, +static int tftp_send_data(struct tftp_session *spt, u_int16_t block_nr, struct tftp_t *recv_tp) { @@ -182,10 +230,10 @@ static int tftp_send_data(struct tftp_session *spt, memset(m->m_data, 0, m->m_size); - m->m_data += if_maxlinkhdr; + m->m_data += IF_MAXLINKHDR; tp = (void *)m->m_data; m->m_data += sizeof(struct udpiphdr); - + tp->tp_op = htons(TFTP_DATA); tp->x.tp_data.tp_block_nr = htons(block_nr); @@ -207,7 +255,7 @@ static int tftp_send_data(struct tftp_session *spt, return -1; } - m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - + m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct ip) - sizeof(struct udphdr); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); @@ -237,7 +285,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) spt = &tftp_sessions[s]; src = tp->x.tp_buf; - dst = (u_int8_t *)spt->filename; + dst = spt->filename; n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); /* get name */ @@ -249,28 +297,30 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) else { return; } - + if (src[k] == '\0') { break; } } - + if (k >= n) { return; } - + k++; - + /* check mode */ if ((n - k) < 6) { return; } - + if (memcmp(&src[k], "octet\0", 6) != 0) { tftp_send_error(spt, 4, "Unsupported transfer mode", tp); return; } + k += 6; /* skipping octet */ + /* do sanity checks on the filename */ if ((spt->filename[0] != '/') @@ -282,19 +332,60 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) /* only allow exported prefixes */ - if (!tftp_prefix - || (strncmp(spt->filename, tftp_prefix, strlen(tftp_prefix)) != 0)) { + if (!tftp_prefix) { tftp_send_error(spt, 2, "Access violation", tp); return; } /* check if the file exists */ - - if (tftp_read_data(spt, 0, (u_int8_t *)spt->filename, 0) < 0) { + + if (tftp_read_data(spt, 0, spt->filename, 0) < 0) { tftp_send_error(spt, 1, "File not found", tp); return; } + if (src[n - 1] != 0) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + + while (k < n) { + const char *key, *value; + + key = src + k; + k += strlen(key) + 1; + + if (k >= n) { + tftp_send_error(spt, 2, "Access violation", tp); + return; + } + + value = src + k; + k += strlen(value) + 1; + + if (strcmp(key, "tsize") == 0) { + int tsize = atoi(value); + struct stat stat_p; + + if (tsize == 0 && tftp_prefix) { + char buffer[1024]; + int len; + + len = snprintf(buffer, sizeof(buffer), "%s/%s", + tftp_prefix, spt->filename); + + if (stat(buffer, &stat_p) == 0) + tsize = stat_p.st_size; + else { + tftp_send_error(spt, 1, "File not found", tp); + return; + } + } + + tftp_send_oack(spt, "tsize", tsize, tp); + } + } + tftp_send_data(spt, 1, tp); } @@ -308,8 +399,8 @@ static void tftp_handle_ack(struct tftp_t *tp, int pktlen) return; } - if (tftp_send_data(&tftp_sessions[s], - ntohs(tp->x.tp_data.tp_block_nr) + 1, + if (tftp_send_data(&tftp_sessions[s], + ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) { return; } diff --git a/BasiliskII/src/slirp/tftp.h b/BasiliskII/src/slirp/tftp.h index b150a049..8f2675e0 100644 --- a/BasiliskII/src/slirp/tftp.h +++ b/BasiliskII/src/slirp/tftp.h @@ -9,32 +9,25 @@ #define TFTP_DATA 3 #define TFTP_ACK 4 #define TFTP_ERROR 5 +#define TFTP_OACK 6 #define TFTP_FILENAME_MAX 512 -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct tftp_t { struct ip ip; struct udphdr udp; u_int16_t tp_op; union { - struct { + struct { u_int16_t tp_block_nr; u_int8_t tp_buf[512]; } tp_data; - struct { + struct { u_int16_t tp_error_code; u_int8_t tp_msg[512]; } tp_error; u_int8_t tp_buf[512 + 2]; } x; -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; void tftp_input(struct mbuf *m); diff --git a/BasiliskII/src/slirp/udp.c b/BasiliskII/src/slirp/udp.c index 9d805ff3..c48923b0 100644 --- a/BasiliskII/src/slirp/udp.c +++ b/BasiliskII/src/slirp/udp.c @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -33,27 +37,31 @@ /* * Changes and additions relating to SLiRP * Copyright (c) 1995 Danny Gasparovski. - * - * Please read the file COPYRIGHT for the + * + * Please read the file COPYRIGHT for the * terms and conditions of the copyright. */ -#include #include #include "ip_icmp.h" +#ifdef LOG_ENABLED struct udpstat udpstat; +#endif struct socket udb; +static u_int8_t udp_tos(struct socket *so); +static void udp_emu(struct socket *so, struct mbuf *m); + /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ #ifndef COMPAT_42 -int udpcksum = 1; +#define UDPCKSUM 1 #else -int udpcksum = 0; /* XXX */ +#define UDPCKSUM 0 /* XXX */ #endif struct socket *udp_last_so = &udb; @@ -63,8 +71,8 @@ udp_init() { udb.so_next = udb.so_prev = &udb; } -/* m->m_data points at ip packet header - * m->m_len length ip packet +/* m->m_data points at ip packet header + * m->m_len length ip packet * ip->ip_len length data (IPDU) */ void @@ -76,14 +84,14 @@ udp_input(m, iphlen) register struct udphdr *uh; /* struct mbuf *opts = 0;*/ int len; - struct ip save_ip; + struct ip save_ip; struct socket *so; - + DEBUG_CALL("udp_input"); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("iphlen = %d", iphlen); - - udpstat.udps_ipackets++; + + STAT(udpstat.udps_ipackets++); /* * Strip IP options, if any; should skip this, @@ -110,34 +118,34 @@ udp_input(m, iphlen) if (ip->ip_len != len) { if (len > ip->ip_len) { - udpstat.udps_badlen++; + STAT(udpstat.udps_badlen++); goto bad; } m_adj(m, len - ip->ip_len); ip->ip_len = len; } - + /* * Save a copy of the IP header in case we want restore it * for sending an ICMP error message in response. */ - save_ip = *ip; + save_ip = *ip; save_ip.ip_len+= iphlen; /* tcp_input subtracts this */ /* * Checksum extended UDP header and data. */ - if (udpcksum && uh->uh_sum) { + if (UDPCKSUM && uh->uh_sum) { ((struct ipovly *)ip)->ih_next = 0; ((struct ipovly *)ip)->ih_prev = 0; ((struct ipovly *)ip)->ih_x1 = 0; ((struct ipovly *)ip)->ih_len = uh->uh_ulen; /* keep uh_sum for ICMP reply - * uh->uh_sum = cksum(m, len + sizeof (struct ip)); - * if (uh->uh_sum) { + * uh->uh_sum = cksum(m, len + sizeof (struct ip)); + * if (uh->uh_sum) { */ if(cksum(m, len + sizeof(struct ip))) { - udpstat.udps_badsum++; + STAT(udpstat.udps_badsum++); goto bad; } } @@ -165,7 +173,7 @@ udp_input(m, iphlen) if (so->so_lport != uh->uh_sport || so->so_laddr.s_addr != ip->ip_src.s_addr) { struct socket *tmp; - + for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) { if (tmp->so_lport == uh->uh_sport && tmp->so_laddr.s_addr == ip->ip_src.s_addr) { @@ -178,11 +186,11 @@ udp_input(m, iphlen) if (tmp == &udb) { so = NULL; } else { - udpstat.udpps_pcbcachemiss++; + STAT(udpstat.udpps_pcbcachemiss++); udp_last_so = so; } } - + if (so == NULL) { /* * If there's no socket for this packet, @@ -190,22 +198,22 @@ udp_input(m, iphlen) */ if ((so = socreate()) == NULL) goto bad; if(udp_attach(so) == -1) { - DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", + DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", errno,strerror(errno))); sofree(so); goto bad; } - + /* * Setup fields */ /* udp_last_so = so; */ so->so_laddr = ip->ip_src; so->so_lport = uh->uh_sport; - + if ((so->so_iptos = udp_tos(so)) == 0) so->so_iptos = ip->ip_tos; - + /* * XXXXX Here, check if it's in udpexec_list, * and if it is, do the fork_exec() etc. @@ -230,7 +238,7 @@ udp_input(m, iphlen) m->m_data -= iphlen; *ip=save_ip; DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); - icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); + icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); } m_free(so->so_m); /* used for ICMP if error on sorecvfrom */ @@ -248,7 +256,7 @@ bad: return; } -int udp_output2(struct socket *so, struct mbuf *m, +int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos) { @@ -266,19 +274,16 @@ int udp_output2(struct socket *so, struct mbuf *m, */ m->m_data -= sizeof(struct udpiphdr); m->m_len += sizeof(struct udpiphdr); - + /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); - //ui->ui_next = ui->ui_prev = 0; - - memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); - + ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; - ui->ui_len = htons((u_short) (m->m_len - sizeof(struct ip))); /* + sizeof (struct udphdr)); */ + ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ ui->ui_src = saddr->sin_addr; ui->ui_dst = daddr->sin_addr; @@ -290,23 +295,23 @@ int udp_output2(struct socket *so, struct mbuf *m, * Stuff checksum and output datagram. */ ui->ui_sum = 0; - if (udpcksum) { + if (UDPCKSUM) { if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) ui->ui_sum = 0xffff; } - ((struct ip *)ui)->ip_len = (u_int16_t) m->m_len; + ((struct ip *)ui)->ip_len = m->m_len; - ((struct ip *)ui)->ip_ttl = ip_defttl; + ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; - - udpstat.udps_opackets++; - + + STAT(udpstat.udps_opackets++); + error = ip_output(so, m); - + return (error); } -int udp_output(struct socket *so, struct mbuf *m, +int udp_output(struct socket *so, struct mbuf *m, struct sockaddr_in *addr) { @@ -320,7 +325,7 @@ int udp_output(struct socket *so, struct mbuf *m, } daddr.sin_addr = so->so_laddr; daddr.sin_port = so->so_lport; - + return udp_output2(so, m, &saddr, &daddr, so->so_iptos); } @@ -329,22 +334,25 @@ udp_attach(so) struct socket *so; { struct sockaddr_in addr; - + if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) { /* * Here, we bind() the socket. Although not really needed * (sendto() on an unbound socket will bind it), it's done * here so that emulation of ytalk etc. don't have to do it */ - memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = 0; addr.sin_addr.s_addr = INADDR_ANY; if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) { - int error = WSAGetLastError(); + int lasterrno=errno; closesocket(so->s); so->s=-1; - WSASetLastError(error); +#ifdef _WIN32 + WSASetLastError(lasterrno); +#else + errno=lasterrno; +#endif } else { /* success, insert in queue */ so->so_expire = curtime + SO_EXPIRE; @@ -364,7 +372,7 @@ udp_detach(so) sofree(so); } -struct tos_t udptos[] = { +static const struct tos_t udptos[] = { {0, 53, IPTOS_LOWDELAY, 0}, /* DNS */ {517, 517, IPTOS_LOWDELAY, EMU_TALK}, /* talk */ {518, 518, IPTOS_LOWDELAY, EMU_NTALK}, /* ntalk */ @@ -372,12 +380,11 @@ struct tos_t udptos[] = { {0, 0, 0, 0} }; -u_int8_t -udp_tos(so) - struct socket *so; +static u_int8_t +udp_tos(struct socket *so) { int i = 0; - + while(udptos[i].tos) { if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { @@ -386,7 +393,7 @@ udp_tos(so) } i++; } - + return 0; } @@ -397,29 +404,27 @@ udp_tos(so) /* * Here, talk/ytalk/ntalk requests must be emulated */ -void -udp_emu(so, m) - struct socket *so; - struct mbuf *m; +static void +udp_emu(struct socket *so, struct mbuf *m) { struct sockaddr_in addr; - socklen_t addrlen = sizeof(addr); + int addrlen = sizeof(addr); #ifdef EMULATE_TALK CTL_MSG_OLD *omsg; CTL_MSG *nmsg; char buff[sizeof(CTL_MSG)]; u_char type; - + struct talk_request { struct talk_request *next; struct socket *udp_so; struct socket *tcp_so; } *req; - - static struct talk_request *req_tbl = 0; - + + static struct talk_request *req_tbl = 0; + #endif - + struct cu_header { uint16_t d_family; // destination family uint16_t d_port; // destination port @@ -446,7 +451,7 @@ struct cu_header { */ if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) return; - + #define IS_OLD (so->so_emu == EMU_TALK) #define COPY_MSG(dest, src) { dest->type = src->type; \ @@ -469,7 +474,7 @@ struct cu_header { OTOSIN(omsg, ctl_addr)->sin_port = addr.sin_port; OTOSIN(omsg, ctl_addr)->sin_addr = our_addr; strncpy(omsg->l_name, getlogin(), NAME_SIZE_OLD); - } else { /* new talk */ + } else { /* new talk */ omsg = (CTL_MSG_OLD *) buff; nmsg = mtod(m, CTL_MSG *); type = nmsg->type; @@ -477,10 +482,10 @@ struct cu_header { OTOSIN(nmsg, ctl_addr)->sin_addr = our_addr; strncpy(nmsg->l_name, getlogin(), NAME_SIZE_OLD); } - - if (type == LOOK_UP) + + if (type == LOOK_UP) return; /* for LOOK_UP this is enough */ - + if (IS_OLD) { /* make a copy of the message */ COPY_MSG(nmsg, omsg); nmsg->vers = 1; @@ -499,75 +504,75 @@ struct cu_header { * ports, 517 and 518. This is why we have two copies * of the message, one in old talk and one in new talk * format. - */ + */ if (type == ANNOUNCE) { int s; u_short temp_port; - + for(req = req_tbl; req; req = req->next) if (so == req->udp_so) break; /* found it */ - + if (!req) { /* no entry for so, create new */ req = (struct talk_request *) malloc(sizeof(struct talk_request)); req->udp_so = so; - req->tcp_so = solisten(0, - OTOSIN(omsg, addr)->sin_addr.s_addr, + req->tcp_so = solisten(0, + OTOSIN(omsg, addr)->sin_addr.s_addr, OTOSIN(omsg, addr)->sin_port, SS_FACCEPTONCE); req->next = req_tbl; req_tbl = req; - } - + } + /* replace port number in addr field */ addrlen = sizeof(addr); - getsockname(req->tcp_so->s, + getsockname(req->tcp_so->s, (struct sockaddr *) &addr, - &addrlen); + &addrlen); OTOSIN(omsg, addr)->sin_port = addr.sin_port; OTOSIN(omsg, addr)->sin_addr = our_addr; OTOSIN(nmsg, addr)->sin_port = addr.sin_port; - OTOSIN(nmsg, addr)->sin_addr = our_addr; - + OTOSIN(nmsg, addr)->sin_addr = our_addr; + /* send LEAVE_INVITEs */ temp_port = OTOSIN(omsg, ctl_addr)->sin_port; OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0; - omsg->type = nmsg->type = LEAVE_INVITE; - + omsg->type = nmsg->type = LEAVE_INVITE; + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); addr.sin_addr = our_addr; addr.sin_family = AF_INET; addr.sin_port = htons(517); - sendto(s, (char *)omsg, sizeof(*omsg), 0, + sendto(s, (char *)omsg, sizeof(*omsg), 0, (struct sockaddr *)&addr, sizeof(addr)); addr.sin_port = htons(518); sendto(s, (char *)nmsg, sizeof(*nmsg), 0, (struct sockaddr *) &addr, sizeof(addr)); closesocket(s) ; - omsg->type = nmsg->type = ANNOUNCE; + omsg->type = nmsg->type = ANNOUNCE; OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; } - - /* + + /* * If it is a DELETE message, we send a copy to the * local daemons. Then we delete the entry corresponding * to our socket from the request table. */ - + if (type == DELETE) { struct talk_request *temp_req, *req_next; int s; u_short temp_port; - + temp_port = OTOSIN(omsg, ctl_addr)->sin_port; OTOSIN(omsg, ctl_addr)->sin_port = 0; OTOSIN(nmsg, ctl_addr)->sin_port = 0; - + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); addr.sin_addr = our_addr; addr.sin_family = AF_INET; @@ -578,7 +583,7 @@ struct cu_header { sendto(s, (char *)nmsg, sizeof(*nmsg), 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(s); - + OTOSIN(omsg, ctl_addr)->sin_port = temp_port; OTOSIN(nmsg, ctl_addr)->sin_port = temp_port; @@ -601,18 +606,18 @@ struct cu_header { } } } - - return; + + return; #endif - + case EMU_CUSEEME: - + /* * Cu-SeeMe emulation. * Hopefully the packet is more that 16 bytes long. We don't * do any other tests, just replace the address and port * fields. - */ + */ if (m->m_len >= sizeof (*cu_head)) { if (getsockname(so->s, (struct sockaddr *)&addr, &addrlen) < 0) return; @@ -620,7 +625,7 @@ struct cu_header { cu_head->s_port = addr.sin_port; cu_head->so_addr = our_addr.s_addr; } - + return; } } @@ -634,9 +639,8 @@ udp_listen(port, laddr, lport, flags) { struct sockaddr_in addr; struct socket *so; - socklen_t addrlen = sizeof(struct sockaddr_in); - int opt = 1; - + int addrlen = sizeof(struct sockaddr_in), opt = 1; + if ((so = socreate()) == NULL) { free(so); return NULL; @@ -645,7 +649,6 @@ udp_listen(port, laddr, lport, flags) so->so_expire = curtime + SO_EXPIRE; insque(so,&udb); - memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = port; @@ -656,20 +659,20 @@ udp_listen(port, laddr, lport, flags) } setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); /* setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); */ - + getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) so->so_faddr = alias_addr; else so->so_faddr = addr.sin_addr; - + so->so_lport = lport; so->so_laddr.s_addr = laddr; if (flags != SS_FACCEPTONCE) so->so_expire = 0; - + so->so_state = SS_ISFCONNECTED; - + return so; } diff --git a/BasiliskII/src/slirp/udp.h b/BasiliskII/src/slirp/udp.h index 7d844efe..4f69b098 100644 --- a/BasiliskII/src/slirp/udp.h +++ b/BasiliskII/src/slirp/udp.h @@ -10,7 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -42,20 +46,12 @@ extern struct socket *udp_last_so; * Udp protocol header. * Per RFC 768, September, 1981. */ -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(1) -#endif - struct udphdr { u_int16_t uh_sport; /* source port */ u_int16_t uh_dport; /* destination port */ int16_t uh_ulen; /* udp length */ u_int16_t uh_sum; /* udp checksum */ -} PACKED__; - -#ifdef PRAGMA_PACK_SUPPORTED -#pragma pack(PACK_RESET) -#endif +}; /* * UDP kernel structures and variables. @@ -76,6 +72,7 @@ struct udpiphdr { #define ui_ulen ui_u.uh_ulen #define ui_sum ui_u.uh_sum +#ifdef LOG_ENABLED struct udpstat { /* input statistics: */ u_long udps_ipackets; /* total input packets */ @@ -89,6 +86,7 @@ struct udpstat { /* output statistics: */ u_long udps_opackets; /* total output packets */ }; +#endif /* * Names for UDP sysctl objects @@ -96,19 +94,20 @@ struct udpstat { #define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ #define UDPCTL_MAXID 2 +#ifdef LOG_ENABLED extern struct udpstat udpstat; +#endif + extern struct socket udb; struct mbuf; -void udp_init(void); -void udp_input(register struct mbuf *, int); -int udp_output(struct socket *, struct mbuf *, struct sockaddr_in *); -int udp_attach(struct socket *); -void udp_detach(struct socket *); -u_int8_t udp_tos(struct socket *); -void udp_emu(struct socket *, struct mbuf *); -struct socket * udp_listen(u_int, u_int32_t, u_int, int); -int udp_output2(struct socket *so, struct mbuf *m, +void udp_init _P((void)); +void udp_input _P((register struct mbuf *, int)); +int udp_output _P((struct socket *, struct mbuf *, struct sockaddr_in *)); +int udp_attach _P((struct socket *)); +void udp_detach _P((struct socket *)); +struct socket * udp_listen _P((u_int, u_int32_t, u_int, int)); +int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos); #endif