bostic@OKEEFFE.BERKELEY.EDU (Keith Bostic) (04/05/88)
Subject: (socket 1 of 2) updated IP/TCP and XNS sources for 4.3BSD Index: sys 4.3BSD Description: This is number 8 of 11 total articles posted to the newsgroup comp.bugs.4bsd.ucb-fixes. This archive is number 1 of the 2 articles that make up the socket posting. # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # README # h # h/domain.h # h/protosw.h # h/socket.h # h/un.h # h/unpcb.h # net # net/af.c # net/af.h # net/if.c # net/if.h # net/if_arp.h # net/if_loop.c # net/netisr.h # net/raw_cb.c # net/raw_cb.h # net/raw_usrreq.c # echo x - README sed 's/^X//' >README << 'END-of-README' XThis is the description of a release of updated networking software Xfor the 4.3BSD distribution from the University of California, Berkeley. XThese changes are part of the current Berkeley operating system and Xwill be included in future tape releases. This release is being Xmade available by anonymous FTP from the ARPANET and on the Usenet Xnewsgroup comp.bugs.4bsd.ucb-fixes. X XThe major changes in this release are in the TCP send policy. XBecause the improvements in the send policy could significantly Xreduce congestion on the ARPANET and the NSFNET, all sites with Xdirect or indirect connections to long-haul nets are urged to upgrade Xas quickly as possible. Vendors supplying TCP products based on 4.2BSD Xor 4.3BSD are strongly urged to update as quickly as possible. Vendors Xusing other TCP implementations should consider the use of the new algorithms Xas well, and may find the current Berkeley source code useful as a guide Xto their implementation. X XThe FTP release consists of five files: tcp.tar, inet.tar, netns.tar, Xsocket.tar and imp.tar. They are all present on host ucbarpa.Berkeley.EDU Xin the directory pub/4.3. (Each is also available in compressed form, Xindicated by a trailing ".Z".) Each archive file includes a copy of this Xfile (called README). X XThe first file, tcp.tar, contains sources for the current version of TCP, Xincluding the slow start algorithm and other work by Van Jacobson of LBL Xand a retransmission timer algorithm suggested by Phil Karn. It is designed Xto replace the 4.3BSD TCP, although it also has #ifdef's for installation Xin a 4.2-based system (including SunOS versions up to 3.6). The changes made Xsince the release of 4.3 dramatically improve performance over slow and/or Xlossy networks such as the ARPANET/Milnet and Satnet, and also reduce the Xnumber of unnecessary retransmissions nearly to zero. Performance on Xfast, local-area networks is also somewhat improved, especially on faster Xprocessors when larger buffers are used. Several new bug fixes have Xalso been made. The file TCP_INSTALL contains some hints on configuring XTCP for systems other than standard 4.3BSD and 4.2BSD. X XThe second file, inet.tar, contains sources for IP, ICMP, UDP and common Xinternet code (all of the netinet directory except the TCP sources). XIt also includes a few files from the sys and h directories that have Xbeen changed since the 4.3BSD release. There are changes in the processing Xof IP record-route and timestamp options and in handling of certain broadcast XUDP requests. The mbuf allocation routines include a fix for a race and Xchanges to call the protocol drain routines when appropriate, and will Xno longer panic when new allocation requests discover that the mbuf map Xhas been exhausted. A recent problem in the code for fragmenting IP packets Xwith options is fixed. The complete source for the netstat program is also Xincluded in inet.tar. It will be usable only on 4.3BSD systems without Xmodification. (Note: there are two versions of main.c and host.c in Xthe netstat directory. Unless you are installing the new imp code, Xyou must use main.c.oldimp and host.c.oldimp.) X XThe combination of tcp.tar and inet.tar is sufficient to upgrade a 4.3BSD Xsystem to the current level of IP/TCP. It is strongly recommended that X4.3BSD sites that are connected to the Internet, directly or indirectly, Xas well as 4.3BSD gateway sites, should upgrade as quickly as possible. X XThe third file, netns.tar, contains the current version of the Xerox NS Xprotocols from the netns source directory. The Sequenced Packet Protocol Xhas modifications similar to those in TCP, as well as several bug fixes. XSites that use XNS must upgrade it at the same time as TCP, as the old XXNS code used the old tcp_timer.h. X XThe fourth file, socket.tar, includes the remainder of the socket and generic Xnetwork source files. These files are identical to those in the 4.3BSD Xrelease. They are provided for completeness for those who do not have access Xto the original 4.3BSD sources. They are not required for installation Xof the TCP and other internet fixes in a 4.3BSD system, nor for installation Xof the new internet code into most 4.2BSD-derived systems. They may Xbe useful for upgrading the socket or network code in a 4.2BSD-derived Xsystem. We cannot provide any assistance in such upgrades, but we Xare interested in hearing about any successful upgrades. X XThe fifth file, imp.tar, includes recent modifications to the code for Xhandling an ARPANET/Milnet IMP using an AHIP (1822) interface. It was not Xquite ready for distribution when the rest of the update was finished, and Xmay not be present in the anonymous FTP area immediately. If you want Xit, check back later or watch for an announcement on the tcp-ip mailing Xlist. X XNote that the Berkeley network source code is *not* public-domain. XHowever, as it contains no code licensed by AT&T or others, it is owned Xby the Regents of the University of California, Berkeley. It is provided Xas-is, without any warranty, for any purpose. It may be used, modified or Xredistributed in source or binary forms, as long as due credit is given Xto the University and the University copyright notices are retained. X XThese sources may be updated from time to time as improvements or additions Xare made. The next update will include support for IP multicast done Xby Steve Deering at Stanford. Updates will be announced on the tcp-ip Xmailing list, which is redistributed on Usenet. X X Mike Karels karels@Berkeley.EDU X Van Jacobson van@lbl-csam.arpa END-of-README echo c - h mkdir h > /dev/null 2>&1 echo x - h/domain.h sed 's/^X//' >h/domain.h << 'END-of-h/domain.h' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)domain.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Structure per communications domain. X */ Xstruct domain { X int dom_family; /* AF_xxx */ X char *dom_name; X int (*dom_init)(); /* initialize domain data structures */ X int (*dom_externalize)(); /* externalize access rights */ X int (*dom_dispose)(); /* dispose of internalized rights */ X struct protosw *dom_protosw, *dom_protoswNPROTOSW; X struct domain *dom_next; X}; X X#ifdef KERNEL Xstruct domain *domains; X#endif END-of-h/domain.h echo x - h/protosw.h sed 's/^X//' >h/protosw.h << 'END-of-h/protosw.h' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)protosw.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Protocol switch table. X * X * Each protocol has a handle initializing one of these structures, X * which is used for protocol-protocol and system-protocol communication. X * X * A protocol is called through the pr_init entry before any other. X * Thereafter it is called every 200ms through the pr_fasttimo entry and X * every 500ms through the pr_slowtimo for timer based actions. X * The system will call the pr_drain entry if it is low on space and X * this should throw away any non-critical data. X * X * Protocols pass data between themselves as chains of mbufs using X * the pr_input and pr_output hooks. Pr_input passes data up (towards X * UNIX) and pr_output passes it down (towards the imps); control X * information passes up and down on pr_ctlinput and pr_ctloutput. X * The protocol is responsible for the space occupied by any the X * arguments to these entries and must dispose it. X * X * The userreq routine interfaces protocols to the system and is X * described below. X */ Xstruct protosw { X short pr_type; /* socket type used for */ X struct domain *pr_domain; /* domain protocol a member of */ X short pr_protocol; /* protocol number */ X short pr_flags; /* see below */ X/* protocol-protocol hooks */ X int (*pr_input)(); /* input to protocol (from below) */ X int (*pr_output)(); /* output to protocol (from above) */ X int (*pr_ctlinput)(); /* control input (from below) */ X int (*pr_ctloutput)(); /* control output (from above) */ X/* user-protocol hook */ X int (*pr_usrreq)(); /* user request: see list below */ X/* utility hooks */ X int (*pr_init)(); /* initialization hook */ X int (*pr_fasttimo)(); /* fast timeout (200ms) */ X int (*pr_slowtimo)(); /* slow timeout (500ms) */ X int (*pr_drain)(); /* flush any excess space possible */ X}; X X#define PR_SLOWHZ 2 /* 2 slow timeouts per second */ X#define PR_FASTHZ 5 /* 5 fast timeouts per second */ X X/* X * Values for pr_flags X */ X#define PR_ATOMIC 0x01 /* exchange atomic messages only */ X#define PR_ADDR 0x02 /* addresses given with messages */ X/* in the current implementation, PR_ADDR needs PR_ATOMIC to work */ X#define PR_CONNREQUIRED 0x04 /* connection required by protocol */ X#define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */ X#define PR_RIGHTS 0x10 /* passes capabilities */ X X/* X * The arguments to usrreq are: X * (*protosw[].pr_usrreq)(up, req, m, nam, opt); X * where up is a (struct socket *), req is one of these requests, X * m is a optional mbuf chain containing a message, X * nam is an optional mbuf chain containing an address, X * and opt is a pointer to a socketopt structure or nil. X * The protocol is responsible for disposal of the mbuf chain m, X * the caller is responsible for any space held by nam and opt. X * A non-zero return from usrreq gives an X * UNIX error number which should be passed to higher level software. X */ X#define PRU_ATTACH 0 /* attach protocol to up */ X#define PRU_DETACH 1 /* detach protocol from up */ X#define PRU_BIND 2 /* bind socket to address */ X#define PRU_LISTEN 3 /* listen for connection */ X#define PRU_CONNECT 4 /* establish connection to peer */ X#define PRU_ACCEPT 5 /* accept connection from peer */ X#define PRU_DISCONNECT 6 /* disconnect from peer */ X#define PRU_SHUTDOWN 7 /* won't send any more data */ X#define PRU_RCVD 8 /* have taken data; more room now */ X#define PRU_SEND 9 /* send this data */ X#define PRU_ABORT 10 /* abort (fast DISCONNECT, DETATCH) */ X#define PRU_CONTROL 11 /* control operations on protocol */ X#define PRU_SENSE 12 /* return status into m */ X#define PRU_RCVOOB 13 /* retrieve out of band data */ X#define PRU_SENDOOB 14 /* send out of band data */ X#define PRU_SOCKADDR 15 /* fetch socket's address */ X#define PRU_PEERADDR 16 /* fetch peer's address */ X#define PRU_CONNECT2 17 /* connect two sockets */ X/* begin for protocols internal use */ X#define PRU_FASTTIMO 18 /* 200ms timeout */ X#define PRU_SLOWTIMO 19 /* 500ms timeout */ X#define PRU_PROTORCV 20 /* receive from below */ X#define PRU_PROTOSEND 21 /* send to below */ X X#define PRU_NREQ 21 X X#ifdef PRUREQUESTS Xchar *prurequests[] = { X "ATTACH", "DETACH", "BIND", "LISTEN", X "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN", X "RCVD", "SEND", "ABORT", "CONTROL", X "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR", X "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO", X "PROTORCV", "PROTOSEND", X}; X#endif X X/* X * The arguments to the ctlinput routine are X * (*protosw[].pr_ctlinput)(cmd, arg); X * where cmd is one of the commands below, and arg is X * an optional argument (caddr_t). X * X * N.B. The IMP code, in particular, pressumes the values X * of some of the commands; change with extreme care. X * TODO: X * spread out codes so new ICMP codes can be X * accomodated more easily X */ X#define PRC_IFDOWN 0 /* interface transition */ X#define PRC_ROUTEDEAD 1 /* select new route if possible */ X#define PRC_QUENCH 4 /* some said to slow down */ X#define PRC_MSGSIZE 5 /* message size forced drop */ X#define PRC_HOSTDEAD 6 /* normally from IMP */ X#define PRC_HOSTUNREACH 7 /* ditto */ X#define PRC_UNREACH_NET 8 /* no route to network */ X#define PRC_UNREACH_HOST 9 /* no route to host */ X#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ X#define PRC_UNREACH_PORT 11 /* bad port # */ X#define PRC_UNREACH_NEEDFRAG 12 /* IP_DF caused drop */ X#define PRC_UNREACH_SRCFAIL 13 /* source route failed */ X#define PRC_REDIRECT_NET 14 /* net routing redirect */ X#define PRC_REDIRECT_HOST 15 /* host routing redirect */ X#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ X#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ X#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ X#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ X#define PRC_PARAMPROB 20 /* header incorrect */ X X#define PRC_NCMDS 21 X X#ifdef PRCREQUESTS Xchar *prcrequests[] = { X "IFDOWN", "ROUTEDEAD", "#2", "#3", X "QUENCH", "MSGSIZE", "HOSTDEAD", "HOSTUNREACH", X "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", X "FRAG-UNREACH", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", X "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", X "PARAMPROB" X}; X#endif X X/* X * The arguments to ctloutput are: X * (*protosw[].pr_ctloutput)(req, so, level, optname, optval); X * req is one of the actions listed below, so is a (struct socket *), X * level is an indication of which protocol layer the option is intended. X * optname is a protocol dependent socket option request, X * optval is a pointer to a mbuf-chain pointer, for value-return results. X * The protocol is responsible for disposal of the mbuf chain *optval X * if supplied, X * the caller is responsible for any space held by *optval, when returned. X * A non-zero return from usrreq gives an X * UNIX error number which should be passed to higher level software. X */ X#define PRCO_GETOPT 0 X#define PRCO_SETOPT 1 X X#define PRCO_NCMDS 2 X X#ifdef PRCOREQUESTS Xchar *prcorequests[] = { X "GETOPT", "SETOPT", X}; X#endif X X#ifdef KERNEL Xextern struct protosw *pffindproto(), *pffindtype(); X#endif END-of-h/protosw.h echo x - h/socket.h sed 's/^X//' >h/socket.h << 'END-of-h/socket.h' X/* X * Copyright (c) 1982, 1985, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)socket.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Definitions related to sockets: types, address families, options. X */ X X/* X * Types X */ X#define SOCK_STREAM 1 /* stream socket */ X#define SOCK_DGRAM 2 /* datagram socket */ X#define SOCK_RAW 3 /* raw-protocol interface */ X#define SOCK_RDM 4 /* reliably-delivered message */ X#define SOCK_SEQPACKET 5 /* sequenced packet stream */ X X/* X * Option flags per-socket. X */ X#define SO_DEBUG 0x0001 /* turn on debugging info recording */ X#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ X#define SO_REUSEADDR 0x0004 /* allow local address reuse */ X#define SO_KEEPALIVE 0x0008 /* keep connections alive */ X#define SO_DONTROUTE 0x0010 /* just use interface addresses */ X#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */ X#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */ X#define SO_LINGER 0x0080 /* linger on close if data present */ X#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */ X X/* X * Additional options, not kept in so_options. X */ X#define SO_SNDBUF 0x1001 /* send buffer size */ X#define SO_RCVBUF 0x1002 /* receive buffer size */ X#define SO_SNDLOWAT 0x1003 /* send low-water mark */ X#define SO_RCVLOWAT 0x1004 /* receive low-water mark */ X#define SO_SNDTIMEO 0x1005 /* send timeout */ X#define SO_RCVTIMEO 0x1006 /* receive timeout */ X#define SO_ERROR 0x1007 /* get error status and clear */ X#define SO_TYPE 0x1008 /* get socket type */ X X/* X * Structure used for manipulating linger option. X */ Xstruct linger { X int l_onoff; /* option on/off */ X int l_linger; /* linger time */ X}; X X/* X * Level number for (get/set)sockopt() to apply to socket itself. X */ X#define SOL_SOCKET 0xffff /* options for socket level */ X X/* X * Address families. X */ X#define AF_UNSPEC 0 /* unspecified */ X#define AF_UNIX 1 /* local to host (pipes, portals) */ X#define AF_INET 2 /* internetwork: UDP, TCP, etc. */ X#define AF_IMPLINK 3 /* arpanet imp addresses */ X#define AF_PUP 4 /* pup protocols: e.g. BSP */ X#define AF_CHAOS 5 /* mit CHAOS protocols */ X#define AF_NS 6 /* XEROX NS protocols */ X#define AF_NBS 7 /* nbs protocols */ X#define AF_ECMA 8 /* european computer manufacturers */ X#define AF_DATAKIT 9 /* datakit protocols */ X#define AF_CCITT 10 /* CCITT protocols, X.25 etc */ X#define AF_SNA 11 /* IBM SNA */ X#define AF_DECnet 12 /* DECnet */ X#define AF_DLI 13 /* Direct data link interface */ X#define AF_LAT 14 /* LAT */ X#define AF_HYLINK 15 /* NSC Hyperchannel */ X#define AF_APPLETALK 16 /* Apple Talk */ X X#define AF_MAX 17 X X/* X * Structure used by kernel to store most X * addresses. X */ Xstruct sockaddr { X u_short sa_family; /* address family */ X char sa_data[14]; /* up to 14 bytes of direct address */ X}; X X/* X * Structure used by kernel to pass protocol X * information in raw sockets. X */ Xstruct sockproto { X u_short sp_family; /* address family */ X u_short sp_protocol; /* protocol */ X}; X X/* X * Protocol families, same as address families for now. X */ X#define PF_UNSPEC AF_UNSPEC X#define PF_UNIX AF_UNIX X#define PF_INET AF_INET X#define PF_IMPLINK AF_IMPLINK X#define PF_PUP AF_PUP X#define PF_CHAOS AF_CHAOS X#define PF_NS AF_NS X#define PF_NBS AF_NBS X#define PF_ECMA AF_ECMA X#define PF_DATAKIT AF_DATAKIT X#define PF_CCITT AF_CCITT X#define PF_SNA AF_SNA X#define PF_DECnet AF_DECnet X#define PF_DLI AF_DLI X#define PF_LAT AF_LAT X#define PF_HYLINK AF_HYLINK X#define PF_APPLETALK AF_APPLETALK X X#define PF_MAX AF_MAX X X/* X * Maximum queue length specifiable by listen. X */ X#define SOMAXCONN 5 X X/* X * Message header for recvmsg and sendmsg calls. X */ Xstruct msghdr { X caddr_t msg_name; /* optional address */ X int msg_namelen; /* size of address */ X struct iovec *msg_iov; /* scatter/gather array */ X int msg_iovlen; /* # elements in msg_iov */ X caddr_t msg_accrights; /* access rights sent/received */ X int msg_accrightslen; X}; X X#define MSG_OOB 0x1 /* process out-of-band data */ X#define MSG_PEEK 0x2 /* peek at incoming message */ X#define MSG_DONTROUTE 0x4 /* send without using routing tables */ X X#define MSG_MAXIOVLEN 16 END-of-h/socket.h echo x - h/un.h sed 's/^X//' >h/un.h << 'END-of-h/un.h' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)un.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Definitions for UNIX IPC domain. X */ Xstruct sockaddr_un { X short sun_family; /* AF_UNIX */ X char sun_path[108]; /* path name (gag) */ X}; X X#ifdef KERNEL Xint unp_discard(); X#endif END-of-h/un.h echo x - h/unpcb.h sed 's/^X//' >h/unpcb.h << 'END-of-h/unpcb.h' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)unpcb.h 7.2 (Berkeley) 1/7/88 X */ X X/* X * Protocol control block for an active X * instance of a UNIX internal protocol. X * X * A socket may be associated with an inode in the X * file system. If so, the unp_inode pointer holds X * a reference count to this inode, which should be irele'd X * when the socket goes away. X * X * A socket may be connected to another socket, in which X * case the control block of the socket to which it is connected X * is given by unp_conn. X * X * A socket may be referenced by a number of sockets (e.g. several X * sockets may be connected to a datagram socket.) These sockets X * are in a linked list starting with unp_refs, linked through X * unp_nextref and null-terminated. Note that a socket may be referenced X * by a number of other sockets and may also reference a socket (not X * necessarily one which is referencing it). This generates X * the need for unp_refs and unp_nextref to be separate fields. X * X * Stream sockets keep copies of receive sockbuf sb_cc and sb_mbcnt X * so that changes in the sockbuf may be computed to modify X * back pressure on the sender accordingly. X */ Xstruct unpcb { X struct socket *unp_socket; /* pointer back to socket */ X struct inode *unp_inode; /* if associated with file */ X ino_t unp_ino; /* fake inode number */ X struct unpcb *unp_conn; /* control block of connected socket */ X struct unpcb *unp_refs; /* referencing socket linked list */ X struct unpcb *unp_nextref; /* link in unp_refs list */ X struct mbuf *unp_addr; /* bound address of socket */ X int unp_cc; /* copy of rcv.sb_cc */ X int unp_mbcnt; /* copy of rcv.sb_mbcnt */ X}; X X#define sotounpcb(so) ((struct unpcb *)((so)->so_pcb)) END-of-h/unpcb.h echo c - net mkdir net > /dev/null 2>&1 echo x - net/af.c sed 's/^X//' >net/af.c << 'END-of-net/af.c' X/* X * Copyright (c) 1983, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)af.c 7.3 (Berkeley) 12/30/87 X */ X X#include "param.h" X#include "mbuf.h" X#include "protosw.h" X#include "socket.h" X#include "socketvar.h" X#include "af.h" X X/* X * Address family support routines X */ Xint null_hash(), null_netmatch(); X#define AFNULL \ X { null_hash, null_netmatch } X X#ifdef INET Xextern int inet_hash(), inet_netmatch(); X#define AFINET \ X { inet_hash, inet_netmatch } X#else X#define AFINET AFNULL X#endif X X#ifdef NS Xextern int ns_hash(), ns_netmatch(); X#define AFNS \ X { ns_hash, ns_netmatch } X#else X#define AFNS AFNULL X#endif X Xstruct afswitch afswitch[AF_MAX] = { X AFNULL, AFNULL, AFINET, AFINET, AFNULL, X AFNULL, AFNS, AFNULL, AFNULL, AFNULL, X AFNULL, AFNULL, AFNULL, AFNULL, AFNULL, X AFNULL, AFNULL, /* through 16 */ X}; X Xnull_init() X{ X register struct afswitch *af; X X for (af = afswitch; af < &afswitch[AF_MAX]; af++) X if (af->af_hash == (int (*)())NULL) { X af->af_hash = null_hash; X af->af_netmatch = null_netmatch; X } X} X X/*ARGSUSED*/ Xnull_hash(addr, hp) X struct sockaddr *addr; X struct afhash *hp; X{ X X hp->afh_nethash = hp->afh_hosthash = 0; X} X X/*ARGSUSED*/ Xnull_netmatch(a1, a2) X struct sockaddr *a1, *a2; X{ X X return (0); X} END-of-net/af.c echo x - net/af.h sed 's/^X//' >net/af.h << 'END-of-net/af.h' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)af.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Address family routines, X * used in handling generic sockaddr structures. X * X * Hash routine is called X * af_hash(addr, h); X * struct sockaddr *addr; struct afhash *h; X * producing an afhash structure for addr. X * X * Netmatch routine is called X * af_netmatch(addr1, addr2); X * where addr1 and addr2 are sockaddr *. Returns 1 if network X * values match, 0 otherwise. X */ Xstruct afswitch { X int (*af_hash)(); X int (*af_netmatch)(); X}; X Xstruct afhash { X u_int afh_hosthash; X u_int afh_nethash; X}; X X#ifdef KERNEL Xstruct afswitch afswitch[]; X#endif END-of-net/af.h echo x - net/if.c sed 's/^X//' >net/if.c << 'END-of-net/if.c' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * %W% (Berkeley) %G% X */ X X#include "param.h" X#include "mbuf.h" X#include "systm.h" X#include "socket.h" X#include "socketvar.h" X#include "protosw.h" X#include "dir.h" X#include "user.h" X#include "kernel.h" X#include "ioctl.h" X#include "errno.h" X X#include "if.h" X#include "af.h" X X#include "ether.h" X Xint ifqmaxlen = IFQ_MAXLEN; X X/* X * Network interface utility routines. X * X * Routines with ifa_ifwith* names take sockaddr *'s as X * parameters. X */ X Xifinit() X{ X register struct ifnet *ifp; X X for (ifp = ifnet; ifp; ifp = ifp->if_next) X if (ifp->if_snd.ifq_maxlen == 0) X ifp->if_snd.ifq_maxlen = ifqmaxlen; X if_slowtimo(); X} X X#ifdef vax X/* X * Call each interface on a Unibus reset. X */ Xifubareset(uban) X int uban; X{ X register struct ifnet *ifp; X X for (ifp = ifnet; ifp; ifp = ifp->if_next) X if (ifp->if_reset) X (*ifp->if_reset)(ifp->if_unit, uban); X} X#endif X X/* X * Attach an interface to the X * list of "active" interfaces. X */ Xif_attach(ifp) X struct ifnet *ifp; X{ X register struct ifnet **p = &ifnet; X X while (*p) X p = &((*p)->if_next); X *p = ifp; X} X X/* X * Locate an interface based on a complete address. X */ X/*ARGSUSED*/ Xstruct ifaddr * Xifa_ifwithaddr(addr) X struct sockaddr *addr; X{ X register struct ifnet *ifp; X register struct ifaddr *ifa; X X#define equal(a1, a2) \ X (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) X for (ifp = ifnet; ifp; ifp = ifp->if_next) X for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { X if (ifa->ifa_addr.sa_family != addr->sa_family) X continue; X if (equal(&ifa->ifa_addr, addr)) X return (ifa); X if ((ifp->if_flags & IFF_BROADCAST) && X equal(&ifa->ifa_broadaddr, addr)) X return (ifa); X } X return ((struct ifaddr *)0); X} X/* X * Locate the point to point interface with a given destination address. X */ X/*ARGSUSED*/ Xstruct ifaddr * Xifa_ifwithdstaddr(addr) X struct sockaddr *addr; X{ X register struct ifnet *ifp; X register struct ifaddr *ifa; X X for (ifp = ifnet; ifp; ifp = ifp->if_next) X if (ifp->if_flags & IFF_POINTOPOINT) X for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { X if (ifa->ifa_addr.sa_family != addr->sa_family) X continue; X if (equal(&ifa->ifa_dstaddr, addr)) X return (ifa); X } X return ((struct ifaddr *)0); X} X X/* X * Find an interface on a specific network. If many, choice X * is first found. X */ Xstruct ifaddr * Xifa_ifwithnet(addr) X register struct sockaddr *addr; X{ X register struct ifnet *ifp; X register struct ifaddr *ifa; X register u_int af = addr->sa_family; X register int (*netmatch)(); X X if (af >= AF_MAX) X return (0); X netmatch = afswitch[af].af_netmatch; X for (ifp = ifnet; ifp; ifp = ifp->if_next) X for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { X if (ifa->ifa_addr.sa_family != addr->sa_family) X continue; X if ((*netmatch)(&ifa->ifa_addr, addr)) X return (ifa); X } X return ((struct ifaddr *)0); X} X X#ifdef notdef X/* X * Find an interface using a specific address family X */ Xstruct ifaddr * Xifa_ifwithaf(af) X register int af; X{ X register struct ifnet *ifp; X register struct ifaddr *ifa; X X for (ifp = ifnet; ifp; ifp = ifp->if_next) X for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) X if (ifa->ifa_addr.sa_family == af) X return (ifa); X return ((struct ifaddr *)0); X} X#endif X X/* X * Mark an interface down and notify protocols of X * the transition. X * NOTE: must be called at splnet or eqivalent. X */ Xif_down(ifp) X register struct ifnet *ifp; X{ X register struct ifaddr *ifa; X X ifp->if_flags &= ~IFF_UP; X for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) X pfctlinput(PRC_IFDOWN, &ifa->ifa_addr); X if_qflush(&ifp->if_snd); X} X X/* X * Flush an interface queue. X */ Xif_qflush(ifq) X register struct ifqueue *ifq; X{ X register struct mbuf *m, *n; X X n = ifq->ifq_head; X while (m = n) { X n = m->m_act; X m_freem(m); X } X ifq->ifq_head = 0; X ifq->ifq_tail = 0; X ifq->ifq_len = 0; X} X X/* X * Handle interface watchdog timer routines. Called X * from softclock, we decrement timers (if set) and X * call the appropriate interface routine on expiration. X */ Xif_slowtimo() X{ X register struct ifnet *ifp; X X for (ifp = ifnet; ifp; ifp = ifp->if_next) { X if (ifp->if_timer == 0 || --ifp->if_timer) X continue; X if (ifp->if_watchdog) X (*ifp->if_watchdog)(ifp->if_unit); X } X timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); X} X X/* X * Map interface name to X * interface structure pointer. X */ Xstruct ifnet * Xifunit(name) X register char *name; X{ X register char *cp; X register struct ifnet *ifp; X int unit; X X for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) X if (*cp >= '0' && *cp <= '9') X break; X if (*cp == '\0' || cp == name + IFNAMSIZ) X return ((struct ifnet *)0); X unit = *cp - '0'; X for (ifp = ifnet; ifp; ifp = ifp->if_next) { X if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) X continue; X if (unit == ifp->if_unit) X break; X } X return (ifp); X} X X/* X * Interface ioctls. X */ Xifioctl(so, cmd, data) X struct socket *so; X int cmd; X caddr_t data; X{ X register struct ifnet *ifp; X register struct ifreq *ifr; X X switch (cmd) { X X case SIOCGIFCONF: X return (ifconf(cmd, data)); X X#if defined(INET) && NETHER > 0 X case SIOCSARP: X case SIOCDARP: X if (!suser()) X return (u.u_error); X /* FALL THROUGH */ X case SIOCGARP: X return (arpioctl(cmd, data)); X#endif X } X ifr = (struct ifreq *)data; X ifp = ifunit(ifr->ifr_name); X if (ifp == 0) X return (ENXIO); X switch (cmd) { X X case SIOCGIFFLAGS: X ifr->ifr_flags = ifp->if_flags; X break; X X case SIOCGIFMETRIC: X ifr->ifr_metric = ifp->if_metric; X break; X X case SIOCSIFFLAGS: X if (!suser()) X return (u.u_error); X if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { X int s = splimp(); X if_down(ifp); X splx(s); X } X ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | X (ifr->ifr_flags &~ IFF_CANTCHANGE); X if (ifp->if_ioctl) X (void) (*ifp->if_ioctl)(ifp, cmd, data); X break; X X case SIOCSIFMETRIC: X if (!suser()) X return (u.u_error); X ifp->if_metric = ifr->ifr_metric; X break; X X default: X if (so->so_proto == 0) X return (EOPNOTSUPP); X return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, X cmd, data, ifp)); X } X return (0); X} X X/* X * Return interface configuration X * of system. List may be used X * in later ioctl's (above) to get X * other information. X */ X/*ARGSUSED*/ Xifconf(cmd, data) X int cmd; X caddr_t data; X{ X register struct ifconf *ifc = (struct ifconf *)data; X register struct ifnet *ifp = ifnet; X register struct ifaddr *ifa; X register char *cp, *ep; X struct ifreq ifr, *ifrp; X int space = ifc->ifc_len, error = 0; X X ifrp = ifc->ifc_req; X ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; X for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { X bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); X for (cp = ifr.ifr_name; cp < ep && *cp; cp++) X ; X *cp++ = '0' + ifp->if_unit; *cp = '\0'; X if ((ifa = ifp->if_addrlist) == 0) { X bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); X error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); X if (error) X break; X space -= sizeof (ifr), ifrp++; X } else X for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { X ifr.ifr_addr = ifa->ifa_addr; X error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); X if (error) X break; X space -= sizeof (ifr), ifrp++; X } X } X ifc->ifc_len -= space; X return (error); X} END-of-net/if.c echo x - net/if.h sed 's/^X//' >net/if.h << 'END-of-net/if.h' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)if.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Structures defining a network interface, providing a packet X * transport mechanism (ala level 0 of the PUP protocols). X * X * Each interface accepts output datagrams of a specified maximum X * length, and provides higher level routines with input datagrams X * received from its medium. X * X * Output occurs when the routine if_output is called, with three parameters: X * (*ifp->if_output)(ifp, m, dst) X * Here m is the mbuf chain to be sent and dst is the destination address. X * The output routine encapsulates the supplied datagram if necessary, X * and then transmits it on its medium. X * X * On input, each interface unwraps the data received by it, and either X * places it on the input queue of a internetwork datagram routine X * and posts the associated software interrupt, or passes the datagram to a raw X * packet input routine. X * X * Routines exist for locating interfaces by their addresses X * or for locating a interface on a certain network, as well as more general X * routing and gateway routines maintaining information used to locate X * interfaces. These routines live in the files if.c and route.c X */ X X/* X * Structure defining a queue for a network interface. X * X * (Would like to call this struct ``if'', but C isn't PL/1.) X */ Xstruct ifnet { X char *if_name; /* name, e.g. ``en'' or ``lo'' */ X short if_unit; /* sub-unit for lower level driver */ X short if_mtu; /* maximum transmission unit */ X short if_flags; /* up/down, broadcast, etc. */ X short if_timer; /* time 'til if_watchdog called */ X int if_metric; /* routing metric (external only) */ X struct ifaddr *if_addrlist; /* linked list of addresses per if */ X struct ifqueue { X struct mbuf *ifq_head; X struct mbuf *ifq_tail; X int ifq_len; X int ifq_maxlen; X int ifq_drops; X } if_snd; /* output queue */ X/* procedure handles */ X int (*if_init)(); /* init routine */ X int (*if_output)(); /* output routine */ X int (*if_ioctl)(); /* ioctl routine */ X int (*if_reset)(); /* bus reset routine */ X int (*if_watchdog)(); /* timer routine */ X/* generic interface statistics */ X int if_ipackets; /* packets received on interface */ X int if_ierrors; /* input errors on interface */ X int if_opackets; /* packets sent on interface */ X int if_oerrors; /* output errors on interface */ X int if_collisions; /* collisions on csma interfaces */ X/* end statistics */ X struct ifnet *if_next; X}; X X#define IFF_UP 0x1 /* interface is up */ X#define IFF_BROADCAST 0x2 /* broadcast address valid */ X#define IFF_DEBUG 0x4 /* turn on debugging */ X#define IFF_LOOPBACK 0x8 /* is a loopback net */ X#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ X#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ X#define IFF_RUNNING 0x40 /* resources allocated */ X#define IFF_NOARP 0x80 /* no address resolution protocol */ X/* next two not supported now, but reserved: */ X#define IFF_PROMISC 0x100 /* receive all packets */ X#define IFF_ALLMULTI 0x200 /* receive all multicast packets */ X/* flags set internally only: */ X#define IFF_CANTCHANGE (IFF_BROADCAST | IFF_POINTOPOINT | IFF_RUNNING) X X/* X * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1) X * input routines have queues of messages stored on ifqueue structures X * (defined above). Entries are added to and deleted from these structures X * by these macros, which should be called with ipl raised to splimp(). X */ X#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) X#define IF_DROP(ifq) ((ifq)->ifq_drops++) X#define IF_ENQUEUE(ifq, m) { \ X (m)->m_act = 0; \ X if ((ifq)->ifq_tail == 0) \ X (ifq)->ifq_head = m; \ X else \ X (ifq)->ifq_tail->m_act = m; \ X (ifq)->ifq_tail = m; \ X (ifq)->ifq_len++; \ X} X#define IF_PREPEND(ifq, m) { \ X (m)->m_act = (ifq)->ifq_head; \ X if ((ifq)->ifq_tail == 0) \ X (ifq)->ifq_tail = (m); \ X (ifq)->ifq_head = (m); \ X (ifq)->ifq_len++; \ X} X/* X * Packets destined for level-1 protocol input routines X * have a pointer to the receiving interface prepended to the data. X * IF_DEQUEUEIF extracts and returns this pointer when dequeueing the packet. X * IF_ADJ should be used otherwise to adjust for its presence. X */ X#define IF_ADJ(m) { \ X (m)->m_off += sizeof(struct ifnet *); \ X (m)->m_len -= sizeof(struct ifnet *); \ X if ((m)->m_len == 0) { \ X struct mbuf *n; \ X MFREE((m), n); \ X (m) = n; \ X } \ X} X#define IF_DEQUEUEIF(ifq, m, ifp) { \ X (m) = (ifq)->ifq_head; \ X if (m) { \ X if (((ifq)->ifq_head = (m)->m_act) == 0) \ X (ifq)->ifq_tail = 0; \ X (m)->m_act = 0; \ X (ifq)->ifq_len--; \ X (ifp) = *(mtod((m), struct ifnet **)); \ X IF_ADJ(m); \ X } \ X} X#define IF_DEQUEUE(ifq, m) { \ X (m) = (ifq)->ifq_head; \ X if (m) { \ X if (((ifq)->ifq_head = (m)->m_act) == 0) \ X (ifq)->ifq_tail = 0; \ X (m)->m_act = 0; \ X (ifq)->ifq_len--; \ X } \ X} X X#define IFQ_MAXLEN 50 X#define IFNET_SLOWHZ 1 /* granularity is 1 second */ X X/* X * The ifaddr structure contains information about one address X * of an interface. They are maintained by the different address families, X * are allocated and attached when an address is set, and are linked X * together so all addresses for an interface can be located. X */ Xstruct ifaddr { X struct sockaddr ifa_addr; /* address of interface */ X union { X struct sockaddr ifu_broadaddr; X struct sockaddr ifu_dstaddr; X } ifa_ifu; X#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ X#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of p-to-p link */ X struct ifnet *ifa_ifp; /* back-pointer to interface */ X struct ifaddr *ifa_next; /* next address for interface */ X}; X X/* X * Interface request structure used for socket X * ioctl's. All interface ioctl's must have parameter X * definitions which begin with ifr_name. The X * remainder may be interface specific. X */ Xstruct ifreq { X#define IFNAMSIZ 16 X char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ X union { X struct sockaddr ifru_addr; X struct sockaddr ifru_dstaddr; X struct sockaddr ifru_broadaddr; X short ifru_flags; X int ifru_metric; X caddr_t ifru_data; X } ifr_ifru; X#define ifr_addr ifr_ifru.ifru_addr /* address */ X#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ X#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ X#define ifr_flags ifr_ifru.ifru_flags /* flags */ X#define ifr_metric ifr_ifru.ifru_metric /* metric */ X#define ifr_data ifr_ifru.ifru_data /* for use by interface */ X}; X X/* X * Structure used in SIOCGIFCONF request. X * Used to retrieve interface configuration X * for machine (useful for programs which X * must know all networks accessible). X */ Xstruct ifconf { X int ifc_len; /* size of associated buffer */ X union { X caddr_t ifcu_buf; X struct ifreq *ifcu_req; X } ifc_ifcu; X#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ X#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ X}; X X#ifdef KERNEL X#include "../net/if_arp.h" Xstruct ifqueue rawintrq; /* raw packet input queue */ Xstruct ifnet *ifnet; Xstruct ifaddr *ifa_ifwithaddr(), *ifa_ifwithnet(); Xstruct ifaddr *ifa_ifwithdstaddr(); X#else KERNEL X#include <net/if_arp.h> X#endif KERNEL END-of-net/if.h echo x - net/if_arp.h sed 's/^X//' >net/if_arp.h << 'END-of-net/if_arp.h' X/* X * Copyright (c) 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)if_arp.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Address Resolution Protocol. X * X * See RFC 826 for protocol description. ARP packets are variable X * in size; the arphdr structure defines the fixed-length portion. X * Protocol type values are the same as those for 10 Mb/s Ethernet. X * It is followed by the variable-sized fields ar_sha, arp_spa, X * arp_tha and arp_tpa in that order, according to the lengths X * specified. Field names used correspond to RFC 826. X */ Xstruct arphdr { X u_short ar_hrd; /* format of hardware address */ X#define ARPHRD_ETHER 1 /* ethernet hardware address */ X u_short ar_pro; /* format of protocol address */ X u_char ar_hln; /* length of hardware address */ X u_char ar_pln; /* length of protocol address */ X u_short ar_op; /* one of: */ X#define ARPOP_REQUEST 1 /* request to resolve address */ X#define ARPOP_REPLY 2 /* response to previous request */ X/* X * The remaining fields are variable in size, X * according to the sizes above. X */ X/* u_char ar_sha[]; /* sender hardware address */ X/* u_char ar_spa[]; /* sender protocol address */ X/* u_char ar_tha[]; /* target hardware address */ X/* u_char ar_tpa[]; /* target protocol address */ X}; X X/* X * ARP ioctl request X */ Xstruct arpreq { X struct sockaddr arp_pa; /* protocol address */ X struct sockaddr arp_ha; /* hardware address */ X int arp_flags; /* flags */ X}; X/* arp_flags and at_flags field values */ X#define ATF_INUSE 0x01 /* entry in use */ X#define ATF_COM 0x02 /* completed entry (enaddr valid) */ X#define ATF_PERM 0x04 /* permanent entry */ X#define ATF_PUBL 0x08 /* publish entry (respond for other host) */ X#define ATF_USETRAILERS 0x10 /* has requested trailers */ END-of-net/if_arp.h echo x - net/if_loop.c sed 's/^X//' >net/if_loop.c << 'END-of-net/if_loop.c' X/* X * Copyright (c) 1982, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)if_loop.c 7.3 (Berkeley) 12/30/87 X */ X X/* X * Loopback interface driver for protocol testing and timing. X */ X X#include "param.h" X#include "systm.h" X#include "mbuf.h" X#include "socket.h" X#include "errno.h" X#include "ioctl.h" X X#include "../net/if.h" X#include "../net/netisr.h" X#include "../net/route.h" X X#include "../machine/mtpr.h" X X#ifdef INET X#include "../netinet/in.h" X#include "../netinet/in_systm.h" X#include "../netinet/in_var.h" X#include "../netinet/ip.h" X#endif X X#ifdef NS X#include "../netns/ns.h" X#include "../netns/ns_if.h" X#endif X X#define LOMTU (1024+512) X Xstruct ifnet loif; Xint looutput(), loioctl(); X Xloattach() X{ X register struct ifnet *ifp = &loif; X X ifp->if_name = "lo"; X ifp->if_mtu = LOMTU; X ifp->if_flags = IFF_LOOPBACK; X ifp->if_ioctl = loioctl; X ifp->if_output = looutput; X if_attach(ifp); X} X Xlooutput(ifp, m0, dst) X struct ifnet *ifp; X register struct mbuf *m0; X struct sockaddr *dst; X{ X int s; X register struct ifqueue *ifq; X struct mbuf *m; X X /* X * Place interface pointer before the data X * for the receiving protocol. X */ X if (m0->m_off <= MMAXOFF && X m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { X m0->m_off -= sizeof(struct ifnet *); X m0->m_len += sizeof(struct ifnet *); X } else { X MGET(m, M_DONTWAIT, MT_HEADER); X if (m == (struct mbuf *)0) X return (ENOBUFS); X m->m_off = MMINOFF; X m->m_len = sizeof(struct ifnet *); X m->m_next = m0; X m0 = m; X } X *(mtod(m0, struct ifnet **)) = ifp; X s = splimp(); X ifp->if_opackets++; X switch (dst->sa_family) { X X#ifdef INET X case AF_INET: X ifq = &ipintrq; X if (IF_QFULL(ifq)) { X IF_DROP(ifq); X m_freem(m0); X splx(s); X return (ENOBUFS); X } X IF_ENQUEUE(ifq, m0); X schednetisr(NETISR_IP); X break; X#endif X#ifdef NS X case AF_NS: X ifq = &nsintrq; X if (IF_QFULL(ifq)) { X IF_DROP(ifq); X m_freem(m0); X splx(s); X return (ENOBUFS); X } X IF_ENQUEUE(ifq, m0); X schednetisr(NETISR_NS); X break; X#endif X default: X splx(s); X printf("lo%d: can't handle af%d\n", ifp->if_unit, X dst->sa_family); X m_freem(m0); X return (EAFNOSUPPORT); X } X ifp->if_ipackets++; X splx(s); X return (0); X} X X/* X * Process an ioctl request. X */ X/* ARGSUSED */ Xloioctl(ifp, cmd, data) X register struct ifnet *ifp; X int cmd; X caddr_t data; X{ X int error = 0; X X switch (cmd) { X X case SIOCSIFADDR: X ifp->if_flags |= IFF_UP; X /* X * Everything else is done at a higher level. X */ X break; X X default: X error = EINVAL; X } X return (error); X} END-of-net/if_loop.c echo x - net/netisr.h sed 's/^X//' >net/netisr.h << 'END-of-net/netisr.h' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)netisr.h 7.3 (Berkeley) 12/30/87 X */ X X/* X * The networking code runs off software interrupts. X * X * You can switch into the network by doing splnet() and return by splx(). X * The software interrupt level for the network is higher than the software X * level for the clock (so you can enter the network in routines called X * at timeout time). X */ X#if defined(vax) || defined(tahoe) X#define setsoftnet() mtpr(SIRR, 12) X#endif X X/* X * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status X * word which is used to de-multiplex a single software X * interrupt used for scheduling the network code to calls X * on the lowest level routine of each protocol. X */ X#define NETISR_RAW 0 /* same as AF_UNSPEC */ X#define NETISR_IP 2 /* same as AF_INET */ X#define NETISR_IMP 3 /* same as AF_IMPLINK */ X#define NETISR_NS 6 /* same as AF_NS */ X X#define schednetisr(anisr) { netisr |= 1<<(anisr); setsoftnet(); } X X#ifndef LOCORE X#ifdef KERNEL Xint netisr; /* scheduling bits for network */ X#endif X#endif END-of-net/netisr.h echo x - net/raw_cb.c sed 's/^X//' >net/raw_cb.c << 'END-of-net/raw_cb.c' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)raw_cb.c 7.4 (Berkeley) 12/30/87 X */ X X#include "param.h" X#include "systm.h" X#include "mbuf.h" X#include "socket.h" X#include "socketvar.h" X#include "domain.h" X#include "protosw.h" X#include "errno.h" X X#include "if.h" X#include "route.h" X#include "raw_cb.h" X#include "../netinet/in.h" X X#include "../machine/mtpr.h" X X/* X * Routines to manage the raw protocol control blocks. X * X * TODO: X * hash lookups by protocol family/protocol + address family X * take care of unique address problems per AF? X * redo address binding to allow wildcards X */ X X/* X * Allocate a control block and a nominal amount X * of buffer space for the socket. X */ Xraw_attach(so, proto) X register struct socket *so; X int proto; X{ X struct mbuf *m; X register struct rawcb *rp; X X m = m_getclr(M_DONTWAIT, MT_PCB); X if (m == 0) X return (ENOBUFS); X if (sbreserve(&so->so_snd, RAWSNDQ) == 0) X goto bad; X if (sbreserve(&so->so_rcv, RAWRCVQ) == 0) X goto bad2; X rp = mtod(m, struct rawcb *); X rp->rcb_socket = so; X so->so_pcb = (caddr_t)rp; X rp->rcb_pcb = 0; X rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family; X rp->rcb_proto.sp_protocol = proto; X insque(rp, &rawcb); X return (0); Xbad2: X sbrelease(&so->so_snd); Xbad: X (void) m_free(m); X return (ENOBUFS); X} X X/* X * Detach the raw connection block and discard X * socket resources. X */ Xraw_detach(rp) X register struct rawcb *rp; X{ X struct socket *so = rp->rcb_socket; X X if (rp->rcb_route.ro_rt) X rtfree(rp->rcb_route.ro_rt); X so->so_pcb = 0; X sofree(so); X remque(rp); X if (rp->rcb_options) X m_freem(rp->rcb_options); X m_freem(dtom(rp)); X} X X/* X * Disconnect and possibly release resources. X */ Xraw_disconnect(rp) X struct rawcb *rp; X{ X X rp->rcb_flags &= ~RAW_FADDR; X if (rp->rcb_socket->so_state & SS_NOFDREF) X raw_detach(rp); X} X Xraw_bind(so, nam) X register struct socket *so; X struct mbuf *nam; X{ X struct sockaddr *addr = mtod(nam, struct sockaddr *); X register struct rawcb *rp; X X if (ifnet == 0) X return (EADDRNOTAVAIL); X/* BEGIN DUBIOUS */ X /* X * Should we verify address not already in use? X * Some say yes, others no. X */ X switch (addr->sa_family) { X X#ifdef INET X case AF_IMPLINK: X case AF_INET: { X if (((struct sockaddr_in *)addr)->sin_addr.s_addr && X ifa_ifwithaddr(addr) == 0) X return (EADDRNOTAVAIL); X break; X } X#endif X X default: X return (EAFNOSUPPORT); X } X/* END DUBIOUS */ X rp = sotorawcb(so); X bcopy((caddr_t)addr, (caddr_t)&rp->rcb_laddr, sizeof (*addr)); X rp->rcb_flags |= RAW_LADDR; X return (0); X} X X/* X * Associate a peer's address with a X * raw connection block. X */ Xraw_connaddr(rp, nam) X struct rawcb *rp; X struct mbuf *nam; X{ X struct sockaddr *addr = mtod(nam, struct sockaddr *); X X bcopy((caddr_t)addr, (caddr_t)&rp->rcb_faddr, sizeof(*addr)); X rp->rcb_flags |= RAW_FADDR; X} END-of-net/raw_cb.c echo x - net/raw_cb.h sed 's/^X//' >net/raw_cb.h << 'END-of-net/raw_cb.h' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)raw_cb.h 7.2 (Berkeley) 12/30/87 X */ X X/* X * Raw protocol interface control block. Used X * to tie a socket to the generic raw interface. X */ Xstruct rawcb { X struct rawcb *rcb_next; /* doubly linked list */ X struct rawcb *rcb_prev; X struct socket *rcb_socket; /* back pointer to socket */ X struct sockaddr rcb_faddr; /* destination address */ X struct sockaddr rcb_laddr; /* socket's address */ X struct sockproto rcb_proto; /* protocol family, protocol */ X caddr_t rcb_pcb; /* protocol specific stuff */ X struct mbuf *rcb_options; /* protocol specific options */ X struct route rcb_route; /* routing information */ X short rcb_flags; X}; X X/* X * Since we can't interpret canonical addresses, X * we mark an address present in the flags field. X */ X#define RAW_LADDR 01 X#define RAW_FADDR 02 X#define RAW_DONTROUTE 04 /* no routing, default */ X X#define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) X X/* X * Nominal space allocated to a raw socket. X */ X#define RAWSNDQ 2048 X#define RAWRCVQ 2048 X X/* X * Format of raw interface header prepended by X * raw_input after call from protocol specific X * input routine. X */ Xstruct raw_header { X struct sockproto raw_proto; /* format of packet */ X struct sockaddr raw_dst; /* dst address for rawintr */ X struct sockaddr raw_src; /* src address for sbappendaddr */ X}; X X#ifdef KERNEL Xstruct rawcb rawcb; /* head of list */ X#endif END-of-net/raw_cb.h echo x - net/raw_usrreq.c sed 's/^X//' >net/raw_usrreq.c << 'END-of-net/raw_usrreq.c' X/* X * Copyright (c) 1980, 1986 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)raw_usrreq.c 7.3 (Berkeley) 12/30/87 X */ X X#include "param.h" X#include "mbuf.h" X#include "domain.h" X#include "protosw.h" X#include "socket.h" X#include "socketvar.h" X#include "errno.h" X X#include "if.h" X#include "route.h" X#include "netisr.h" X#include "raw_cb.h" X X#include "../machine/mtpr.h" X X/* X * Initialize raw connection block q. X */ Xraw_init() X{ X X rawcb.rcb_next = rawcb.rcb_prev = &rawcb; X rawintrq.ifq_maxlen = IFQ_MAXLEN; X} X X/* X * Raw protocol interface. X */ Xraw_input(m0, proto, src, dst) X struct mbuf *m0; X struct sockproto *proto; X struct sockaddr *src, *dst; X{ X register struct mbuf *m; X struct raw_header *rh; X int s; X X /* X * Rip off an mbuf for a generic header. X */ X m = m_get(M_DONTWAIT, MT_HEADER); X if (m == 0) { X m_freem(m0); X return; X } X m->m_next = m0; X m->m_len = sizeof(struct raw_header); X rh = mtod(m, struct raw_header *); X rh->raw_dst = *dst; X rh->raw_src = *src; X rh->raw_proto = *proto; X X /* X * Header now contains enough info to decide X * which socket to place packet in (if any). X * Queue it up for the raw protocol process X * running at software interrupt level. X */ X s = splimp(); X if (IF_QFULL(&rawintrq)) X m_freem(m); X else X IF_ENQUEUE(&rawintrq, m); X splx(s); X schednetisr(NETISR_RAW); X} X X/* X * Raw protocol input routine. Process packets entered X * into the queue at interrupt time. Find the socket X * associated with the packet(s) and move them over. If X * nothing exists for this packet, drop it. X */ Xrawintr() X{ X int s; X struct mbuf *m; X register struct rawcb *rp; X register struct raw_header *rh; X struct socket *last; X Xnext: X s = splimp(); X IF_DEQUEUE(&rawintrq, m); X splx(s); X if (m == 0) X return; X rh = mtod(m, struct raw_header *); X last = 0; X for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { X if (rp->rcb_proto.sp_family != rh->raw_proto.sp_family) X continue; X if (rp->rcb_proto.sp_protocol && X rp->rcb_proto.sp_protocol != rh->raw_proto.sp_protocol) X continue; X /* X * We assume the lower level routines have X * placed the address in a canonical format X * suitable for a structure comparison. X */ X#define equal(a1, a2) \ X (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) X if ((rp->rcb_flags & RAW_LADDR) && X !equal(rp->rcb_laddr, rh->raw_dst)) X continue; X if ((rp->rcb_flags & RAW_FADDR) && X !equal(rp->rcb_faddr, rh->raw_src)) X continue; X if (last) { X struct mbuf *n; X if (n = m_copy(m->m_next, 0, (int)M_COPYALL)) { X if (sbappendaddr(&last->so_rcv, &rh->raw_src, X n, (struct mbuf *)0) == 0) X /* should notify about lost packet */ X m_freem(n); X else X sorwakeup(last); X } X } X last = rp->rcb_socket; X } X if (last) { X if (sbappendaddr(&last->so_rcv, &rh->raw_src, X m->m_next, (struct mbuf *)0) == 0) X m_freem(m->m_next); X else X sorwakeup(last); X (void) m_free(m); /* header */ X } else X m_freem(m); X goto next; X} X X/*ARGSUSED*/ Xraw_ctlinput(cmd, arg) X int cmd; X struct sockaddr *arg; X{ X X if (cmd < 0 || cmd > PRC_NCMDS) X return; X /* INCOMPLETE */ X} X X/*ARGSUSED*/ Xraw_usrreq(so, req, m, nam, rights) X struct socket *so; X int req; X struct mbuf *m, *nam, *rights; X{ X register struct rawcb *rp = sotorawcb(so); X register int error = 0; X X if (req == PRU_CONTROL) X return (EOPNOTSUPP); X if (rights && rights->m_len) { X error = EOPNOTSUPP; X goto release; X } X if (rp == 0 && req != PRU_ATTACH) { X error = EINVAL; X goto release; X } X switch (req) { X X /* X * Allocate a raw control block and fill in the X * necessary info to allow packets to be routed to X * the appropriate raw interface routine. X */ X case PRU_ATTACH: X if ((so->so_state & SS_PRIV) == 0) { X error = EACCES; X break; X } X if (rp) { X error = EINVAL; X break; X } X error = raw_attach(so, (int)nam); X break; X X /* X * Destroy state just before socket deallocation. X * Flush data or not depending on the options. X */ X case PRU_DETACH: X if (rp == 0) { X error = ENOTCONN; X break; X } X raw_detach(rp); X break; X X /* X * If a socket isn't bound to a single address, X * the raw input routine will hand it anything X * within that protocol family (assuming there's X * nothing else around it should go to). X */ X case PRU_CONNECT: X if (rp->rcb_flags & RAW_FADDR) { X error = EISCONN; X break; X } X raw_connaddr(rp, nam); X soisconnected(so); X break; X X case PRU_CONNECT2: X error = EOPNOTSUPP; X goto release; X X case PRU_BIND: X if (rp->rcb_flags & RAW_LADDR) { X error = EINVAL; /* XXX */ X break; X } X error = raw_bind(so, nam); X break; X X case PRU_DISCONNECT: X if ((rp->rcb_flags & RAW_FADDR) == 0) { X error = ENOTCONN; X break; X } X raw_disconnect(rp); X soisdisconnected(so); X break; X X /* X * Mark the connection as being incapable of further input. X */ X case PRU_SHUTDOWN: X socantsendmore(so); X break; X X /* X * Ship a packet out. The appropriate raw output X * routine handles any massaging necessary. X */ X case PRU_SEND: X if (nam) { X if (rp->rcb_flags & RAW_FADDR) { X error = EISCONN; X break; X } X raw_connaddr(rp, nam); X } else if ((rp->rcb_flags & RAW_FADDR) == 0) { X error = ENOTCONN; X break; X } X error = (*so->so_proto->pr_output)(m, so); X m = NULL; X if (nam) X rp->rcb_flags &= ~RAW_FADDR; X break; X X case PRU_ABORT: X raw_disconnect(rp); X sofree(so); X soisdisconnected(so); X break; X X case PRU_SENSE: X /* X * stat: don't bother with a blocksize. X */ X return (0); X X /* X * Not supported. X */ X case PRU_RCVOOB: X case PRU_RCVD: X return(EOPNOTSUPP); X X case PRU_LISTEN: X case PRU_ACCEPT: X case PRU_SENDOOB: X error = EOPNOTSUPP; X break; X X case PRU_SOCKADDR: X bcopy((caddr_t)&rp->rcb_laddr, mtod(nam, caddr_t), X sizeof (struct sockaddr)); X nam->m_len = sizeof (struct sockaddr); X break; X X case PRU_PEERADDR: X bcopy((caddr_t)&rp->rcb_faddr, mtod(nam, caddr_t), X sizeof (struct sockaddr)); X nam->m_len = sizeof (struct sockaddr); X break; X X default: X panic("raw_usrreq"); X } Xrelease: X if (m != NULL) X m_freem(m); X return (error); X} END-of-net/raw_usrreq.c exit