diff options
Diffstat (limited to 'sys/netinet')
35 files changed, 1563 insertions, 268 deletions
diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h index 34ab22bf56f2..47454f89b51d 100644 --- a/sys/netinet/icmp_var.h +++ b/sys/netinet/icmp_var.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)icmp_var.h 7.5 (Berkeley) 6/28/90 - * $Id: icmp_var.h,v 1.2 1993/10/16 18:25:52 rgrimes Exp $ + * $Id: icmp_var.h,v 1.5 1993/12/19 00:52:29 wollman Exp $ */ +#ifndef _NETINET_ICMP_VAR_H_ +#define _NETINET_ICMP_VAR_H_ 1 + /* * Variables related to this implementation * of the internet control message protocol. @@ -43,6 +46,8 @@ struct icmpstat { int icps_error; /* # of calls to icmp_error */ int icps_oldshort; /* no error 'cuz old ip too short */ int icps_oldicmp; /* no error 'cuz old was icmp */ + int icps_oldmcast; /* no error 'cuz old was multicast */ + int icps_oldbadaddr; /* no error 'cuz old had bad address */ int icps_outhist[ICMP_MAXTYPE + 1]; /* statistics related to input messages processed */ int icps_badcode; /* icmp_code out of range */ @@ -54,5 +59,10 @@ struct icmpstat { }; #ifdef KERNEL -struct icmpstat icmpstat; +extern struct icmpstat icmpstat; +extern int icmpprintfs; +extern int ipbroadcastecho; +extern int ipmaskagent; +extern struct sockaddr_in icmpmask; #endif +#endif /* _NETINET_ICMP_VAR_H_ */ diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index ad39b441e26f..ebad56b12dcf 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)if_ether.c 7.13 (Berkeley) 10/31/90 - * $Id: if_ether.c,v 1.3 1993/10/16 18:25:54 rgrimes Exp $ + * $Id: if_ether.c,v 1.4 1993/11/25 01:34:57 wollman Exp $ */ /* @@ -60,6 +60,9 @@ #include "ip.h" #include "if_ether.h" +static void in_arpinput(struct arpcom *, struct mbuf *); +static void arptfree(struct arptab *); + #ifdef GATEWAY #define ARPTAB_BSIZ 16 /* bucket size */ #define ARPTAB_NB 37 /* number of buckets */ @@ -100,6 +103,7 @@ extern struct ifnet loif; /* * Timeout routine. Age arp_tab entries once a minute. */ +void arptimer() { register struct arptab *at; @@ -121,6 +125,7 @@ arptimer() /* * Broadcast an ARP packet, asking who has addr on interface ac. */ +void arpwhohas(ac, addr) register struct arpcom *ac; struct in_addr *addr; @@ -172,6 +177,7 @@ int useloopback = 1; /* use loopback interface for local traffic */ * arptab is also altered from input interrupt service (ecintr/ilintr * calls arpinput when ETHERTYPE_ARP packets come in). */ +int arpresolve(ac, m, destip, desten, usetrailers) register struct arpcom *ac; struct mbuf *m; @@ -270,6 +276,7 @@ arpresolve(ac, m, destip, desten, usetrailers) * is received. Common length and type checks are done here, * then the protocol-specific routine is called. */ +void arpinput(ac, m) struct arpcom *ac; struct mbuf *m; @@ -314,13 +321,14 @@ out: * We reply to requests for ETHERTYPE_TRAIL protocol as well, * but don't normally send requests. */ +void in_arpinput(ac, m) register struct arpcom *ac; struct mbuf *m; { register struct ether_arp *ea; struct ether_header *eh; - register struct arptab *at; /* same as "merge" flag */ + register struct arptab *at = 0; /* same as "merge" flag */ register struct in_ifaddr *ia; struct in_ifaddr *maybe_ia = 0; struct mbuf *mcopy = 0; @@ -469,6 +477,7 @@ out: /* * Free an arptab entry. */ +void arptfree(at) register struct arptab *at; { @@ -524,6 +533,7 @@ out: return (at); } +int arpioctl(cmd, data) int cmd; caddr_t data; diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index 8dc3d26a8c95..787b561e6fdf 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)if_ether.h 7.5 (Berkeley) 6/28/90 - * $Id: if_ether.h,v 1.2 1993/10/16 18:25:55 rgrimes Exp $ + * $Id: if_ether.h,v 1.4 1993/11/25 01:35:01 wollman Exp $ */ +#ifndef _NETINET_IF_ETHER_H_ +#define _NETINET_IF_ETHER_H_ 1 + /* * Structure of a 10Mb/s Ethernet header. */ @@ -102,8 +105,11 @@ struct arptab { }; #ifdef KERNEL -u_char etherbroadcastaddr[6]; +extern u_char etherbroadcastaddr[6]; /* defined in net/if_ethersubr.c */ struct arptab *arptnew(); -int ether_output(), ether_input(); -char *ether_sprintf(); + +extern void ether_input(struct ifnet *, struct ether_header *, struct mbuf *); +extern char *ether_sprintf(u_char *); + #endif +#endif /* _NETINET_IF_ETHER_H_ */ diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 7f989a233e27..2c662e2d6336 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -31,10 +31,11 @@ * SUCH DAMAGE. * * from: @(#)in.c 7.17 (Berkeley) 4/20/91 - * $Id: in.c,v 1.2 1993/10/16 18:25:57 rgrimes Exp $ + * $Id: in.c,v 1.8 1994/01/15 14:29:21 davidg Exp $ */ #include "param.h" +#include "systm.h" #include "ioctl.h" #include "mbuf.h" #include "socket.h" @@ -42,11 +43,13 @@ #include "in_systm.h" #include "net/if.h" #include "net/route.h" -#include "net/af.h" #include "in.h" #include "in_var.h" #ifdef INET + +static void in_ifscrub(struct ifnet *, struct in_ifaddr *); + /* * Formulate an Internet address from network + host. */ @@ -106,6 +109,7 @@ in_netof(in) /* * Compute and save network mask as sockaddr from an internet address. */ +void in_sockmaskof(in, sockmask) struct in_addr in; register struct sockaddr_in *sockmask; @@ -183,16 +187,13 @@ in_lnaof(in) return (host); } -#ifndef SUBNETSARELOCAL -#define SUBNETSARELOCAL 1 -#endif -int subnetsarelocal = SUBNETSARELOCAL; /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal * is true, this includes other subnets of the local net. * Otherwise, it includes only the directly-connected (sub)nets. */ +int in_localaddr(in) struct in_addr in; { @@ -216,6 +217,7 @@ in_localaddr(in) * that may not be forwarded, or whether datagrams to that destination * may be forwarded. */ +int in_canforward(in) struct in_addr in; { @@ -226,20 +228,20 @@ in_canforward(in) return (0); if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; - if (net == 0 || net == IN_LOOPBACKNET) + if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) return (0); } return (1); } -int in_interfaces; /* number of external internet interfaces */ -extern struct ifnet loif; +static int in_interfaces; /* number of external internet interfaces */ /* * Generic internet control operations (ioctl's). * Ifp is 0 if not an interface-specific ioctl. */ /* ARGSUSED */ +int in_control(so, cmd, data, ifp) struct socket *so; int cmd; @@ -364,7 +366,8 @@ in_control(so, cmd, data, ifp) oldaddr = ia->ia_dstaddr; ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; if (ifp->if_ioctl && - (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { + (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, + (caddr_t)ia))) { ia->ia_dstaddr = oldaddr; return (error); } @@ -463,6 +466,7 @@ in_control(so, cmd, data, ifp) /* * Delete any existing route for an interface. */ +static void in_ifscrub(ifp, ia) register struct ifnet *ifp; register struct in_ifaddr *ia; @@ -481,10 +485,12 @@ in_ifscrub(ifp, ia) * Initialize an interface's internet address * and routing table entry. */ +int in_ifinit(ifp, ia, sin, scrub) register struct ifnet *ifp; register struct in_ifaddr *ia; struct sockaddr_in *sin; + int scrub; { register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; @@ -497,7 +503,8 @@ in_ifinit(ifp, ia, sin, scrub) * if this is its first address, * and to validate the address if necessary. */ - if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { + if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, + (caddr_t)ia))) { splx(s); ia->ia_addr = oldaddr; return (error); @@ -571,6 +578,7 @@ in_iaonnetof(net) /* * Return 1 if the address might be a local broadcast address. */ +int in_broadcast(in) struct in_addr in; { diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 89a9da45a500..48f24b39ede4 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)in.h 7.11 (Berkeley) 4/20/91 - * $Id: in.h,v 1.3 1993/10/16 18:25:58 rgrimes Exp $ + * $Id: in.h,v 1.4 1993/12/19 00:52:35 wollman Exp $ */ #ifndef _NETINET_IN_H_ @@ -82,33 +82,33 @@ struct in_addr { * On subnets, the decomposition of addresses to host and net parts * is done according to subnet mask, not the masks here. */ -#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0) -#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA(i) (((u_long)(i) & 0x80000000UL) == 0) +#define IN_CLASSA_NET 0xff000000UL #define IN_CLASSA_NSHIFT 24 -#define IN_CLASSA_HOST 0x00ffffff +#define IN_CLASSA_HOST 0x00ffffffUL #define IN_CLASSA_MAX 128 -#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000) -#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB(i) (((u_long)(i) & 0xc0000000UL) == 0x80000000UL) +#define IN_CLASSB_NET 0xffff0000UL #define IN_CLASSB_NSHIFT 16 -#define IN_CLASSB_HOST 0x0000ffff +#define IN_CLASSB_HOST 0x0000ffffUL #define IN_CLASSB_MAX 65536 -#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000) -#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC(i) (((u_long)(i) & 0xe0000000UL) == 0xc0000000UL) +#define IN_CLASSC_NET 0xffffff00UL #define IN_CLASSC_NSHIFT 8 -#define IN_CLASSC_HOST 0x000000ff +#define IN_CLASSC_HOST 0x000000ffUL -#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_CLASSD(i) (((u_long)(i) & 0xf0000000UL) == 0xe0000000UL) #define IN_MULTICAST(i) IN_CLASSD(i) -#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000) -#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000) +#define IN_EXPERIMENTAL(i) (((u_long)(i) & 0xe0000000UL) == 0xe0000000UL) +#define IN_BADCLASS(i) (((u_long)(i) & 0xf0000000UL) == 0xf0000000UL) -#define INADDR_ANY (u_long)0x00000000 -#define INADDR_BROADCAST (u_long)0xffffffff /* must be masked */ +#define INADDR_ANY 0x00000000UL +#define INADDR_BROADCAST 0xffffffffUL /* must be masked */ #ifndef KERNEL -#define INADDR_NONE 0xffffffff /* -1 return */ +#define INADDR_NONE 0xffffffffUL /* -1 return */ #endif #define IN_LOOPBACKNET 127 /* official! */ @@ -150,8 +150,18 @@ struct ip_opts { #define IP_RETOPTS 8 /* ip_opts; set/get IP per-packet options */ #ifdef KERNEL -struct in_addr in_makeaddr(); -u_long in_netof(), in_lnaof(); -#endif +/* From in.c: */ +extern struct in_addr in_makeaddr(u_long, u_long); +extern u_long in_netof(struct in_addr); +extern void in_sockmaskof(struct in_addr, struct sockaddr_in *); +extern u_long in_lnaof(struct in_addr); +extern int in_localaddr(struct in_addr); +extern int in_canforward(struct in_addr); +struct socket; struct ifnet; +extern int in_control(struct socket *, int, caddr_t, struct ifnet *); +struct in_ifaddr; +extern int in_broadcast(struct in_addr); + +#endif /* KERNEL */ #endif /* _NETINET_IN_H_ */ diff --git a/sys/netinet/in_mtudisc.c b/sys/netinet/in_mtudisc.c new file mode 100644 index 000000000000..db74443bf8c6 --- /dev/null +++ b/sys/netinet/in_mtudisc.c @@ -0,0 +1,377 @@ +/*- + * Copyright (c) 1993, University of Vermont and State + * Agricultural College. + * Copyright (c) 1993, Garrett A. Wollman. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND AUTHOR ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: in_mtudisc.c,v 1.2 1993/12/19 00:52:36 wollman Exp $ + */ + +#ifdef MTUDISC + +#include "param.h" +#include "systm.h" +#include "kernel.h" +#include "mbuf.h" +#include "socket.h" +#include "socketvar.h" +#include "in_systm.h" +#include "net/if.h" +#include "net/route.h" +#include "in.h" +#include "in_var.h" +#include "ip.h" +#include "protosw.h" +#include "in_pcb.h" + +#ifdef INET + +/* + * checkpcbs[] lists all the PCB heads that might call on the services + * of MTU discovery. + * This is really bogus 'cuz a ULP needs to both get its entry added here + * /and/ set INP_DISCOVERMTU in each PCB. + */ +extern struct inpcb tcb; /* XXX move to header file */ + +struct inpcb *checkpcbs[] = { + &tcb, + 0 +}; + + +/* + * Table of likely MTU values, courtesy of RFC 1191. + * This MUST remain in sorted order. + */ +static const u_short in_mtus[] = { + 65535, /* maximum */ + 32767, /* convenient power of 2 - 1 */ + 17914, /* 16Mb Token Ring */ + 16383, /* convenient power of 2 - 1 */ + 8166, /* IEEE 802.4 */ + 6288, /* convenient stopping point */ + 4352, /* FDDI */ + 3144, /* convenient stopping point */ + 2002, /* IEEE 802.5 */ + 1492, /* IEEE 802.3 */ + 1006, /* BBN 1822 */ + 508, /* ARCNET */ + 296, /* SLIP, PPP */ + 128 /* minimum we'll accept */ +}; + +#define NMTUS ((sizeof in_mtus)/(sizeof in_mtus[0])) + +/* + * Find the next MTU in the sequence from CURRENT. + * If HIGHER, increase size; else decrease. + * Return of zero means we're stuck. + * NB: We might be called with a CURRENT MTU that's not in the + * table (as, for example, when an ICMP tells us there's a problem + * and reports a max path MTU value). + */ +unsigned +in_nextmtu(unsigned current, int higher) { + int i; + + for(i = 0; i < NMTUS; i++) { + if(in_mtus[i] <= (u_short)current) + break; + } + + if(i == NMTUS) { + if(higher) return in_mtus[NMTUS - 1]; + else return 0; /* error return */ + } + + /* + * Now we know that CURRENT lies somewhere in the interval + * (in_mtus[i - 1], in_mtus[i]]. If we want to go higher, + * take in_mtus[i - 1] always. If we want to go lower, we + * must check the lower bound to see if it's equal, and if so, + * take in_mtus[i + 1], unless i == NMTUS - 1, in which case + * we return failure. + * Got that? + */ + if(higher) + return in_mtus[(i >= 1) ? (i - 1) : 0]; + + /* now we know it's lower */ + if(current == in_mtus[i]) { + if(i == NMTUS - 1) + return 0; + else + return in_mtus[i + 1]; + } + + return in_mtus[i]; +} + +/* + * Set up the route to do MTU discovery. This only works for host routes, + * not net routes; in any case, ALL systems should have all IP routes + * marked with RTF_CLONING (and a genmask of zero), which will do the right + * thing, and also arrange for the pre-ARPing code to get called on + * on appropriate interfaces. + * + * We also go to some pains to keep listeners on the routing socket aware + * of what's going on when we fiddle the flags or metrics. I don't know + * if this is really necessary or not (or even if we're doing it in the + * right way). + */ +int in_routemtu(struct route *ro) { + if(!ro->ro_rt) + return 0; + + if((ro->ro_rt->rt_flags & (RTF_HOST | RTF_UP)) != (RTF_HOST | RTF_UP)) + return 0; + + if(ro->ro_rt->rt_rmx.rmx_mtu) { + /* + * Let the user know that we've turned on MTU discovery for this + * route entry. This doesn't do anything at present, but may + * be useful later on. + */ + if(!(ro->ro_rt->rt_flags & RTF_PROTO1)) { + ro->ro_rt->rt_flags |= RTF_PROTO1; + } + return 1; + } + + if(ro->ro_rt->rt_ifp && !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU)) { + ro->ro_rt->rt_flags |= RTF_PROTO1; + /* + * Subtraction is necessary because the interface's MTU includes + * the interface's own headers. We subtract the header length + * provided and hope for the best. + */ + ro->ro_rt->rt_rmx.rmx_mtu = + ro->ro_rt->rt_ifp->if_mtu - ro->ro_rt->rt_ifp->if_hdrlen; + return 1; + } + return 0; +} + +/* + * Perform the PCB fiddling necessary when the route changes. + * Protect against recursion, since we might get called as a + * result of notifying someone else that the MTU is changing. + */ +void +in_pcbmtu(struct inpcb *inp) { + static int notifying = 0; + static int timerstarted = 0; + unsigned oldmtu = inp->inp_pmtu; + int oldflags = inp->inp_flags; + + if (!timerstarted) { + timeout(in_mtutimer, 0, 60 * hz); + timerstarted = 1; + } + + if (inp->inp_flags & INP_DISCOVERMTU) { + /* + * If no route present, get one. + * If there is one present, but it's marked as being `down', + * try to get another one. + */ + if(!inp->inp_route.ro_rt) + rtalloc(&inp->inp_route); + else if((inp->inp_route.ro_rt->rt_flags & RTF_UP) == 0) { + RTFREE(inp->inp_route.ro_rt); + inp->inp_route.ro_rt = 0; + rtalloc(&inp->inp_route); + } + + if(in_routemtu(&inp->inp_route)) { + inp->inp_flags |= INP_MTUDISCOVERED; + inp->inp_pmtu = inp->inp_route.ro_rt->rt_rmx.rmx_mtu; + inp->inp_ip.ip_off |= IP_DF; + } else { + inp->inp_flags &= ~INP_MTUDISCOVERED; + inp->inp_ip.ip_off &= ~IP_DF; + } + /* + * If nothing has changed since the last value we had, + * don't waste any time notifying everybody that nothing + * has changed. + */ + if(inp->inp_pmtu != oldmtu + || (inp->inp_flags ^ oldflags)) { + notifying = 1; + /* + * If the MTU has decreased, use timer 2. + */ + inp->inp_mtutimer = + (inp->inp_pmtu < oldmtu) ? in_mtutimer2 : in_mtutimer1; + in_mtunotify(inp); + notifying = 0; + } + } +} + +/* + * Tell the clients that have the same destination as INP that they + * need to take a new look at the MTU value and flags. + */ +void +in_mtunotify(struct inpcb *inp) { + in_pcbnotify(inp->inp_head, &inp->inp_route.ro_dst, 0, zeroin_addr, + 0, PRC_MTUCHANGED, inp->inp_mtunotify); +} + +/* + * Adjust the MTU listed in the route on the basis of an ICMP + * Unreachable: Need Fragmentation message. + * Note that the PRC_MSGSIZE error is still delivered; this just + * makes the adjustment in the route, and depends on the ULPs which + * are required to translate PRC_MSGSIZE into an in_pcbmtu() which will + * pick up the new size. + */ +void +in_mtureduce(struct in_addr dst, unsigned newsize) { + struct route ro; + + ro.ro_dst.sa_family = AF_INET; + ro.ro_dst.sa_len = sizeof ro.ro_dst; + ((struct sockaddr_in *)&ro.ro_dst)->sin_addr = dst; + ro.ro_rt = 0; + rtalloc(&ro); + + /* + * If there was no route, just forget about it, can't do anything. + */ + if(!ro.ro_rt) + return; + + /* + * If there was a route, but it's the wrong kind, forget it. + */ + if((ro.ro_rt->rt_flags & (RTF_UP | RTF_HOST)) != (RTF_UP | RTF_HOST)) { + RTFREE(ro.ro_rt); + return; + } + + /* + * If the MTU is locked by some outside agency, forget it. + */ + if(ro.ro_rt->rt_rmx.rmx_locks & RTV_MTU) { + RTFREE(ro.ro_rt); + return; + } + + /* + * If newsize == 0, then we got an ICMP from a router + * which doesn't support the MTU extension, so just go down one. + */ + newsize = in_nextmtu(ro.ro_rt->rt_rmx.rmx_mtu, 0); + + if(!newsize) { + ro.ro_rt->rt_rmx.rmx_mtu = 0; /* we can't go any lower */ + RTFREE(ro.ro_rt); + return; + } + /* + * If the new MTU is greater than the old MTU, forget it. (Prevent + * denial-of-service attack.) Don't bother if the new MTU is the + * same as the old one. + */ + if(ro.ro_rt->rt_rmx.rmx_mtu <= newsize) { + RTFREE(ro.ro_rt); + return; + } + + /* + * OK, do it. + */ + ro.ro_rt->rt_rmx.rmx_mtu = newsize; + RTFREE(ro.ro_rt); +} + +/* + * Walk through all the PCB lists in checkpcbs[] and decrement the + * timers on the ones still participating in MTU discovery. + * If the timers reach zero, bump the MTU (clamped to the interface + * MTU), assuming the route is still good. + */ +void +in_mtutimer(caddr_t dummy1, int dummy2) { + int i; + struct inpcb *inp; + struct rtentry *rt; + int s = splnet(); + + for(i = 0; checkpcbs[i]; i++) { + inp = checkpcbs[i]; + + while(inp = inp->inp_next) { + if(inp->inp_flags & INP_MTUDISCOVERED) { + if(!inp->inp_route.ro_rt + || !(inp->inp_route.ro_rt->rt_flags & RTF_UP)) { + inp->inp_flags &= ~INP_MTUDISCOVERED; + continue; /* we'll notice it later */ + } + + if(--inp->inp_mtutimer == 0) { + in_bumpmtu(inp); + inp->inp_mtutimer = in_mtutimer1; + if(inp->inp_route.ro_rt->rt_rmx.rmx_rtt + && ((in_mtutimer1 * 60) + > (inp->inp_route.ro_rt->rt_rmx.rmx_rtt / RTM_RTTUNIT))) { + inp->inp_mtutimer = + inp->inp_route.ro_rt->rt_rmx.rmx_rtt / RTM_RTTUNIT; + } + } + } + } + } + splx(s); + timeout(in_mtutimer, (caddr_t)0, 60 * hz); +} + +/* + * Try to increase the MTU and let everyone know that it has changed. + * Must be called with a valid route in inp->inp_route. Probably + * must be at splnet(), too. + */ +void +in_bumpmtu(struct inpcb *inp) { + struct route *ro; + unsigned newmtu; + + ro = &inp->inp_route; + newmtu = in_nextmtu(inp->inp_pmtu, 1); + if(!newmtu) return; /* doing the best we can */ + if(newmtu <= ro->ro_rt->rt_ifp->if_mtu) { + if(!(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU)) { + ro->ro_rt->rt_rmx.rmx_mtu = newmtu; + in_pcbmtu(inp); + } + } +} + +#endif /* INET */ +#endif /* MTUDISC */ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 3d333bcfc6fd..cc404e6f1510 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)in_pcb.c 7.14 (Berkeley) 4/20/91 - * $Id: in_pcb.c,v 1.2 1993/10/16 18:26:01 rgrimes Exp $ + * $Id: in_pcb.c,v 1.5 1993/12/19 00:52:37 wollman Exp $ */ #include "param.h" @@ -52,8 +52,7 @@ #include "in_pcb.h" #include "in_var.h" -struct in_addr zeroin_addr; - +int in_pcballoc(so, head) struct socket *so; struct inpcb *head; @@ -72,6 +71,7 @@ in_pcballoc(so, head) return (0); } +int in_pcbbind(inp, nam) register struct inpcb *inp; struct mbuf *nam; @@ -135,12 +135,13 @@ noname: * If don't have a local address for this socket yet, * then pick one. */ +int in_pcbconnect(inp, nam) register struct inpcb *inp; struct mbuf *nam; { struct in_ifaddr *ia; - struct sockaddr_in *ifaddr; + struct sockaddr_in *ifaddr = 0; register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); if (nam->m_len != sizeof (*sin)) @@ -232,19 +233,31 @@ in_pcbconnect(inp, nam) } inp->inp_faddr = sin->sin_addr; inp->inp_fport = sin->sin_port; +#ifdef MTUDISC + /* + * If the upper layer asked for PMTU discovery services, see + * if we can get an idea of what the MTU should be... + */ + in_pcbmtu(inp); +#endif /* MTUDISC */ return (0); } +void in_pcbdisconnect(inp) struct inpcb *inp; { inp->inp_faddr.s_addr = INADDR_ANY; inp->inp_fport = 0; +#ifdef MTUDISC + inp->inp_flags &= ~INP_MTUDISCOVERED; +#endif if (inp->inp_socket->so_state & SS_NOFDREF) in_pcbdetach(inp); } +void in_pcbdetach(inp) struct inpcb *inp; { @@ -260,6 +273,7 @@ in_pcbdetach(inp) (void) m_free(dtom(inp)); } +void in_setsockaddr(inp, nam) register struct inpcb *inp; struct mbuf *nam; @@ -275,6 +289,7 @@ in_setsockaddr(inp, nam) sin->sin_addr = inp->inp_laddr; } +void in_setpeeraddr(inp, nam) struct inpcb *inp; struct mbuf *nam; @@ -301,18 +316,18 @@ in_setpeeraddr(inp, nam) * * Must be called at splnet. */ +void in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify) struct inpcb *head; struct sockaddr *dst; u_short fport, lport; struct in_addr laddr; - int cmd, (*notify)(); + int cmd; + void (*notify)(struct inpcb *, int); { register struct inpcb *inp, *oinp; struct in_addr faddr; int errno; - int in_rtchange(); - extern u_char inetctlerrmap[]; if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET) return; @@ -324,14 +339,16 @@ in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify) * Redirects go to all references to the destination, * and use in_rtchange to invalidate the route cache. * Dead host indications: notify all references to the destination. + * MTU change indications: same thing. * Otherwise, if we have knowledge of the local port and address, * deliver only to that socket. */ - if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { + if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD + || cmd == PRC_MTUCHANGED) { fport = 0; lport = 0; laddr.s_addr = 0; - if (cmd != PRC_HOSTDEAD) + if (cmd != PRC_HOSTDEAD && cmd != PRC_MTUCHANGED) notify = in_rtchange; } errno = inetctlerrmap[cmd]; @@ -357,6 +374,7 @@ in_pcbnotify(head, dst, fport, laddr, lport, cmd, notify) * routing information. If the route was created dynamically * (by a redirect), time to try a default gateway again. */ +void in_losing(inp) struct inpcb *inp; { @@ -372,10 +390,14 @@ in_losing(inp) (struct rtentry **)0); inp->inp_route.ro_rt = 0; rtfree(rt); + +#ifdef MTUDISC /* - * A new route can be allocated - * the next time output is attempted. + * When doing MTU discovery, we want to find out as + * quickly as possible what the MTU of the new route is. */ + in_pcbmtu(inp); +#endif /* MTUDISC */ } } @@ -383,16 +405,22 @@ in_losing(inp) * After a routing change, flush old routing * and allocate a (hopefully) better one. */ -in_rtchange(inp) +void +in_rtchange(inp, errno) register struct inpcb *inp; + int errno; { if (inp->inp_route.ro_rt) { rtfree(inp->inp_route.ro_rt); inp->inp_route.ro_rt = 0; +#ifdef MTUDISC /* * A new route can be allocated the next time - * output is attempted. + * output is attempted, but make sure to let + * MTU discovery know about it. */ + in_pcbmtu(inp); +#endif /* MTUDISC */ } } diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 92e3ddf0a315..e4adb614e6d4 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)in_pcb.h 7.6 (Berkeley) 6/28/90 - * $Id: in_pcb.h,v 1.2 1993/10/16 18:26:03 rgrimes Exp $ + * $Id: in_pcb.h,v 1.5 1993/11/25 01:35:06 wollman Exp $ */ +#ifndef _NETINET_IN_PCB_H_ +#define _NETINET_IN_PCB_H_ 1 + /* * Common structure pcb for internet protocol implementation. * Here are stored pointers to local and foreign host table @@ -56,12 +59,24 @@ struct inpcb { int inp_flags; /* generic IP/datagram flags */ struct ip inp_ip; /* header prototype; should have more */ struct mbuf *inp_options; /* IP options */ +#ifdef MTUDISC + int inp_pmtu; /* path mtu if INP_MTUDISCOVERED */ + int inp_mtutimer; /* decremented once a minute to + try to increase mtu */ + int (*inp_mtunotify)(struct inpcb *, int); + /* function to call when MTU may have + * changed */ +#endif /* MTUDISC */ }; /* flags in inp_flags: */ #define INP_RECVOPTS 0x01 /* receive incoming IP options */ #define INP_RECVRETOPTS 0x02 /* receive IP options for reply */ #define INP_RECVDSTADDR 0x04 /* receive IP dst address */ +#ifdef MTUDISC +#define INP_DISCOVERMTU 0x08 /* practice Path MTU discovery */ +#define INP_MTUDISCOVERED 0x10 /* we were able to get such a route */ +#endif /* MTUDISC */ #define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR) #ifdef sotorawcb @@ -88,5 +103,24 @@ struct raw_inpcb { #define sotorawinpcb(so) ((struct raw_inpcb *)(so)->so_pcb) #ifdef KERNEL -struct inpcb *in_pcblookup(); -#endif +/* From in_pcb.h: */ +extern int in_pcballoc(struct socket *, struct inpcb *); +extern int in_pcbbind(struct inpcb *, struct mbuf *); +extern int in_pcbconnect(struct inpcb *, struct mbuf *); +extern void in_pcbdisconnect(struct inpcb *); +extern void in_pcbdetach(struct inpcb *); +extern void in_setsockaddr(struct inpcb *, struct mbuf *); +extern void in_setpeeraddr(struct inpcb *, struct mbuf *); +extern void in_pcbnotify(struct inpcb *, struct sockaddr *, int, struct in_addr, int, int, void (*)(struct inpcb *, int)); +extern void in_losing(struct inpcb *); +extern void in_rtchange(struct inpcb *, int); +extern struct inpcb *in_pcblookup(struct inpcb *, struct in_addr, int, struct in_addr, int, int); + + +#ifdef MTUDISC +extern void in_pcbmtu(struct inpcb *); +extern void in_mtunotify(struct inpcb *); +extern void in_bumpmtu(struct inpcb *); +#endif /* MTUDISC */ +#endif /* KERNEL */ +#endif /* _NETINET_IN_PCB_H_ */ diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index 2aa8279328df..dc147f090b51 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)in_proto.c 7.5 (Berkeley) 6/28/90 - * $Id: in_proto.c,v 1.2 1993/10/16 18:26:04 rgrimes Exp $ + * $Id: in_proto.c,v 1.3 1993/12/19 00:52:38 wollman Exp $ */ #include "param.h" @@ -39,23 +39,52 @@ #include "protosw.h" #include "domain.h" #include "mbuf.h" +#include "net/if.h" +#include "net/route.h" #include "in.h" #include "in_systm.h" +#include "in_var.h" /* IP prototypes */ + +#include "ip.h" +#include "ip_var.h" /* more IP prototypes */ + +#include "ip_icmp.h" +#include "icmp_var.h" /* ICMP prototypes */ + +#include "udp.h" +#include "udp_var.h" /* UDP prototypes */ + +#include "tcp.h" +#include "tcp_fsm.h" +#include "tcp_seq.h" +#include "tcp_timer.h" +#include "tcp_var.h" /* TCP prototypes */ /* * TCP/IP protocol family: IP, ICMP, UDP, TCP. */ -int ip_output(),ip_ctloutput(); -int ip_init(),ip_slowtimo(),ip_drain(); -int icmp_input(); -int udp_input(),udp_ctlinput(); -int udp_usrreq(); -int udp_init(); -int tcp_input(),tcp_ctlinput(); -int tcp_usrreq(),tcp_ctloutput(); -int tcp_init(),tcp_fasttimo(),tcp_slowtimo(),tcp_drain(); -int rip_input(),rip_output(),rip_ctloutput(), rip_usrreq(); +in_output_t ip_output; +in_ctloutput_t ip_ctloutput; +void ip_init(); +void ip_slowtimo(); +void ip_drain(); +in_input_t udp_input; +in_ctlinput_t udp_ctlinput; +int udp_usrreq(); +void udp_init(); +in_input_t tcp_input; +in_ctlinput_t tcp_ctlinput; +int tcp_usrreq(); +in_ctloutput_t tcp_ctloutput; +void tcp_init(); +void tcp_fasttimo(); +void tcp_slowtimo(); +void tcp_drain(); +in_input_t rip_input; +in_output_t rip_output; +in_ctloutput_t rip_ctloutput; +int rip_usrreq(); /* * IMP protocol family: raw interface. * Using the raw interface entry to get the timer routine @@ -63,25 +92,34 @@ int rip_input(),rip_output(),rip_ctloutput(), rip_usrreq(); */ #include "imp.h" #if NIMP > 0 -int rimp_output(), hostslowtimo(); +int rimp_output(); +void hostslowtimo(); #endif #ifdef NSIP -int idpip_input(), nsip_ctlinput(); +in_input_t idpip_input; +in_ctlinput_t nsip_ctlinput; #endif #ifdef TPIP -int tpip_input(), tpip_ctlinput(), tp_ctloutput(), tp_usrreq(); -int tp_init(), tp_slowtimo(), tp_drain(); +in_input_t tpip_input; +in_ctlinput_t tpip_ctlinput; +in_ctloutput_t tp_ctloutput; +int tp_usrreq(); +void tp_init(); +void tp_slowtimo(); +void tp_drain(); #endif #ifdef EON -int eoninput(), eonctlinput(), eonprotoinit(); -#endif EON +in_input_t eoninput; +in_ctlinput_t eonctlinput; +void eonprotoinit(); +#endif /* EON */ extern struct domain inetdomain; -struct protosw inetsw[] = { +struct in_protosw inetsw[] = { { 0, &inetdomain, 0, 0, 0, ip_output, 0, 0, 0, @@ -138,8 +176,10 @@ struct protosw inetsw[] = { }; struct domain inetdomain = - { AF_INET, "internet", 0, 0, 0, - inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])] }; +{ AF_INET, "internet", 0, 0, 0, + (struct protosw *)inetsw, + (struct protosw *)&inetsw[sizeof(inetsw)/sizeof(inetsw[0])] +}; #if NIMP > 0 extern struct domain impdomain; diff --git a/sys/netinet/in_systm.h b/sys/netinet/in_systm.h index ad2c205f7269..6faca52cd61e 100644 --- a/sys/netinet/in_systm.h +++ b/sys/netinet/in_systm.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)in_systm.h 7.4 (Berkeley) 6/28/90 - * $Id: in_systm.h,v 1.2 1993/10/16 18:26:06 rgrimes Exp $ + * $Id: in_systm.h,v 1.3 1993/11/07 17:47:52 wollman Exp $ */ +#ifndef _NETINET_IN_SYSTM_H_ +#define _NETINET_IN_SYSTM_H_ 1 + /* * Miscellaneous internetwork * definitions for kernel. @@ -55,3 +58,4 @@ typedef u_long n_time; /* ms since 00:00 GMT, byte rev */ #ifdef KERNEL n_time iptime(); #endif +#endif /* _NETINET_IN_SYSTM_H_ */ diff --git a/sys/netinet/in_var.c b/sys/netinet/in_var.c new file mode 100644 index 000000000000..4a292b000d6a --- /dev/null +++ b/sys/netinet/in_var.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: in_var.c,v 1.1 1993/12/09 03:43:29 wollman Exp $ + */ + +/* + * This file attempts to centralize all the various variables that have + * a hand in controlling the operation of IP and its ULPs. + */ + +#include "param.h" +#include "systm.h" +#include "mbuf.h" +#include "domain.h" +#include "protosw.h" +#include "socket.h" +#include "time.h" +#include "net/if.h" +#include "net/route.h" + +#include "in.h" +#include "in_systm.h" +#include "ip.h" +#include "in_pcb.h" +#include "in_var.h" +#include "ip_var.h" +#include "ip_icmp.h" +#include "icmp_var.h" + + +/* + * IPFORWARDING controls whether the IP layer will forward packets received + * by us but not addressed to one of our addresses. + * + * IPSENDREDIRECTS controls whether the IP layer will send ICMP Redirect + * messages. + * + * GATEWAY turns both of these on, and also allocates more memory for some + * networking functions. + */ + +#ifndef IPFORWARDING +#ifdef GATEWAY +#define IPFORWARDING 1 /* forward IP packets not for us */ +#else /* not GATEWAY */ +#define IPFORWARDING 0 /* don't forward IP packets not for us */ +#endif /* not GATEWAY */ +#endif /* not IPFORWARDING */ + +/* + * NB: RFC 1122, ``Requirements for Internet Hosts: Communication Layers'', + * absolutely forbids hosts (which are not acting as gateways) from sending + * ICMP redirects. + */ +#ifndef IPSENDREDIRECTS +#ifdef GATEWAY +#define IPSENDREDIRECTS 1 +#else /* not GATEWAY */ +#define IPSENDREDIRECTS 0 +#endif /* not GATEWAY */ +#endif /* not IPSENDREDIRECTS */ + +int ipforwarding = IPFORWARDING; +int ipsendredirects = IPSENDREDIRECTS; +#ifdef DIAGNOSTIC +int ipprintfs = 0; +#endif + +/* + * ip_protox[] maps from IP protocol number to an index in inetsw[]. + */ +u_char ip_protox[IPPROTO_MAX]; + +/* + * ipqmaxlen is the maximum length of the IP input queue. + * ipintrq is the queue itself. + */ +struct ifqueue ipintrq; +int ipqmaxlen = IFQ_MAXLEN; + +/* + * the IP reassembly queue + */ +struct ipq ipq; + +/* + * in_ifaddr points to a linked list of IP interface addresses, managed + * by the code in in.c. + */ +struct in_ifaddr *in_ifaddr; /* first inet address */ + +/* + * statistics for netstat and management + */ +struct ipstat ipstat; + +/* + * ip_id is the next IP packet id number to be assigned (used in fragmentation + * and reassembly). + */ +u_short ip_id; + +/* + * When acting as a gateway, the IP layer keeps track of how many packets + * are forwarded for each (in-ifp, out-ifp) pair. This code needs to get + * updated or junked now that interfaces can come and go like the wind. + * (in ip_input.c) + */ +#ifdef GATEWAY +u_long *ip_ifmatrix; +#endif + +/* + * ipaddr is a sockaddr_in used by various bits of code when they + * need to convert a `struct in_addr' to a `struct sockaddr_in'. + * + * ipforward_rt is a route used when forwarding packets. It functions + * as a route cache of order one, if you want to think of it that way. + */ +struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; +struct route ipforward_rt; + +/* + * inetctlerrmap[] maps control input commands to errno values. 0 means + * don't signal error. + */ +u_char inetctlerrmap[PRC_NCMDS] = { + 0, /* ifdown */ + 0, /* routedead */ + 0, /* #2 */ + 0, /* quench2 */ + 0, /* quench */ + EMSGSIZE, /* msgsize */ + EHOSTDOWN, /* hostdead */ + EHOSTUNREACH, /* hostunreach */ + EHOSTUNREACH, /* unreachnet */ + EHOSTUNREACH, /* unreachhost */ + ECONNREFUSED, /* unreachproto */ + ECONNREFUSED, /* unreachport */ + EMSGSIZE, /* old needfrag */ + EHOSTUNREACH, /* srcfail */ + EHOSTUNREACH, /* netunknown */ + EHOSTUNREACH, /* hostunknown */ + EHOSTUNREACH, /* isolated */ + ECONNREFUSED, /* net admin. prohibited */ + ECONNREFUSED, /* host admin. prohibited */ + EHOSTUNREACH, /* tos net unreachable */ + EHOSTUNREACH, /* tos host unreachable */ + 0, /* redirect net */ + 0, /* redirect host */ + 0, /* redirect tosnet */ + 0, /* redirect toshost */ + 0, /* time exceeded */ + 0, /* reassembly timeout */ + ENOPROTOOPT, /* parameter problem */ + ENOPROTOOPT, /* required option missing */ + 0, /* MTU changed */ + /* NB: this means that this error will only + get propagated by in_mtunotify(), which + doesn't bother to check. */ +}; + +/* + * SUBNETSARELOCAL determines where IP subnets are considered to be ``local'' + * or not. This option is obsolete. + */ +#ifndef SUBNETSARELOCAL +#define SUBNETSARELOCAL 1 +#endif +int subnetsarelocal = SUBNETSARELOCAL; + +#ifdef MTUDISC +/* + * MTUTIMER1 is the number of minutes to wait after having incremented + * the MTU estimate before trying again. MTUTIMER2 is the number + * of minutes to wait after having decremented the MTU estimate + * before trying to increment it. + */ +#ifndef MTUTIMER1 +#define MTUTIMER1 2 +#endif +int in_mtutimer1 = MTUTIMER1; + +#ifndef MTUTIMER2 +#define MTUTIMER2 10 +#endif +int in_mtutimer2 = MTUTIMER2; +#endif /* MTUDISC */ + +/* + * and a zero in_addr to make some code happy... + */ +struct in_addr zeroin_addr; + +/* + * ICMPPRINTFS enables some debugging printfs in ip_icmp.c. + * + * IPBROADCASTECHO controls whether ICMP Echo Reply packets are sent + * in response to ICMP Echo packets which were addressed to a multicast + * or broadcast address. + * + * IPMASKAGENT controls whether ICMP Mask Reply packets are sent. + * It should only be enabled on the machine which is the authoritative + * mask agent for a subnet. + */ +#ifdef ICMPPRINTFS +int icmpprintfs = 0; +#endif + +#ifndef IPBROADCASTECHO +#define IPBROADCASTECHO 0 +#endif +int ipbroadcastecho = IPBROADCASTECHO; + +#ifndef IPMASKAGENT +#define IPMASKAGENT 0 +#endif +int ipmaskagent = IPMASKAGENT; + +/* + * ICMP statistics + */ +struct icmpstat icmpstat; + +/* + * Yet Another sockaddr_in filled in by various routines when convenient. + */ +struct sockaddr_in icmpmask = { 8, 0 }; + +/* + * Print out TCP debugging messages on the console. + */ +#ifdef TCPDEBUG +int tcpconsdebug = 0; +#endif + +#include "tcp.h" +#include "tcp_fsm.h" +#include "tcp_seq.h" +#include "tcp_timer.h" +#include "tcp_var.h" +#include "tcpip.h" + +/* + * tcp_ttl is the default IP TTL for TCP segments. + * tcp_mssdflt is the default max segment size. + * tcp_rttdflt is the initial round trip time estimate when there is no RTT + * in the route. + */ +int tcp_ttl = TCP_TTL; +int tcp_mssdflt = TCP_MSS; +int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; + +/* + * When KPROF is defined (god only knows why), TCP keeps track of + * protocol requests in this matrix. + */ +#ifdef KPROF +int tcp_acounts[TCP_NSTATES][PRU_NREQ]; +#endif + +/* + * tcp_keepidle is the a fraction of the length of non-response time in a + * in a keepalive situation after which TCP abandons the connection. + * + * tcp_keepintvl is the interval between keepalives. + * + * tcp_maxidle is the time after which a connection will be dropped in + * certain states. It is computed as `TCPTV_KEEPCNT * tcp_keepintvl'. + */ +int tcp_keepidle = TCPTV_KEEP_IDLE; +int tcp_keepintvl = TCPTV_KEEPINTVL; +int tcp_maxidle; + +/* + * tcp_sendspace and tcp_recvspace are the default send and receive window + * sizes, respectively. These are obsolescent (this information should + * be set by the route). + */ +#ifdef TCP_SMALLSPACE +u_long tcp_sendspace = 1024*4; +u_long tcp_recvspace = 1024*4; +#else +u_long tcp_sendspace = 1024*16; +u_long tcp_recvspace = 1024*16; +#endif /* TCP_SMALLSPACE */ + +#include "udp.h" +#include "udp_var.h" + +/* + * udpcksum tells whether to do UDP checksums. It should always be + * turned on, except as required for compatibility with ancient + * 4.2-based systems like SunOS 3.5 and Ultrix 2.0. + */ +#ifndef COMPAT_42 +int udpcksum = 1; +#else +int udpcksum = 0; /* XXX */ +#endif + + +/* + * udp_ttl is the default IP TTL for UDP packets. + */ +int udp_ttl = UDP_TTL; + +/* + * UDP statistics for netstat. + */ +struct udpstat udpstat; + +/* + * udp_sendspace is the maximum datagram size the UDP layer is willing to + * attempt to transmit. + * + * udp_recvspace is the amount of buffer space the UDP layer will + * reserve for holding received packets. + */ +u_long udp_sendspace = 9216; /* really max datagram size */ +u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); + /* 40 1K datagrams */ + + diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 42c93fbac3e4..9e03a296adb4 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)in_var.h 7.6 (Berkeley) 6/28/90 - * $Id: in_var.h,v 1.2 1993/10/16 18:26:07 rgrimes Exp $ + * $Id: in_var.h,v 1.6 1993/12/19 21:43:26 wollman Exp $ */ +#ifndef _NETINET_IN_VAR_H_ +#define _NETINET_IN_VAR_H_ 1 + /* * Interface address, Internet version. One of these structures * is allocated for each interface with an Internet address. @@ -70,8 +73,76 @@ struct in_aliasreq { */ #define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr)) +struct ip; /* forward declaration */ +typedef void in_input_t(struct mbuf *, int); +/* + * Grrr... `netstat' expects to be able to include this file + * with KERNEL defined, to get all sorts of interesting structures, + * but without having to get all these prototypes. (Well, it's not + * really netstat's fault, but this should get fixed when KERNEL gets + * changed to _KERNEL.) + */ +struct socket; +typedef int in_output_t(struct mbuf *, struct socket *); +typedef void in_ctlinput_t(int, struct sockaddr *, struct ip *); +typedef int in_ctloutput_t(int, struct socket *, int, int, struct mbuf **); + +/* + * This structure is a pun for `struct protosw'. The difference is that it + * has appropriate interprotocol hook prototypes for the Internet family. + */ +struct in_protosw { + short pr_type; /* socket type used for */ + struct domain *pr_domain; /* domain protocol a member of */ + short pr_protocol; /* protocol number */ + short pr_flags; /* see below */ +/* protocol-protocol hooks */ + in_input_t *pr_input; + in_output_t *pr_output; + in_ctlinput_t *pr_ctlinput; + in_ctloutput_t *pr_ctloutput; +/* user-protocol hook */ + int (*pr_usrreq)(struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *, struct mbuf *); +/* utility hooks */ + void (*pr_init)(void); /* initialization hook */ + void (*pr_fasttimo)(void); /* fast timeout (200ms) */ + void (*pr_slowtimo)(void); /* slow timeout (500ms) */ + void (*pr_drain)(void); /* flush any excess space possible */ +}; + + #ifdef KERNEL -struct in_ifaddr *in_ifaddr; -struct in_ifaddr *in_iaonnetof(); -struct ifqueue ipintrq; /* ip packet input queue */ -#endif +extern struct in_ifaddr *in_ifaddr; +extern struct in_ifaddr *in_iaonnetof(u_long); +extern struct in_ifaddr *ifptoia(struct ifnet *); +extern int in_ifinit(struct ifnet *, struct in_ifaddr *, struct sockaddr_in *, int); + +extern int in_cksum(struct mbuf *, int); + +extern struct ifqueue ipintrq; /* ip packet input queue */ +extern struct in_protosw inetsw[]; +extern struct domain inetdomain; +extern u_char ip_protox[]; +extern u_char inetctlerrmap[]; +extern struct in_addr zeroin_addr; + +/* From in_var.c: */ +struct route; +extern int subnetsarelocal; /* obsolescent */ +extern int ipqmaxlen; +extern u_long *ip_ifmatrix; +extern int ipforwarding; +extern struct sockaddr_in ipaddr; +extern struct route ipforward_rt; +extern int ipsendredirects; + + +#ifdef MTUDISC +extern unsigned in_nextmtu(unsigned, int); +extern int in_routemtu(struct route *); +extern void in_mtureduce(struct in_addr, unsigned); +extern void in_mtutimer(caddr_t, int); +#endif /* MTUDISC */ +#endif /* KERNEL */ +#endif /* _NETINET_IN_VAR_H_ */ diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h index 2f5687e9f7fb..69b5bf0e428d 100644 --- a/sys/netinet/ip.h +++ b/sys/netinet/ip.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)ip.h 7.10 (Berkeley) 6/28/90 - * $Id: ip.h,v 1.2 1993/10/16 18:26:08 rgrimes Exp $ + * $Id: ip.h,v 1.3 1993/11/07 17:47:54 wollman Exp $ */ +#ifndef _NETINET_IP_H_ +#define _NETINET_IP_H_ 1 + /* * Definitions for internet protocol version 4. * Per RFC 791, September 1981. @@ -165,3 +168,4 @@ struct ip_timestamp { #define IPTTLDEC 1 /* subtracted when forwarding */ #define IP_MSS 576 /* default maximum segment size */ +#endif /* _NETINET_IP_H_ */ diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index b9a444c685b1..ed9b199e1db4 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)ip_icmp.c 7.15 (Berkeley) 4/20/91 - * $Id: ip_icmp.c,v 1.2 1993/10/16 18:26:11 rgrimes Exp $ + * $Id: ip_icmp.c,v 1.6 1993/12/19 00:52:42 wollman Exp $ */ #include "param.h" @@ -58,27 +58,29 @@ * routines to turnaround packets back to the originator, and * host table maintenance routines. */ -#ifdef ICMPPRINTFS -int icmpprintfs = 0; -#endif -extern struct protosw inetsw[]; +#define satosin(sa) ((struct sockaddr_in *)(sa)) +static void icmp_reflect(struct mbuf *); +static void icmp_send(struct mbuf *, struct mbuf *); + /* * Generate an error packet of type error * in response to bad packet ip. */ -/*VARARGS3*/ -icmp_error(n, type, code, dest) +void +icmp_error(n, type, code, dest, mtu) struct mbuf *n; int type, code; struct in_addr dest; + int mtu; /* mtu for ICMP_UNREACH_SRCFRAG */ { register struct ip *oip = mtod(n, struct ip *), *nip; register unsigned oiplen = oip->ip_hl << 2; register struct icmp *icp; - register struct mbuf *m; + register struct mbuf *m = 0; unsigned icmplen; + u_long oaddr; #ifdef ICMPPRINTFS if (icmpprintfs) @@ -86,6 +88,61 @@ icmp_error(n, type, code, dest) #endif if (type != ICMP_REDIRECT) icmpstat.icps_error++; + + /* + * Quoth RFC 1122 (Requirements for Internet Hosts): + * + * An ICMP error message MUST NOT be sent as the result of + * receiving: + * - an ICMP error message, or + * - a datagram destined to an IP broadcast or IP multicast + * address, or + * - a datagram sent as a link-layer broadcast, or + * - a non-initial fragment, or + * - a datagram whose source address does not define a single + * host -- e.g., a zero address, a loopback address, a + * broadcast address, a multicast address, or a Class E + * address. + * + * NOTE: THESE RESTRICTIONS TAKE PRECEDENCE OVER ANY REQUIREMENT + * ELSEWHERE IN THIS DOCUMENT FOR SENDING ICMP ERROR MESSAGES. + */ + + oaddr = ntohl(oip->ip_src.s_addr); + + /* + * Don't send error messages to multicast or broadcast addresses. + */ + if (IN_MULTICAST(oaddr) + || oaddr == INADDR_BROADCAST + || n->m_flags & (M_BCAST | M_MCAST)) { + icmpstat.icps_oldmcast++; + goto freeit; + } + + /* + * Don't send error messages to zero addresses or class E's. + */ + if (IN_EXPERIMENTAL(oaddr) + || ! in_lnaof(oip->ip_src) + || ! in_netof(oip->ip_src)) { + icmpstat.icps_oldbadaddr++; + goto freeit; + } + + /* + * Don't send error messages to loopback addresses. + * As a special (unauthorized) exception, we check to see + * if the packet came from the loopback interface. If it + * did, then we should allow the errors through, because + * the upper layers rely on them. + */ + if(in_netof(oip->ip_src) == IN_LOOPBACKNET + && !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) { + icmpstat.icps_oldbadaddr++; + goto freeit; + } + /* * Don't send error if not the first fragment of message. * Don't error if the old packet protocol was ICMP @@ -116,8 +173,12 @@ icmp_error(n, type, code, dest) icp->icmp_type = type; if (type == ICMP_REDIRECT) icp->icmp_gwaddr = dest; - else + else if (type == ICMP_UNREACH && code == ICMP_UNREACH_NEEDFRAG) { + icp->icmp_mtu = htons(mtu); + icp->icmp_mtuvoid = 0; + } else { icp->icmp_void = 0; + } if (type == ICMP_PARAMPROB) { icp->icmp_pptr = code; code = 0; @@ -152,12 +213,11 @@ static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP }; static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET }; static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET }; static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET }; -struct sockaddr_in icmpmask = { 8, 0 }; -struct in_ifaddr *ifptoia(); /* * Process a received ICMP message. */ +void icmp_input(m, hlen) register struct mbuf *m; int hlen; @@ -167,9 +227,8 @@ icmp_input(m, hlen) int icmplen = ip->ip_len; register int i; struct in_ifaddr *ia; - int (*ctlfunc)(), code; - extern u_char ip_protox[]; - extern struct in_addr in_makeaddr(); + in_ctlinput_t *ctlfunc; + int code; /* * Locate icmp structure in mbuf, and check @@ -214,21 +273,35 @@ icmp_input(m, hlen) switch (icp->icmp_type) { case ICMP_UNREACH: - if (code > 5) + if (code > ICMP_UNREACH_MAXCODE) goto badcode; - code += PRC_UNREACH_NET; + if (code == ICMP_UNREACH_NEEDFRAG) { +#ifdef MTUDISC + /* + * Need to adjust the routing tables immediately; + * when ULP's get the PRC_MSGSIZE, it is their + * responsibility to notice it and update their + * internal ideas of MTU-derived protocol parameters. + */ + in_mtureduce(icp->icmp_ip.ip_dst, + ntohs(icp->icmp_mtu)); + code = PRC_MSGSIZE; +#endif /* MTUDISC */ + } else { + code += PRC_UNREACH_NET; + } goto deliver; case ICMP_TIMXCEED: - if (code > 1) + if (code > ICMP_TIMXCEED_MAXCODE) goto badcode; code += PRC_TIMXCEED_INTRANS; goto deliver; case ICMP_PARAMPROB: - if (code) + if (code > ICMP_PARAMPROB_MAXCODE) goto badcode; - code = PRC_PARAMPROB; + code += PRC_PARAMPROB; goto deliver; case ICMP_SOURCEQUENCH: @@ -252,14 +325,36 @@ icmp_input(m, hlen) icmpsrc.sin_addr = icp->icmp_ip.ip_dst; if (ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput) (*ctlfunc)(code, (struct sockaddr *)&icmpsrc, - (caddr_t) &icp->icmp_ip); + &icp->icmp_ip); break; badcode: icmpstat.icps_badcode++; break; + /* + * Always respond to pings from valid addresses. + * Don't respond to broadcast pings unless ipbroadcastecho + * is set. Don't respond to multicast pings unless + * ipbraodcastecho is set AND we support multicasting + * to begin with. (Per RFC 1122, we may choose either.) + */ case ICMP_ECHO: + { + u_long srcaddr = ntohl(icp->icmp_ip.ip_src.s_addr); +#ifdef MULTICAST + if(IN_MULTICAST(srcaddr) && !ipbroadcastecho) + break; +#else /* not MULTICAST */ + if(IN_MULTICAST(srcaddr)) + break; +#endif /* not MULTICAST */ + if((srcaddr == INADDR_BROADCAST + || m->m_flags & M_BCAST) + && !ipbroadcastecho) + break; + } + icp->icmp_type = ICMP_ECHOREPLY; goto reflect; @@ -273,16 +368,14 @@ icmp_input(m, hlen) icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */ goto reflect; - case ICMP_IREQ: -#define satosin(sa) ((struct sockaddr_in *)(sa)) - if (in_netof(ip->ip_src) == 0 && - (ia = ifptoia(m->m_pkthdr.rcvif))) - ip->ip_src = in_makeaddr(in_netof(IA_SIN(ia)->sin_addr), - in_lnaof(ip->ip_src)); - icp->icmp_type = ICMP_IREQREPLY; - goto reflect; - + /* + * Per RFC 1122, only respond to ICMP mask requests + * if the administrator has SPECIFICALLY CONFIGURED + * this host as an address mask agent. + */ case ICMP_MASKREQ: + if (!ipmaskagent) + break; if (icmplen < ICMP_MASKLEN || (ia = ifptoia(m->m_pkthdr.rcvif)) == 0) break; @@ -320,8 +413,21 @@ reflect: printf("redirect dst %x to %x\n", icp->icmp_ip.ip_dst, icp->icmp_gwaddr); #endif + /* + * Per RFC 1122, throw away redirects that + * suggested places we can't get to, or + * an interface other than the one the packet + * arrived on. + * + * It also says that we SHOULD throw away + * redirects that come from someone other + * than the current first-hop gateway for the + * specified destination. + * + * These are both implemented as general policy + * by rtredirect(). + */ if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) { - u_long in_netof(); icmpsrc.sin_addr = in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY); in_sockmaskof(icp->icmp_ip.ip_dst, &icmpmask); @@ -369,6 +475,7 @@ freeit: /* * Reflect the ip packet back to the source */ +static void icmp_reflect(m) struct mbuf *m; { @@ -485,6 +592,7 @@ ifptoia(ifp) * Send an icmp packet back to the ip level, * after supplying a checksum. */ +static void icmp_send(m, opts) register struct mbuf *m; struct mbuf *opts; diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index effd9e48812d..7f27f2df94c6 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)ip_icmp.h 7.5 (Berkeley) 6/28/90 - * $Id: ip_icmp.h,v 1.2 1993/10/16 18:26:12 rgrimes Exp $ + * $Id: ip_icmp.h,v 1.4 1993/11/18 00:08:19 wollman Exp $ */ +#ifndef _NETINET_IP_ICMP_H_ +#define _NETINET_IP_ICMP_H_ 1 + /* * Interface Control Message Protocol Definitions. * Per RFC 792, September 1981. @@ -53,6 +56,10 @@ struct icmp { n_short icd_id; n_short icd_seq; } ih_idseq; + struct ih_mtu { + n_short imt_unused; + n_short imt_nhmtu; + } ih_mtu; int ih_void; } icmp_hun; #define icmp_pptr icmp_hun.ih_pptr @@ -60,6 +67,8 @@ struct icmp { #define icmp_id icmp_hun.ih_idseq.icd_id #define icmp_seq icmp_hun.ih_idseq.icd_seq #define icmp_void icmp_hun.ih_void +#define icmp_mtu icmp_hun.ih_mtu.imt_nhmtu +#define icmp_mtuvoid icmp_hun.ih_mtu.imt_unused union { struct id_ts { n_time its_otime; @@ -107,17 +116,38 @@ struct icmp { #define ICMP_UNREACH_PORT 3 /* bad port */ #define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ #define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NETUNKNOWN 6 /* dest net unknown */ +#define ICMP_UNREACH_HSTUNKNOWN 7 /* dst host unknown */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated*/ +/* next two are for administratively prohibited */ +#define ICMP_UNREACH_NETADMIN 9 /* dest net */ +#define ICMP_UNREACH_HOSTADMIN 10 /* dest host */ +/* next two are for TOS unreachables */ +#define ICMP_UNREACH_TOSNET 11 /* dest net+tos */ +#define ICMP_UNREACH_TOSHOST 12 /* dest host+tos */ +#define ICMP_UNREACH_MAXCODE 12 + #define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ + #define ICMP_REDIRECT 5 /* shorter route, codes: */ #define ICMP_REDIRECT_NET 0 /* for network */ #define ICMP_REDIRECT_HOST 1 /* for host */ #define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ #define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ +#define ICMP_REDIRECT_MAXCODE 3 + #define ICMP_ECHO 8 /* echo service */ + #define ICMP_TIMXCEED 11 /* time exceeded, code: */ #define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ #define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ +#define ICMP_TIMXCEED_MAXCODE 1 + #define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_PARAMPROB_GENERAL 0 /* generic problems */ +#define ICMP_PARAMPROB_REQDOPT 1 /* option misssing */ +#define ICMP_PARAMPROB_MAXCODE 1 + #define ICMP_TSTAMP 13 /* timestamp request */ #define ICMP_TSTAMPREPLY 14 /* timestamp reply */ #define ICMP_IREQ 15 /* information request */ @@ -132,3 +162,12 @@ struct icmp { (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef KERNEL +struct mbuf; +extern void icmp_error(struct mbuf *, int, int, struct in_addr, int); +extern void icmp_input(struct mbuf *, int); +n_time iptime(void); +#endif + +#endif /* _NETINET_IP_ICMP_H_ */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index c4e0ba1c6823..6c45aed63234 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)ip_input.c 7.19 (Berkeley) 5/25/91 - * $Id: ip_input.c,v 1.2 1993/10/16 18:26:14 rgrimes Exp $ + * $Id: ip_input.c,v 1.8 1994/01/04 17:47:13 ache Exp $ */ #include "param.h" @@ -56,27 +56,12 @@ #include "ip_var.h" #include "ip_icmp.h" -#ifndef IPFORWARDING -#ifdef GATEWAY -#define IPFORWARDING 1 /* forward IP packets not for us */ -#else /* GATEWAY */ -#define IPFORWARDING 0 /* don't forward IP packets not for us */ -#endif /* GATEWAY */ -#endif /* IPFORWARDING */ -#ifndef IPSENDREDIRECTS -#define IPSENDREDIRECTS 1 -#endif -int ipforwarding = IPFORWARDING; -int ipsendredirects = IPSENDREDIRECTS; -#ifdef DIAGNOSTIC -int ipprintfs = 0; -#endif - -extern struct domain inetdomain; -extern struct protosw inetsw[]; -u_char ip_protox[IPPROTO_MAX]; -int ipqmaxlen = IFQ_MAXLEN; -struct in_ifaddr *in_ifaddr; /* first inet address */ +static void ip_freef(struct ipq *); +static void ip_enq(struct ipasfrag *, struct ipasfrag *); +static void ip_deq(struct ipasfrag *); +static void save_rte(u_char *, struct in_addr); +static void ip_forward(struct mbuf *, int); +static struct ip *ip_reass(struct ipasfrag *, struct ipq *); /* * We need to save the IP options in case a protocol wants to respond @@ -93,27 +78,28 @@ static struct ip_srcrt { struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; } ip_srcrt; -#ifdef GATEWAY extern int if_index; -u_long *ip_ifmatrix; +#ifdef DIAGNOSTIC +extern int ipprintfs; #endif /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ +void ip_init() { - register struct protosw *pr; + register struct in_protosw *pr; register int i; - pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); + pr = (struct in_protosw *)pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; - for (pr = inetdomain.dom_protosw; - pr < inetdomain.dom_protoswNPROTOSW; pr++) + for (pr = (struct in_protosw *)inetdomain.dom_protosw; + pr < (struct in_protosw *)inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip_protox[pr->pr_protocol] = pr - inetsw; @@ -127,14 +113,11 @@ ip_init() #endif } -struct ip *ip_reass(); -struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; -struct route ipforward_rt; - /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ +void ipintr() { register struct ip *ip; @@ -348,7 +331,7 @@ bad: * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ -struct ip * +static struct ip * ip_reass(ip, fp) register struct ipasfrag *ip; register struct ipq *fp; @@ -488,6 +471,7 @@ dropfrag: * Free a fragment reassembly header and all * associated datagrams. */ +static void ip_freef(fp) struct ipq *fp; { @@ -506,6 +490,7 @@ ip_freef(fp) * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ +static void ip_enq(p, prev) register struct ipasfrag *p, *prev; { @@ -519,6 +504,7 @@ ip_enq(p, prev) /* * To ip_enq as remque is to insque. */ +static void ip_deq(p) register struct ipasfrag *p; { @@ -532,6 +518,7 @@ ip_deq(p) * if a timer expires on a reassembly * queue, discard it. */ +void ip_slowtimo() { register struct ipq *fp; @@ -556,6 +543,7 @@ ip_slowtimo() /* * Drain off all datagram fragments. */ +void ip_drain() { @@ -575,6 +563,7 @@ struct in_ifaddr *ip_rtaddr(); * Returns 1 if packet has been forwarded/freed, * 0 if the packet should be processed further. */ +int ip_dooptions(m) struct mbuf *m; { @@ -748,7 +737,10 @@ ip_dooptions(m) } else return (0); bad: - icmp_error(m, type, code); + { + static struct in_addr fake; + icmp_error(m, type, code, fake, 0); + } return (1); } @@ -784,6 +776,7 @@ ip_rtaddr(dst) * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ +static void save_rte(option, dst) u_char *option; struct in_addr dst; @@ -878,6 +871,7 @@ ip_srcroute() * will be moved, and return value is their length. * XXX should be deleted; last arg currently ignored. */ +void ip_stripoptions(m, mopt) register struct mbuf *m; struct mbuf *mopt; @@ -897,15 +891,6 @@ ip_stripoptions(m, mopt) ip->ip_hl = sizeof(struct ip) >> 2; } -u_char inetctlerrmap[PRC_NCMDS] = { - 0, 0, 0, 0, - 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, - EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, - EMSGSIZE, EHOSTUNREACH, 0, 0, - 0, 0, 0, 0, - ENOPROTOOPT -}; - /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful @@ -920,6 +905,7 @@ u_char inetctlerrmap[PRC_NCMDS] = { * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ +static void ip_forward(m, srcrt) struct mbuf *m; int srcrt; @@ -927,9 +913,10 @@ ip_forward(m, srcrt) register struct ip *ip = mtod(m, struct ip *); register struct sockaddr_in *sin; register struct rtentry *rt; - int error, type = 0, code; + int error, type = 0, code = 0; struct mbuf *mcopy; struct in_addr dest; + int mtu = 0; dest.s_addr = 0; #ifdef DIAGNOSTIC @@ -944,7 +931,7 @@ ip_forward(m, srcrt) } HTONS(ip->ip_id); if (ip->ip_ttl <= IPTTLDEC) { - icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest); + icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); return; } ip->ip_ttl -= IPTTLDEC; @@ -962,10 +949,12 @@ ip_forward(m, srcrt) rtalloc(&ipforward_rt); if (ipforward_rt.ro_rt == 0) { - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest); + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } rt = ipforward_rt.ro_rt; + mtu = rt->rt_ifp->if_mtu; + /* salt away if's mtu */ } /* @@ -1065,5 +1054,5 @@ ip_forward(m, srcrt) code = 0; break; } - icmp_error(mcopy, type, code, dest); + icmp_error(mcopy, type, code, dest, mtu); } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index ec5a5dd4527d..e9b459e870b8 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -31,10 +31,11 @@ * SUCH DAMAGE. * * from: @(#)ip_output.c 7.23 (Berkeley) 11/12/90 - * $Id: ip_output.c,v 1.3 1993/10/19 09:14:15 davidg Exp $ + * $Id: ip_output.c,v 1.5 1993/12/19 00:52:45 wollman Exp $ */ #include "param.h" +#include "systm.h" #include "malloc.h" #include "mbuf.h" #include "errno.h" @@ -64,6 +65,7 @@ struct mbuf *ip_insertoptions(); * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. */ +int ip_output(m0, opt, ro, flags) struct mbuf *m0; struct mbuf *opt; @@ -345,6 +347,7 @@ ip_insertoptions(m, opt, phlen) * Copy options from ip to jp, * omitting those not copied during fragmentation. */ +int ip_optcopy(ip, jp) struct ip *ip, *jp; { @@ -378,6 +381,7 @@ ip_optcopy(ip, jp) /* * IP socket option processing. */ +int ip_ctloutput(op, so, level, optname, mp) int op; struct socket *so; @@ -386,7 +390,7 @@ ip_ctloutput(op, so, level, optname, mp) { register struct inpcb *inp = sotoinpcb(so); register struct mbuf *m = *mp; - register int optval; + register int optval = 0; int error = 0; if (level != IPPROTO_IP) @@ -512,6 +516,7 @@ ip_ctloutput(op, so, level, optname, mp) * Store in mbuf with pointer in pcbopt, adding pseudo-option * with destination address if source routed. */ +int #ifdef notyet ip_pcbopts(optname, pcbopt, m) int optname; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 9cdfbe1a5aee..47d76fe01b5a 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)ip_var.h 7.7 (Berkeley) 6/28/90 - * $Id: ip_var.h,v 1.2 1993/10/16 18:26:17 rgrimes Exp $ + * $Id: ip_var.h,v 1.3 1993/11/07 17:48:00 wollman Exp $ */ +#ifndef _NETINET_IP_VAR_H_ +#define _NETINET_IP_VAR_H_ 1 + /* * Overlay for ip header used by other protocols (tcp, udp). */ @@ -129,9 +132,10 @@ struct ipstat { #define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */ #define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */ -struct ipstat ipstat; -struct ipq ipq; /* ip reass. queue */ -u_short ip_id; /* ip packet ctr, for ids */ +extern struct ipstat ipstat; +extern struct ipq ipq; /* ip reass. queue */ +extern u_short ip_id; /* ip packet ctr, for ids */ struct mbuf *ip_srcroute(); #endif +#endif /* _NETINET_IP_VAR_H_ */ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 6734534962df..1618339176ae 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)raw_ip.c 7.8 (Berkeley) 7/25/90 - * $Id: raw_ip.c,v 1.2 1993/10/16 18:26:19 rgrimes Exp $ + * $Id: raw_ip.c,v 1.4 1993/12/19 00:52:46 wollman Exp $ */ #include "param.h" @@ -55,15 +55,16 @@ /* * Raw interface to IP protocol. */ +static struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; +static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; +static struct sockproto ripproto = { PF_INET }; -struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; -struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; -struct sockproto ripproto = { PF_INET }; /* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. */ +void rip_input(m) struct mbuf *m; { @@ -84,6 +85,7 @@ rip_input(m) * Tack on options user may have setup with control call. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) +int rip_output(m, so) register struct mbuf *m; struct socket *so; @@ -122,6 +124,7 @@ rip_output(m, so) /* * Raw IP socket option processing. */ +int rip_ctloutput(op, so, level, optname, m) int op; struct socket *so; @@ -190,6 +193,7 @@ rip_ctloutput(op, so, level, optname, m) } /*ARGSUSED*/ +int rip_usrreq(so, req, m, nam, control) register struct socket *so; int req; @@ -254,7 +258,7 @@ rip_usrreq(so, req, m, nam, control) return (0); } } - error = raw_usrreq(so, req, m, nam, control); + error = raw_usrreq(so, req, m, nam, control, 0); if (error && (req == PRU_ATTACH) && so->so_pcb) free(so->so_pcb, M_PCB); diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h index 4ea9d576e0bf..c52883cbdfdf 100644 --- a/sys/netinet/tcp.h +++ b/sys/netinet/tcp.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp.h 7.7 (Berkeley) 6/28/90 - * $Id: tcp.h,v 1.2 1993/10/16 18:26:20 rgrimes Exp $ + * $Id: tcp.h,v 1.3 1993/11/07 17:48:02 wollman Exp $ */ +#ifndef _NETINET_TCP_H_ +#define _NETINET_TCP_H_ 1 + typedef u_long tcp_seq; /* * TCP header. @@ -83,3 +86,4 @@ struct tcphdr { */ #define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ #define TCP_MAXSEG 0x02 /* set maximum segment size */ +#endif /* _NETINET_TCP_H_ */ diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c index 7e141dbdee88..b361f0a125fb 100644 --- a/sys/netinet/tcp_debug.c +++ b/sys/netinet/tcp_debug.c @@ -31,16 +31,14 @@ * SUCH DAMAGE. * * from: @(#)tcp_debug.c 7.6 (Berkeley) 6/28/90 - * $Id: tcp_debug.c,v 1.2 1993/10/16 18:26:22 rgrimes Exp $ + * $Id: tcp_debug.c,v 1.7 1994/01/24 05:12:31 davidg Exp $ */ -#ifdef TCPDEBUG /* load symbolic names */ #define PRUREQUESTS #define TCPSTATES #define TCPTIMERS #define TANAMES -#endif #include "param.h" #include "systm.h" @@ -66,12 +64,13 @@ #include "tcpip.h" #include "tcp_debug.h" -#ifdef TCPDEBUG -int tcpconsdebug = 0; -#endif +struct tcp_debug tcp_debug[TCP_NDEBUG]; +int tcp_debx; + /* * Tcp debug routines */ +void tcp_trace(act, ostate, tp, ti, req) short act, ostate; struct tcpcb *tp; @@ -97,7 +96,6 @@ tcp_trace(act, ostate, tp, ti, req) else bzero((caddr_t)&td->td_ti, sizeof (*ti)); td->td_req = req; -#ifdef TCPDEBUG if (tcpconsdebug == 0) return; if (tp) @@ -131,8 +129,9 @@ tcp_trace(act, ostate, tp, ti, req) if (flags) { #ifndef lint char *cp = "<"; -#define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } +#define pf(f) { if (ti->ti_flags& TH_ ## f) { printf("%s" #f, cp); cp = ","; } } pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); +#undef pf #endif printf(">"); } @@ -155,5 +154,4 @@ tcp_trace(act, ostate, tp, ti, req) tp->snd_max); printf("\tsnd_(wl1,wl2,wnd) (%x,%x,%x)\n", tp->snd_wl1, tp->snd_wl2, tp->snd_wnd); -#endif /* TCPDEBUG */ } diff --git a/sys/netinet/tcp_debug.h b/sys/netinet/tcp_debug.h index b6b134a77ad4..6316ed992dbe 100644 --- a/sys/netinet/tcp_debug.h +++ b/sys/netinet/tcp_debug.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp_debug.h 7.4 (Berkeley) 6/28/90 - * $Id: tcp_debug.h,v 1.2 1993/10/16 18:26:23 rgrimes Exp $ + * $Id: tcp_debug.h,v 1.3 1993/11/07 17:48:04 wollman Exp $ */ +#ifndef _NETINET_TCP_DEBUG_H_ +#define _NETINET_TCP_DEBUG_H_ 1 + struct tcp_debug { n_time td_time; short td_act; @@ -56,5 +59,6 @@ char *tanames[] = #endif #define TCP_NDEBUG 100 -struct tcp_debug tcp_debug[TCP_NDEBUG]; -int tcp_debx; +extern struct tcp_debug tcp_debug[TCP_NDEBUG]; +extern int tcp_debx; +#endif /* _NETINET_TCP_DEBUG_H_ */ diff --git a/sys/netinet/tcp_fsm.h b/sys/netinet/tcp_fsm.h index f1c354e8cc62..e9bbe11a34d4 100644 --- a/sys/netinet/tcp_fsm.h +++ b/sys/netinet/tcp_fsm.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp_fsm.h 7.4 (Berkeley) 6/28/90 - * $Id: tcp_fsm.h,v 1.2 1993/10/16 18:26:24 rgrimes Exp $ + * $Id: tcp_fsm.h,v 1.3 1993/11/07 17:48:05 wollman Exp $ */ +#ifndef _NETINET_TCP_FSM_H_ +#define _NETINET_TCP_FSM_H_ 1 + /* * TCP FSM state definitions. * Per RFC793, September, 1981. @@ -74,7 +77,7 @@ u_char tcp_outflags[TCP_NSTATES] = { #endif #ifdef KPROF -int tcp_acounts[TCP_NSTATES][PRU_NREQ]; +extern int tcp_acounts[TCP_NSTATES][PRU_NREQ]; #endif #ifdef TCPSTATES @@ -84,3 +87,4 @@ char *tcpstates[] = { "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT", }; #endif +#endif /* _NETINET_TCP_FSM_H_ */ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 4258b00d860a..e841fac4077c 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tcp_input.c 7.25 (Berkeley) 6/30/90 - * $Id: tcp_input.c,v 1.2 1993/10/16 18:26:26 rgrimes Exp $ + * $Id: tcp_input.c,v 1.9 1994/01/31 09:47:02 davidg Exp $ */ #include "param.h" @@ -57,16 +57,23 @@ #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" +#ifdef TCPDEBUG #include "tcp_debug.h" +#endif + +static void tcp_dooptions(struct tcpcb *, struct mbuf *, struct tcpiphdr *); +static void tcp_pulloutofband(struct socket *, struct tcpiphdr *, struct mbuf *); +static void tcp_xmit_timer(struct tcpcb *); int tcprexmtthresh = 3; int tcppredack; /* XXX debugging: times hdr predict ok for acks */ int tcppreddat; /* XXX # times header prediction ok for data packets */ int tcppcbcachemiss; +#ifdef TCPDEBUG struct tcpiphdr tcp_saveti; +#endif struct inpcb *tcp_last_inpcb = &tcb; -struct tcpcb *tcp_newtcpcb(); /* * Insert segment ti into reassembly queue of tcp with @@ -95,6 +102,7 @@ struct tcpcb *tcp_newtcpcb(); } \ } +int tcp_reass(tp, ti, m) register struct tcpcb *tp; register struct tcpiphdr *ti; @@ -202,6 +210,7 @@ present: * TCP input routine, follows pages 65-76 of the * protocol specification dated September, 1981 very closely. */ +void tcp_input(m, iphlen) register struct mbuf *m; int iphlen; @@ -212,12 +221,14 @@ tcp_input(m, iphlen) int len, tlen, off; register struct tcpcb *tp = 0; register int tiflags; - struct socket *so; + struct socket *so = 0; int todrop, acked, ourfinisacked, needoutput = 0; - short ostate; struct in_addr laddr; int dropsocket = 0; int iss = 0; +#ifdef TCPDEBUG + short ostate = 0; +#endif tcpstat.tcps_rcvtotal++; /* @@ -321,10 +332,12 @@ findpcb: goto drop; so = inp->inp_socket; if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { +#ifdef TCPDEBUG if (so->so_options & SO_DEBUG) { ostate = tp->t_state; tcp_saveti = *ti; } +#endif if (so->so_options & SO_ACCEPTCONN) { so = sonewconn(so, 0); if (so == 0) @@ -443,7 +456,17 @@ findpcb: m->m_len -= sizeof(struct tcpiphdr); sbappend(&so->so_rcv, m); sorwakeup(so); - tp->t_flags |= TF_DELACK; + /* + * If this is a small packet, then ACK now - with Nagel + * congestion avoidance sender won't send more until + * he gets an ACK. + */ + if ((unsigned)ti->ti_len < tp->t_maxseg) { + tp->t_flags |= TF_ACKNOW; + tcp_output(tp); + } else { + tp->t_flags |= TF_DELACK; + } return; } } @@ -594,7 +617,7 @@ trimthenstep6: * dropping FIN if necessary. */ ti->ti_seq++; - if (ti->ti_len > tp->rcv_wnd) { + if ((u_long)ti->ti_len > (u_long)tp->rcv_wnd) { todrop = ti->ti_len - tp->rcv_wnd; m_adj(m, -todrop); ti->ti_len = tp->rcv_wnd; @@ -1057,7 +1080,7 @@ step6: * but if two URG's are pending at once, some out-of-band * data may creep in... ick. */ - if (ti->ti_urp <= ti->ti_len + if ((u_long)ti->ti_urp <= (u_long)ti->ti_len #ifdef SO_OOBINLINE && (so->so_options & SO_OOBINLINE) == 0 #endif @@ -1144,8 +1167,18 @@ dodata: /* XXX */ break; } } +#ifdef TCPDEBUG if (so->so_options & SO_DEBUG) tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0); +#endif + + /* + * If this is a small packet, then ACK now - with Nagel + * congestion avoidance sender won't send more until + * he gets an ACK. + */ + if (ti->ti_len && ((unsigned)ti->ti_len < tp->t_maxseg)) + tp->t_flags |= TF_ACKNOW; /* * Return any desired output. @@ -1197,8 +1230,10 @@ drop: /* * Drop space held by incoming segment and return. */ +#ifdef TCPDEBUG if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0); +#endif m_freem(m); /* destroy temporarily created socket */ if (dropsocket) @@ -1206,6 +1241,7 @@ drop: return; } +static void tcp_dooptions(tp, om, ti) struct tcpcb *tp; struct mbuf *om; @@ -1253,6 +1289,7 @@ tcp_dooptions(tp, om, ti) * It is still reflected in the segment length for * sequencing purposes. */ +static void tcp_pulloutofband(so, ti, m) struct socket *so; struct tcpiphdr *ti; @@ -1283,6 +1320,7 @@ tcp_pulloutofband(so, ti, m) * Collect new round-trip time estimate * and update averages and current timeout. */ +static void tcp_xmit_timer(tp) register struct tcpcb *tp; { @@ -1366,7 +1404,7 @@ tcp_xmit_timer(tp) * While looking at the routing entry, we also initialize other path-dependent * parameters from pre-set or cached values in the routing entry. */ - +int tcp_mss(tp, offer) register struct tcpcb *tp; u_short offer; @@ -1462,20 +1500,22 @@ tcp_mss(tp, offer) bufsize = so->so_snd.sb_hiwat; if (bufsize < mss) mss = bufsize; - else { + else bufsize = min(bufsize, SB_MAX) / mss * mss; - (void) sbreserve(&so->so_snd, bufsize); - } + + (void) sbreserve(&so->so_snd, bufsize); tp->t_maxseg = mss; #ifdef RTV_RPIPE if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0) #endif bufsize = so->so_rcv.sb_hiwat; - if (bufsize > mss) { + if (bufsize < mss) + bufsize = mss; + else bufsize = min(bufsize, SB_MAX) / mss * mss; - (void) sbreserve(&so->so_rcv, bufsize); - } + + (void) sbreserve(&so->so_rcv, bufsize); } tp->snd_cwnd = mss; diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 5eb58fb5c9a3..d3e1b8d89cb6 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tcp_output.c 7.22 (Berkeley) 8/31/90 - * $Id: tcp_output.c,v 1.2 1993/10/16 18:26:29 rgrimes Exp $ + * $Id: tcp_output.c,v 1.4 1994/01/24 05:12:34 davidg Exp $ */ #include "param.h" @@ -57,10 +57,8 @@ #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" +#ifdef TCPDEBUG #include "tcp_debug.h" - -#ifdef notyet -extern struct mbuf *m_copypack(); #endif /* @@ -71,6 +69,7 @@ u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; /* * Tcp output routine: figure out what should be sent and send it. */ +int tcp_output(tp) register struct tcpcb *tp; { @@ -79,7 +78,7 @@ tcp_output(tp) int off, flags, error; register struct mbuf *m; register struct tcpiphdr *ti; - u_char *opt; + u_char *opt = 0; unsigned optlen, hdrlen; int idle, sendalot; @@ -434,11 +433,13 @@ send: if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) tp->snd_max = tp->snd_nxt + len; +#ifdef TCPDEBUG /* * Trace. */ if (so->so_options & SO_DEBUG) tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); +#endif /* * Fill in IP length and desired time to live and @@ -460,7 +461,7 @@ send: if (error) { out: if (error == ENOBUFS) { - tcp_quench(tp->t_inpcb); + tcp_quench(tp->t_inpcb, 0); return (0); } if ((error == EHOSTUNREACH || error == ENETDOWN) @@ -486,6 +487,7 @@ out: return (0); } +void tcp_setpersist(tp) register struct tcpcb *tp; { diff --git a/sys/netinet/tcp_seq.h b/sys/netinet/tcp_seq.h index 437ea7076b19..266362515a04 100644 --- a/sys/netinet/tcp_seq.h +++ b/sys/netinet/tcp_seq.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp_seq.h 7.4 (Berkeley) 6/28/90 - * $Id: tcp_seq.h,v 1.2 1993/10/16 18:26:30 rgrimes Exp $ + * $Id: tcp_seq.h,v 1.3 1993/11/07 17:48:07 wollman Exp $ */ +#ifndef _NETINET_TCP_SEQ_H_ +#define _NETINET_TCP_SEQ_H_ 1 + /* * TCP sequence numbers are 32 bit integers operated * on with modular arithmetic. These macros can be @@ -59,5 +62,6 @@ #define TCP_ISSINCR (125*1024) /* increment for tcp_iss each second */ #ifdef KERNEL -tcp_seq tcp_iss; /* tcp initial send seq # */ +extern tcp_seq tcp_iss; /* tcp initial send seq # */ #endif +#endif /* _NETINET_TCP_SEQ_H_ */ diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 8558464fb70a..eea64bb08ab1 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tcp_subr.c 7.20 (Berkeley) 12/1/90 - * $Id: tcp_subr.c,v 1.2 1993/10/16 18:26:31 rgrimes Exp $ + * $Id: tcp_subr.c,v 1.6 1993/12/19 00:52:50 wollman Exp $ */ #include "param.h" @@ -50,6 +50,7 @@ #include "in_systm.h" #include "ip.h" #include "in_pcb.h" +#include "in_var.h" #include "ip_var.h" #include "ip_icmp.h" #include "tcp.h" @@ -59,16 +60,18 @@ #include "tcp_var.h" #include "tcpip.h" -/* patchable/settable parameters for tcp */ -int tcp_ttl = TCP_TTL; -int tcp_mssdflt = TCP_MSS; -int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ; +tcp_seq tcp_iss; +struct inpcb tcb; +struct tcpstat tcpstat; -extern struct inpcb *tcp_last_inpcb; +#ifdef MTUDISC +int tcp_mtuchanged(struct inpcb *, int); +#endif /* * Tcp initialization */ +void tcp_init() { @@ -133,6 +136,7 @@ tcp_template(tp) * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ +void tcp_respond(tp, ti, m, ack, seq, flags) struct tcpcb *tp; register struct tcpiphdr *ti; @@ -227,6 +231,13 @@ tcp_newtcpcb(inp) tp->snd_ssthresh = TCP_MAXWIN; inp->inp_ip.ip_ttl = tcp_ttl; inp->inp_ppcb = (caddr_t)tp; +#ifdef MTUDISC + /* + * Enable Path MTU Discovery on this PCB. + */ + inp->inp_mtunotify = tcp_mtuchanged; + inp->inp_flags |= INP_DISCOVERMTU; +#endif /* MTUDISC */ return (tp); } @@ -286,7 +297,7 @@ tcp_close(tp) if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) && (rt = inp->inp_route.ro_rt) && ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) { - register u_long i; + register u_long i = 0; if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) { i = tp->t_srtt * @@ -337,7 +348,7 @@ tcp_close(tp) rt->rt_rmx.rmx_ssthresh = i; } } -#endif RTV_RTT +#endif /* RTV_RTT */ /* free the reassembly queue, if any */ t = tp->seg_next; while (t != (struct tcpiphdr *)tp) { @@ -359,6 +370,7 @@ tcp_close(tp) return ((struct tcpcb *)0); } +void tcp_drain() { @@ -369,6 +381,7 @@ tcp_drain() * store error as soft error, but wake up user * (for now, won't do anything until can select for soft error). */ +void tcp_notify(inp, error) register struct inpcb *inp; int error; @@ -380,18 +393,55 @@ tcp_notify(inp, error) sowwakeup(inp->inp_socket); } +/* + * When we get a PRC_MSGSIZE error (generated by the ICMP layer upon + * receipt of an ICMP_UNREACH_NEEDFRAG message), we need to get the + * IP layer to check the cached MTU data that it has in its PCBs. + * If things have changed, this will cause us to receive a + * PRC_MTUCHANGED message for /every/ connection to the same + * destination; that is handled by he tcp_mtuchanged() function, + * below. + * + * In the immortal words of Ken and Dennis, ``You are not expected to + * understand this.'' + */ +void +tcp_checkmtu(struct inpcb *inp, int error) { +#ifdef MTUDISC + /* + * XXX - this should also cause an immediate retransmission and + * slow start, since we know for a fact that the message we just sent + * got dropped on the floor. For now, just do what tcp_quench does. + */ + tcp_quench(inp); + in_pcbmtu(inp); +#endif /* MTUDISC */ +} + +#ifdef MTUDISC +int /* grrr... should be void... */ +tcp_mtuchanged(struct inpcb *inp, int error) { + /* don't do anything just yet... */; +} +#endif /* MTUDISC */ + +void tcp_ctlinput(cmd, sa, ip) int cmd; struct sockaddr *sa; register struct ip *ip; { register struct tcphdr *th; - extern struct in_addr zeroin_addr; - extern u_char inetctlerrmap[]; - int (*notify)() = tcp_notify, tcp_quench(); + void (*notify)(struct inpcb *, int) = tcp_notify; if (cmd == PRC_QUENCH) notify = tcp_quench; +#ifdef MTUDISC + else if (cmd == PRC_MSGSIZE) + notify = tcp_checkmtu; + else if (cmd == PRC_MTUCHANGED) /* just in case */ + notify = tcp_mtuchanged; +#endif /* MTUDISC */ else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0) return; if (ip) { @@ -406,8 +456,10 @@ tcp_ctlinput(cmd, sa, ip) * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. */ -tcp_quench(inp) +void +tcp_quench(inp, errno) struct inpcb *inp; + int errno; { struct tcpcb *tp = intotcpcb(inp); diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index f43a507b861a..e22a337deeb3 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tcp_timer.c 7.18 (Berkeley) 6/28/90 - * $Id: tcp_timer.c,v 1.2 1993/10/16 18:26:33 rgrimes Exp $ + * $Id: tcp_timer.c,v 1.4 1993/12/19 00:52:52 wollman Exp $ */ #include "param.h" @@ -58,12 +58,10 @@ #include "tcp_var.h" #include "tcpip.h" -int tcp_keepidle = TCPTV_KEEP_IDLE; -int tcp_keepintvl = TCPTV_KEEPINTVL; -int tcp_maxidle; /* * Fast timeout routine for processing delayed acks */ +void tcp_fasttimo() { register struct inpcb *inp; @@ -88,6 +86,7 @@ tcp_fasttimo() * Updates the timers in all active tcb's and * causes finite state machine actions if timers expire. */ +void tcp_slowtimo() { register struct inpcb *ip, *ipnxt; @@ -113,7 +112,8 @@ tcp_slowtimo() if (tp->t_timer[i] && --tp->t_timer[i] == 0) { (void) tcp_usrreq(tp->t_inpcb->inp_socket, PRU_SLOWTIMO, (struct mbuf *)0, - (struct mbuf *)i, (struct mbuf *)0); + (struct mbuf *)i, (struct mbuf *)0, + (struct mbuf *)0); if (ipnxt->inp_prev != ip) goto tpgone; } @@ -135,6 +135,7 @@ tpgone: /* * Cancel all timers for TCP tp. */ +void tcp_canceltimers(tp) struct tcpcb *tp; { diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index 05106e438448..21cd4c06959b 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp_timer.h 7.8 (Berkeley) 6/28/90 - * $Id: tcp_timer.h,v 1.2 1993/10/16 18:26:35 rgrimes Exp $ + * $Id: tcp_timer.h,v 1.4 1993/11/25 01:35:19 wollman Exp $ */ +#ifndef _NETINET_TCP_TIMER_H_ +#define _NETINET_TCP_TIMER_H_ 1 + /* * Definitions of the TCP timers. These timers are counted * down PR_SLOWHZ times a second. @@ -106,7 +109,7 @@ #define TCP_MAXRXTSHIFT 12 /* maximum retransmits */ #ifdef TCPTIMERS -char *tcptimers[] = +const char *tcptimers[] = { "REXMT", "PERSIST", "KEEP", "2MSL" }; #endif @@ -115,9 +118,9 @@ char *tcptimers[] = */ #define TCPT_RANGESET(tv, value, tvmin, tvmax) { \ (tv) = (value); \ - if ((tv) < (tvmin)) \ + if ((u_long)(tv) < (u_long)(tvmin)) \ (tv) = (tvmin); \ - else if ((tv) > (tvmax)) \ + else if ((u_long)(tv) > (u_long)(tvmax)) \ (tv) = (tvmax); \ } @@ -128,3 +131,4 @@ extern int tcp_maxidle; /* time to drop after starting probes */ extern int tcp_ttl; /* time to live for TCP segs */ extern int tcp_backoff[]; #endif +#endif /* _NETINET_TCP_TIMER_H_ */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index f0f51fcb40b8..b6f377690856 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)tcp_usrreq.c 7.15 (Berkeley) 6/28/90 - * $Id: tcp_usrreq.c,v 1.2 1993/10/16 18:26:36 rgrimes Exp $ + * $Id: tcp_usrreq.c,v 1.5 1994/01/24 05:12:36 davidg Exp $ */ #include "param.h" @@ -58,13 +58,14 @@ #include "tcp_timer.h" #include "tcp_var.h" #include "tcpip.h" +#ifdef TCPDEBUG #include "tcp_debug.h" +#endif /* * TCP protocol interface to socket abstraction. */ extern char *tcpstates[]; -struct tcpcb *tcp_newtcpcb(); /* * Process a TCP user request for TCP tb. If this is a send request @@ -72,13 +73,15 @@ struct tcpcb *tcp_newtcpcb(); * (called from the software clock routine), then timertype tells which timer. */ /*ARGSUSED*/ -tcp_usrreq(so, req, m, nam, control) +int +tcp_usrreq(so, req, m, nam, control, dummy) struct socket *so; int req; struct mbuf *m, *nam, *control; + struct mbuf *dummy; { register struct inpcb *inp; - register struct tcpcb *tp; + register struct tcpcb *tp = 0; int s; int error = 0; int ostate; @@ -331,12 +334,15 @@ tcp_usrreq(so, req, m, nam, control) default: panic("tcp_usrreq"); } +#ifdef TCPDEBUG if (tp && (so->so_options & SO_DEBUG)) tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req); +#endif splx(s); return (error); } +int tcp_ctloutput(op, so, level, optname, mp) int op; struct socket *so; @@ -395,19 +401,12 @@ tcp_ctloutput(op, so, level, optname, mp) return (error); } -#ifdef TCP_SMALLSPACE -u_long tcp_sendspace = 1024*4; -u_long tcp_recvspace = 1024*4; -#else -u_long tcp_sendspace = 1024*16; -u_long tcp_recvspace = 1024*16; -#endif /* TCP_SMALLSPACE */ - /* * Attach TCP protocol to socket, allocating * internet protocol control block, tcp control block, * bufer space, and entering LISTEN state if to accept connections. */ +int tcp_attach(so) struct socket *so; { diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index ed51ec057191..8d70a9b26906 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcp_var.h 7.10 (Berkeley) 6/28/90 - * $Id: tcp_var.h,v 1.2 1993/10/16 18:26:38 rgrimes Exp $ + * $Id: tcp_var.h,v 1.5 1993/12/19 00:52:54 wollman Exp $ */ +#ifndef _NETINET_TCP_VAR_H_ +#define _NETINET_TCP_VAR_H_ 1 + /* * Kernel variables for tcp. */ @@ -211,9 +214,60 @@ struct tcpstat { }; #ifdef KERNEL -struct inpcb tcb; /* head of queue of active tcpcb's */ -struct tcpstat tcpstat; /* tcp statistics */ -struct tcpiphdr *tcp_template(); -struct tcpcb *tcp_close(), *tcp_drop(); -struct tcpcb *tcp_timers(), *tcp_disconnect(), *tcp_usrclosed(); +extern struct inpcb tcb; /* head of queue of active tcpcb's */ +extern struct tcpstat tcpstat; /* tcp statistics */ + +/* From tcp_input.c: */ +extern int tcp_reass(struct tcpcb *, struct tcpiphdr *, struct mbuf *); +extern void tcp_input(struct mbuf *, int); +extern int tcp_mss(struct tcpcb *, int /*u_short*/); + +/* From tcp_output.c: */ +extern int tcp_output(struct tcpcb *); +extern void tcp_setpersist(struct tcpcb *); + +/* From tcp_subr.c: */ +extern void tcp_init(void); +extern struct tcpiphdr *tcp_template(struct tcpcb *); +extern void tcp_respond(struct tcpcb *, struct tcpiphdr *, struct mbuf *, + tcp_seq, tcp_seq, int); +extern struct tcpcb *tcp_newtcpcb(struct inpcb *); +extern struct tcpcb *tcp_drop(struct tcpcb *, int); +extern struct tcpcb *tcp_close(struct tcpcb *); +extern void tcp_drain(void); +extern void tcp_notify(struct inpcb *, int); +#ifdef MTUDISC +extern void tcp_checkmtu(struct inpcb *, int); +extern void tcp_mtuchanged(struct inpcb *, int); #endif +extern void tcp_ctlinput(int, struct sockaddr *, struct ip *); +extern void tcp_quench(struct inpcb *, int); + +/* From tcp_timer.c: */ +extern void tcp_fasttimo(void); +extern void tcp_slowtimo(void); +extern void tcp_canceltimers(struct tcpcb *); +extern struct tcpcb *tcp_timers(struct tcpcb *, int); + +/* From tcp_usrreq.c: */ +extern int tcp_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, + struct mbuf *, struct mbuf *); +extern int tcp_ctloutput(int, struct socket *, int, int, struct mbuf **); +extern int tcp_attach(struct socket *); +extern struct tcpcb *tcp_disconnect(struct tcpcb *); +extern struct tcpcb *tcp_usrclosed(struct tcpcb *); + +extern struct inpcb *tcp_last_inpcb; + +/* From in_var.c: */ +extern int tcp_ttl; +extern int tcp_mssdflt; +extern int tcp_rttdflt; +extern int tcp_keepidle; +extern int tcp_keepintvl; +extern int tcp_maxidle; +extern u_long tcp_sendspace; +extern u_long tcp_recvspace; + +#endif /* KERNEL */ +#endif /* _NETINET_TCP_VAR_H_ */ diff --git a/sys/netinet/tcpip.h b/sys/netinet/tcpip.h index 69e54216080b..cd17fa5cfbc7 100644 --- a/sys/netinet/tcpip.h +++ b/sys/netinet/tcpip.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)tcpip.h 7.4 (Berkeley) 6/28/90 - * $Id: tcpip.h,v 1.2 1993/10/16 18:26:40 rgrimes Exp $ + * $Id: tcpip.h,v 1.3 1993/11/07 17:48:12 wollman Exp $ */ +#ifndef _NETINET_TCPIP_H_ +#define _NETINET_TCPIP_H_ 1 + /* * Tcp+ip header, after ip options removed. */ @@ -58,3 +61,4 @@ struct tcpiphdr { #define ti_win ti_t.th_win #define ti_sum ti_t.th_sum #define ti_urp ti_t.th_urp +#endif /* _NETINET_TCPIP_H_ */ diff --git a/sys/netinet/udp.h b/sys/netinet/udp.h index d6ecd5c8f7c2..b4e00136bcc6 100644 --- a/sys/netinet/udp.h +++ b/sys/netinet/udp.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)udp.h 7.4 (Berkeley) 6/28/90 - * $Id: udp.h,v 1.2 1993/10/16 18:26:41 rgrimes Exp $ + * $Id: udp.h,v 1.3 1993/11/07 17:48:13 wollman Exp $ */ +#ifndef _NETINET_UDP_H_ +#define _NETINET_UDP_H_ 1 + /* * Udp protocol header. * Per RFC 768, September, 1981. @@ -44,3 +47,4 @@ struct udphdr { short uh_ulen; /* udp length */ u_short uh_sum; /* udp checksum */ }; +#endif /* _NETINET_UDP_H_ */ diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 726988226d78..44e244c31c95 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -31,10 +31,11 @@ * SUCH DAMAGE. * * from: @(#)udp_usrreq.c 7.20 (Berkeley) 4/20/91 - * $Id: udp_usrreq.c,v 1.2 1993/10/16 18:26:43 rgrimes Exp $ + * $Id: udp_usrreq.c,v 1.7 1994/02/07 19:53:25 ache Exp $ */ #include "param.h" +#include "systm.h" #include "malloc.h" #include "mbuf.h" #include "protosw.h" @@ -47,6 +48,7 @@ #include "in.h" #include "in_systm.h" +#include "in_var.h" #include "ip.h" #include "in_pcb.h" #include "ip_var.h" @@ -54,27 +56,25 @@ #include "udp.h" #include "udp_var.h" -struct inpcb *udp_last_inpcb = &udb; +struct inpcb udb; /* Can't be static, because of netstat want it */ +static struct inpcb *udp_last_inpcb = &udb; + +static void udp_detach(struct inpcb *); /* * UDP protocol implementation. * Per RFC 768, August, 1980. */ +void udp_init() { udb.inp_next = udb.inp_prev = &udb; } -#ifndef COMPAT_42 -int udpcksum = 1; -#else -int udpcksum = 0; /* XXX */ -#endif -int udp_ttl = UDP_TTL; - -struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; +static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; +void udp_input(m, iphlen) register struct mbuf *m; int iphlen; @@ -169,7 +169,10 @@ udp_input(m, iphlen) } *ip = save_ip; ip->ip_len += iphlen; - icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT); + { + static struct in_addr fake; + icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, fake, 0); + } return; } @@ -252,8 +255,10 @@ udp_saveopt(p, size, type) * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */ +void udp_notify(inp, errno) register struct inpcb *inp; + int errno; { inp->inp_socket->so_error = errno; @@ -261,6 +266,7 @@ udp_notify(inp, errno) sowwakeup(inp->inp_socket); } +void udp_ctlinput(cmd, sa, ip) int cmd; struct sockaddr *sa; @@ -280,6 +286,7 @@ udp_ctlinput(cmd, sa, ip) in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify); } +int udp_output(inp, m, addr, control) register struct inpcb *inp; register struct mbuf *m; @@ -288,7 +295,7 @@ udp_output(inp, m, addr, control) register struct udpiphdr *ui; register int len = m->m_pkthdr.len; struct in_addr laddr; - int s, error = 0; + int s = 0, error = 0; if (control) m_freem(control); /* XXX */ @@ -362,11 +369,8 @@ release: return (error); } -u_long udp_sendspace = 9216; /* really max datagram size */ -u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); - /* 40 1K datagrams */ - /*ARGSUSED*/ +int udp_usrreq(so, req, m, addr, control) struct socket *so; int req; @@ -503,6 +507,7 @@ release: return (error); } +static void udp_detach(inp) struct inpcb *inp; { diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index bb97b4b5a64e..8bd35b466078 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -31,9 +31,12 @@ * SUCH DAMAGE. * * from: @(#)udp_var.h 7.7 (Berkeley) 6/28/90 - * $Id: udp_var.h,v 1.2 1993/10/16 18:26:44 rgrimes Exp $ + * $Id: udp_var.h,v 1.4 1993/12/19 00:52:57 wollman Exp $ */ +#ifndef _NETINET_UDP_VAR_H_ +#define _NETINET_UDP_VAR_H_ 1 + /* * UDP kernel structures and variables. */ @@ -70,6 +73,14 @@ struct udpstat { #define UDP_TTL 30 /* default time to live for UDP packets */ #ifdef KERNEL -struct inpcb udb; -struct udpstat udpstat; -#endif +extern struct inpcb udb; +extern struct udpstat udpstat; + +/* From in_var.h: */ +extern int udpcksum; +extern int udp_ttl; +extern u_long udp_sendspace; +extern u_long udp_recvspace; + +#endif /* KERNEL */ +#endif /* _NETINET_UDP_VAR_H_ */ |
