Patch #: 94 Type: operational change Priority: none Modification: add Kernel AppleTalk capability Submitted: David Hornsby Archived: munnari.OZ.AU mac/cap.patches/cap60.patch094 Application: 'cd cap60; patch -p < cap60.patches/cap60.patch094' Summary: Add interface to University of Michigan netatalk-1.2. Summary: Alternate LAP delivery via AF_APPLETALK sockets in kernel. File: cap60/Makefile File: cap60/gen.makes File: cap60/Configure File: cap60/lib/cap/atalkdbm.c File: cap60/lib/cap/abkas.c File: cap60/lib/cap/abversion.c File: cap60/netat/appletalk.h File: cap60/etc/atis.c File: cap60/support/capd/Makefile.m4 File: cap60/support/capd/capd.c File: cap60/support/capd/capd.kas.c File: cap60/support/capd/README WARNING: netat/appletalk.h changed, requires 'make include' WARNING: Experimental Release: tested only under SunOS 4.1.1 *** Makefile.orig Sun Sep 22 15:56:04 1991 --- Makefile Sat Mar 7 21:06:45 1992 *************** *** 25,30 **** --- 25,31 ---- -(cd contrib; make) -(cd applications; make) -(cd support/uab; make) + -(cd support/capd; make) -(cd support/ethertalk; make) touch programs *************** *** 34,39 **** --- 35,41 ---- -(cd contrib; make install) -(cd applications; make install) -(cd support/uab; make install) + -(cd support/capd; make install) -(cd support/ethertalk; make install) cap.shar: listtodist *************** *** 69,74 **** --- 71,77 ---- -(cd extras; make clean) -(cd applications; make clean) -(cd support/uab; make clean) + -(cd support/capd; make clean) -(cd support/ethertalk; make clean) spotless: *************** *** 87,90 **** --- 90,94 ---- -(cd extras; make spotless) -(cd applications; make spotless) -(cd support/uab; make spotless) + -(cd support/capd; make spotless) -(cd support/ethertalk; make spotless) *** gen.makes.orig Sat Jul 27 21:06:45 1991 --- gen.makes Sat Mar 7 21:06:50 1992 *************** *** 3,9 **** # -f specifies a different setup file # -o specifies a different output file appdirs="applications applications/aufs applications/papif applications/lwsrv" ! supportdirs="support/uab support/ethertalk" libdirs="lib lib/afp lib/afpc lib/cap" dirs="netat contrib samples extras etc ${libdirs} ${appdirs} ${supportdirs}" m4setup=`pwd`/m4.setup --- 3,9 ---- # -f specifies a different setup file # -o specifies a different output file appdirs="applications applications/aufs applications/papif applications/lwsrv" ! supportdirs="support/uab support/ethertalk support/capd" libdirs="lib lib/afp lib/afpc lib/cap" dirs="netat contrib samples extras etc ${libdirs} ${appdirs} ${supportdirs}" m4setup=`pwd`/m4.setup *** Configure.orig Sat Feb 22 22:15:23 1992 --- Configure Sat Mar 7 22:23:02 1992 *************** *** 1,7 **** #!/bin/sh ! # $Author: djh $ $Date: 1992/02/22 11:15:10 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.36 1992/02/22 11:15:10 djh Rel djh $ ! # $Revision: 2.36 $ # CAP configuration shell script. This ain't perfect, but it's a start. # Execute with /bin/sh Configure if your system won't run it (ksh is okay too) # --- 1,7 ---- #!/bin/sh ! # $Author: djh $ $Date: 1992/03/07 12:22:53 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.38 1992/03/07 12:22:53 djh Rel djh $ ! # $Revision: 2.38 $ # CAP configuration shell script. This ain't perfect, but it's a start. # Execute with /bin/sh Configure if your system won't run it (ksh is okay too) # *************** *** 283,288 **** --- 283,290 ---- uabpobjs="define([uabpobjs],[])" etherprogs="define([etherprogs],[])" etherpobjs="define([etherpobjs],[])" + capdprogs="define([capdprogs],[])" + capdpobjs="define([capdpobjs],[])" lapobj="define([lapobj],[abkip.o abddp.o abnbp.o atalkdbm.o])" usingphase2="# define([usephase2],1)" usingatis="# define([useatis],1)" *************** *** 291,301 **** --- 293,308 ---- usephase2=0 uabsupport=0 ethersupport=0 + kernelsupport=0 case ${os} in "sunos"|"ultrix40"|"ultrix20"|"ultrix12") uabsupport=1 ethersupport=1 + kernelsupport=1 ;; + "aix") + kernelsupport=1 + ;; "pyr") # later, someone should try this. # uabsupport=1 *************** *** 412,418 **** fi case ${ans} in "yes"|"y") - result=0 usephase2=1 echo "OK, setting things up for Native EtherTalk, Phase 2" ;; --- 419,424 ---- *************** *** 432,438 **** fi case ${ans} in "yes"|"y") - result=0 usephase2=1 ;; *) --- 438,443 ---- *************** *** 444,453 **** ans="no" fi case ${ans} in ! "yes"|"y") result=1;; ! *) result=0;; esac ! if [ $result -eq 0 ]; then echo $newl "OK, using the NIT ethernet interface" etherpobjs="define([etherpobjs],[snitp.o])" else --- 449,458 ---- ans="no" fi case ${ans} in ! "yes"|"y") aresult=1;; ! *) aresult=0;; esac ! if [ $aresult -eq 0 ]; then echo $newl "OK, using the NIT ethernet interface" etherpobjs="define([etherpobjs],[snitp.o])" else *************** *** 464,469 **** --- 469,504 ---- fi fi fi + echo + if [ $result -eq 0 ]; then + if [ ${kernelsupport} -eq 1 ]; then + result=0 + while : + do + echo $newl "Do you wish to use Kernel AppleTalk (default no) ? " + read ans + if [ -z "${ans}" ]; then + ans="no" + fi + case ${ans} in + "yes"|"y") result=1; break;; + "no" |"n") result=0; break;; + *) echo "you must answer yes or no or carriage return for no." ;; + esac + done + if [ $result -eq 0 ]; then + echo "Not using Kernel AppleTalk." + capdprogs="define([capdprogs],[])" + capdpobjs="define([capdpobjs],[])" + lapobj="define([lapobj],[abkip.o abddp.o abnbp.o atalkdbm.o])" + else + echo "OK, setting things up for Kernel AppleTalk." + capdprogs="define([capdprogs],[capd])" + capdpobjs="define([capdpobjs],[capd.kas.o])" + lapobj="define([lapobj],[abkas.o abddp.o abnbp.o atalkdbm.o])" + fi + fi + fi if [ $useauxappletalk -ne 0 ]; then lapobj="define([lapobj],[abauxddp.o abauxnbp.o])" fi *************** *** 932,937 **** --- 967,976 ---- echo "# This sets up Native EtherTalk support" echo "${etherprogs}" echo "${etherpobjs}" + echo + echo "# This sets up capd" + echo "${capdprogs}" + echo "${capdpobjs}" echo echo "# And this determines if Phase 2 packets are used" echo "${usingphase2}" *** lib/cap/atalkdbm.c.orig Mon Feb 17 13:14:17 1992 --- lib/cap/atalkdbm.c Sat Mar 7 21:07:39 1992 *************** *** 1,7 **** /* ! * $Date: 1992/02/17 02:13:58 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/atalkdbm.c,v 2.8 1992/02/17 02:13:58 djh Rel djh $ ! * $Revision: 2.8 $ * * mods for async appletalk support, /etc/etalk.local for EtherTalk and * changes for quoted zone names: djh@munnari.OZ.AU, 27/11/90 --- 1,7 ---- /* ! * $Date: 1992/03/07 11:07:25 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/atalkdbm.c,v 2.9 1992/03/07 11:07:25 djh Rel djh $ ! * $Revision: 2.9 $ * * mods for async appletalk support, /etc/etalk.local for EtherTalk and * changes for quoted zone names: djh@munnari.OZ.AU, 27/11/90 *************** *** 366,375 **** fprintf(fp, "# Generated by UAB\n#\n"); if (lap_proto == LAP_ETALK) #ifdef PHASE2 ! fprintf(fp, "# Generated by native EtherTalk (Phase 2)\n#\n"); #else PHASE2 ! fprintf(fp, "# Generated by native EtherTalk (Phase 1)\n#\n"); #endif PHASE2 if (*interface != '\0') fprintf(fp, "%-12s\t\"%s\"\n", ETH_INTERFACE, interface); #ifdef PHASE2 --- 366,377 ---- fprintf(fp, "# Generated by UAB\n#\n"); if (lap_proto == LAP_ETALK) #ifdef PHASE2 ! fprintf(fp, "# Generated by Native EtherTalk (Phase 2)\n#\n"); #else PHASE2 ! fprintf(fp, "# Generated by Native EtherTalk (Phase 1)\n#\n"); #endif PHASE2 + if (lap_proto == LAP_KERNEL) + fprintf(fp, "# Generated by Kernel AppleTalk\n#\n"); if (*interface != '\0') fprintf(fp, "%-12s\t\"%s\"\n", ETH_INTERFACE, interface); #ifdef PHASE2 *** lib/cap/abkas.c.orig Sat Mar 7 20:58:28 1992 --- lib/cap/abkas.c Sat Mar 7 21:04:58 1992 *************** *** 0 **** --- 1,775 ---- + /* + * $Author: djh $ $Date: 1992/03/07 11:04:41 $ + * $Header: /mac/src/cap60/lib/cap/RCS/abkas.c,v 2.1 1992/03/07 11:04:41 djh Rel djh $ + * $Revision: 2.1 $ + */ + + /* + * abkas.c - use UNIX Kernel AppleTalk Support via AF_APPLETALK sockets + * + * AppleTalk package for UNIX (4.2 BSD). + * + * Copyright (c) 1986, 1987, 1988 by The Trustees of Columbia University + * in the City of New York. + * + * Copyright (c) 1992 The University of Melbourne. + * + * Edit History: + * + * February 1992 djh Created + * + */ + + /* + * The following list of exported routines is provided so you'll know what + * have to be done to do another interface type (ethertalk, etc) + * + * EXPORTED ROUTINES: + * + * OSErr GetNodeAddress(int *mynode, int *mynet) + * Return node addresses + * OSErr GetBridgeAddress(AddrBlock *addr) + * Return bridge addresses + * OSErr SetBridgeAddress(AddrBlock *addr) + * Set bridge addresses + * OSErr SetNetRange(u_short range_start, u_short range_end) + * Set Network Range (Phase 2) + * int abInit(boolean dispay_message) + * Initialize AppleTalk + * int abOpen(int *returnsocket, int wantsocket, struct iovec iov[], iovlen) + * Open a DDP socket + * int abClose(int socket) + * Close a DDP socket + * void abnet_cacheit(word srcNet, byte srcNode) + * Call in DDP protocol layer to tell the lower layer that + * the last packet that came in was from srcNet, srcNode + * int routeddp(struct iovec *iov, int iovlen) + * This is the DDP incursion. With a full AppleTalk implementation, + * this would be part of DDP (abddp2). This routes the DDP packet: + * normally would decide where to send and then send via lap, with KIP + * decides where and sends via UDP. + * + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include /* to cover difference between bsd systems */ + #include + + #define ATADDR_ANYNET (u_short)0x0000 + #define ATADDR_LATENET (u_short)0xffff + #define ATADDR_ANYNODE (u_char)0x00 + #define ATADDR_ANYPORT (u_char)0x00 + #define ATADDR_BCAST (u_char)0xff + + #ifdef s_net + #undef s_net + #endif s_net + + /* AppleTalk Address */ + + struct at_addr { + u_short s_net; + u_char s_node; + }; + + /* Socket Address for AppleTalk */ + + struct sockaddr_at { + short sat_family; + u_char sat_port; + struct at_addr sat_addr; + char sat_zero[8]; + }; + + /* imported network information */ + + extern word this_net, bridge_net, nis_net, async_net; + extern byte this_node, bridge_node, nis_node; + extern char this_zone[34], async_zone[34], interface[50]; + + extern struct in_addr bridge_addr; + + #ifdef PHASE2 + extern word net_range_start, net_range_end; + #endif PHASE2 + + short lap_proto = LAP_KERNEL; /* kernel appletalk support */ + + /* + * Configuration defines + * + * NORECVMSG - no recvmsg() + * NOSENDMSG - no sendmsg() + * MEEDMSGHDR - no msghdr in sockets.h - define our own + * + */ + + #ifdef NORECVMSG + # ifndef NEEDNETBUF + # define NEEDNETBUF + # endif NEEDNETBUF + #endif NORECVMSG + #ifdef NOSENDMSG + # ifndef NEEDNETBUF + # define NEEDNETBUF + # endif NEEDNETBUF + #endif NOSENDMSG + + import int ddp_protocol(); /* DDP protocol handler */ + + private int ddp_get(); /* kernel packet listener */ + private int kip_get(); /* loopback packet listener */ + + private struct sockaddr_at addr; /* local appletalk socket addr */ + private struct sockaddr_at raddr;/* input appletalk socket addr */ + private struct sockaddr_in from; /* loopback receive address */ + private struct sockaddr_in send; /* send packet to loopback */ + + private int skt2fd[ddpMaxSkt+1]; /* translate socket to file descriptor */ + private int skt2kip[ddpMaxSkt+1];/* loopback socket to file descriptor */ + private int ddpskt2udpport[ddpMaxWKS+1]; /* ddp "wks" skt to udp port */ + + private LAP laph; + + export DBUG dbug; + + /* + * initialize + * + */ + + export + abInit(disp) + int disp; + { + int i; + static int here_before = 0; + + for (i = 0; i < ddpMaxSkt+1; i++) { + skt2fd[i] = -1; /* mark all these as unused */ + skt2kip[i] = -1; /* mark all these as unused */ + } + + for (i = 0; i < ddpMaxWKS+1; i++) + ddpskt2udpport[i] = -1; /* mark as unused */ + + if (!here_before) { + openetalkdb(NULL); /* set up variables */ + here_before = 1; + } + + init_fdlistening(); + + if (disp) { + printf("abInit: [ddp: %3d.%02d, %d]", + ntohs(this_net) >> 8, ntohs(this_net) & 0xff, this_node); + if (this_net != nis_net || this_node != nis_node) + printf(", [NBP (atis) Server: %3d.%02d, %d]", + ntohs(nis_net) >> 8, ntohs(nis_net) & 0xff, nis_node); + if (bridge_node) + printf(", [GW: %3d.%02d, %d]", + ntohs(this_net) >> 8, ntohs(this_net) & 0xff, bridge_node); + printf(" starting\n"); + } + + DDPInit(); + return(0); + } + + /* + * int abOpen(int *skt,rskt, iov, iovlen) + * + * abOpen opens the ddp socket in "skt" or if "skt" is zero allocates + * and opens a new socket. Upon return "skt" contains the socket number + * and the returned value is >=0 if no error, < 0 if error. + * + * iov should be an array of type "struct iov" of length at least + * IOV_LAP_SIZE+1. Levels after IOV_LAP_LVL are assume to filled. + * + */ + + int abOpen(skt,rskt, iov, iovlen) + int *skt; + int rskt; + struct iovec *iov; + int iovlen; + { + int len, fd, err; + + if (iov == NULL || iovlen < IOV_LAP_SIZE+1 || iovlen > IOV_READ_MAX) + return(-1); + + if ((fd = socket(AF_APPLETALK, SOCK_DGRAM, 0)) < 0) { + perror("socket()"); + return(fd); + } + + bzero(&addr, sizeof(struct sockaddr_at)); + addr.sat_family = AF_APPLETALK; + addr.sat_addr.s_net = ATADDR_LATENET; + addr.sat_addr.s_node = ATADDR_ANYNODE; + addr.sat_port = (rskt == 0) ? ATADDR_ANYPORT : rskt; + + if ((err = bind(fd, &addr, sizeof(struct sockaddr_at))) < 0) { + perror("bind()"); + close(fd); + return(err); + } + + len = sizeof(struct sockaddr_at); + if ((err = getsockname(fd, &addr, &len)) < 0) { + perror("getsockname()"); + close(fd); + return(err); + } + + *skt = addr.sat_port; + + iov[IOV_LAP_LVL].iov_base = (caddr_t)&laph; /* remember this */ + iov[IOV_LAP_LVL].iov_len = lapSize; /* and this */ + + fdlistener(fd, ddp_get, iov, iovlen); /* remember for later */ + + skt2fd[*skt] = fd; /* remember file descriptor for socket */ + + /* open KIP loopback socket */ + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket()"); + fdunlisten(skt2fd[*skt]); + close(skt2fd[*skt]); + return(fd); + } + + send.sin_family = AF_INET; + send.sin_addr.s_addr = INADDR_ANY; + if ((send.sin_port = ddp2ipskt(*skt)) == 0) { + fdunlisten(skt2fd[*skt]); + close(skt2fd[*skt]); + close(fd); + return(ddpSktErr); + } + + if ((err = bind(fd, (struct sockaddr *)&send, sizeof(struct sockaddr))) < 0) { + perror("bind()"); + fdunlisten(skt2fd[*skt]); + close(skt2fd[*skt]); + close(fd); + return(ddpSktErr); + } + + fdlistener(fd, kip_get, iov, iovlen); + + skt2kip[*skt] = fd; + + return(noErr); + } + + /* + * close off socket opened by abOpen() + * + */ + + export int + abClose(skt) + int skt; + { + int fd; + + if (skt < 0 || skt > ddpMaxSkt) { + fprintf(stderr,"abClose: skt out of range\n"); + exit(0); + } + + /* close AppleTalk skt */ + if ((fd = skt2fd[skt]) >= 0) { + fdunlisten(fd); + close(fd); + } + + /* close KIP loopback */ + if ((fd = skt2kip[skt]) >= 0) { + fdunlisten(fd); + close(fd); + } + + skt2fd[skt] = -1; /* mark as unused */ + skt2kip[skt] = -1; /* mark as unused */ + + return(0); + } + + int + abnet_cacheit() + { + } + + /* + * get a packet from the network + * + * construct appropriate DDP header. + * + */ + + private int + ddp_get(fd, iov, iovlen) + int fd; + struct iovec *iov; + int iovlen; + { + struct msghdr msg; + int len, err; + LAP *lap; + DDP *ddp; + + /* want DDP type in byte 0 */ + iov[IOV_DDP_LVL].iov_len = 1; + + msg.msg_name = (caddr_t) &raddr; + msg.msg_namelen = sizeof(struct sockaddr_at); + msg.msg_iov = iov+1; + msg.msg_iovlen = iovlen-1; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + + len = sizeof(struct sockaddr_at); + if ((err = getsockname(fd, &addr, &len)) < 0) { + perror("getsockname()"); + return(err); + } + + if ((len = recvmsg(fd, &msg, 0)) < 0) { + perror("recvmsg()"); + return(len); + } + + /* make up some dummy headers */ + + lap = (LAP *)iov[IOV_LAP_LVL].iov_base; + lap->type = lapDDP; + lap->dst = addr.sat_addr.s_node; + lap->src = raddr.sat_addr.s_node; + iov[IOV_LAP_LVL].iov_len = lapSize; + + ddp = (DDP *)iov[IOV_DDP_LVL].iov_base; + ddp->type = iov[IOV_DDP_LVL].iov_base[0]; + ddp->length = len + ddpSize - 1; + ddp->checksum = 0; + ddp->dstNet = addr.sat_addr.s_net; + ddp->srcNet = raddr.sat_addr.s_net; + ddp->dstNode = addr.sat_addr.s_node; + ddp->srcNode = raddr.sat_addr.s_node; + ddp->dstSkt = addr.sat_port; + ddp->srcSkt = raddr.sat_port; + iov[IOV_DDP_LVL].iov_len = ddpSize; + + return(ddp_protocol(iov+1, iovlen-1, len+ddpSize)); + } + + /* + * read a KIP packet via loopback + * + */ + + private int + kip_get(fd, iov, iovlen) + int fd; + struct iovec *iov; + int iovlen; + { + struct msghdr msg; + int len; + LAP *lap; + + msg.msg_name = (caddr_t) &from; + msg.msg_namelen = sizeof(from); + msg.msg_iov = iov; + msg.msg_iovlen = iovlen; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + + if ((len = recvmsg(fd, &msg, 0)) < 0) { + perror("recvmsg()"); + return(len); + } + if (iov->iov_len != lapSize) /* check */ + return(-1); + + lap = (LAP *)iov->iov_base; + + if (lap->type == lapDDP) + return(ddp_protocol(iov+1, iovlen-1, len-lapSize)); + + return(-1); + } + + export int + routeddp(iov, iovlen) + struct iovec *iov; + int iovlen; + { + struct sockaddr_at taddr; + struct sockaddr_in tokip; + struct msghdr msg; + DDP *ddp; + LAP lap; + int err; + int fd; + + ddp = (DDP *)iov[IOV_DDP_LVL].iov_base; /* pick out ddp header */ + + /* check ddp socket(s) for validity */ + if ( ddp->srcSkt == 0 || ddp->srcSkt == ddpMaxSkt || + ddp->dstSkt == 0 || ddp->dstSkt == ddpMaxSkt || + skt2fd[ddp->srcSkt] == -1 || skt2kip[ddp->srcSkt] == -1) + return(ddpSktErr); + + /* check for loopback */ + if ((ddp->dstNet == this_net) + && (ddp->dstNode == this_node || ddp->dstNode == 0xff)) { + lap.type = lapDDP; + lap.dst = ddp->dstNode; + lap.src = this_node; + iov[IOV_LAP_LVL].iov_base = (caddr_t)⪅ + iov[IOV_LAP_LVL].iov_len = lapSize; + + tokip.sin_family = AF_INET; + tokip.sin_addr.s_addr = bridge_addr.s_addr; + if ((tokip.sin_port = ddp2ipskt(ddp->dstSkt)) == 0) + return(ddpSktErr); + + msg.msg_name = (caddr_t)&tokip; + msg.msg_namelen = sizeof(tokip); + msg.msg_iov = iov; + msg.msg_iovlen = iovlen; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + fd = skt2kip[ddp->srcSkt]; + + if ((err = sendmsg(fd, &msg, 0)) < 0) + perror("sendmsg()"); + + if (ddp->dstNode != 0xff) + return(noErr); + } + + /* send via kernel EtherTalk */ + + bzero(&taddr, sizeof(struct sockaddr_at)); + taddr.sat_family = AF_APPLETALK; + taddr.sat_addr.s_net = ddp->dstNet; + taddr.sat_addr.s_node = ddp->dstNode; + taddr.sat_port = ddp->dstSkt; + + /* collapse header, except for DDP Type */ + iov[IOV_DDP_LVL].iov_base += (ddpSize-1); + iov[IOV_DDP_LVL].iov_len = 1; /* ddp type */ + + msg.msg_name = (caddr_t)&taddr; + msg.msg_namelen = sizeof(struct sockaddr_at); + msg.msg_iov = iov+1; + msg.msg_iovlen = iovlen-1; + msg.msg_accrights = 0; + msg.msg_accrightslen = 0; + fd = skt2fd[ddp->srcSkt]; + + if ((err = sendmsg(fd, &msg, 0)) < 0) { + perror("sendmsg()"); + return(err); + } + + return(noErr); + } + + /* + * configure the network interface + * + */ + + int + ifconfig(net, node) + int *net, *node; + { + struct sockaddr_at addr; + struct sockaddr_at *sat; + struct ifreq ifreq; + int len, err; + int fd; + + if ((fd = socket(AF_APPLETALK, SOCK_DGRAM, 0)) < 0) { + perror("socket()"); + return(fd); + } + + strncpy(ifreq.ifr_name, interface, sizeof(ifreq.ifr_name)); + sat = (struct sockaddr_at *) &ifreq.ifr_addr; + bzero(sat, sizeof(struct sockaddr_at)); + sat->sat_family = AF_APPLETALK; + sat->sat_addr.s_net = *net; + sat->sat_addr.s_node = *node; + sat->sat_port = ATADDR_ANYPORT; + + if ((err = ioctl(fd, SIOCSIFADDR, &ifreq)) < 0) { + perror("SIOCSIFADDR"); + return(err); + } + + bzero(&addr, sizeof(struct sockaddr_at)); + addr.sat_family = AF_APPLETALK; + addr.sat_addr.s_net = ATADDR_ANYNET; + addr.sat_addr.s_node = ATADDR_ANYNODE; + addr.sat_port = ATADDR_ANYPORT; + + if ((err = bind(fd, &addr, sizeof(struct sockaddr_at))) < 0) { + perror("bind()"); + return(err); + } + + len = sizeof(struct sockaddr_at); + if ((err = getsockname(fd, &addr, &len)) < 0) { + perror("getsockname()"); + return(err); + } + + *net = addr.sat_addr.s_net; + *node = addr.sat_addr.s_node; + + close(fd); + return(0); + } + + /* + * ddp to udp wks translate table + * + */ + + struct wks { + char *name; /* name of wks (as in /etc/services) */ + int ddpport; /* ddp port to map from */ + int udpport; /* udp port to map to */ + int notinited; /* tried /etc/services? */ + }; + + /* + * udpport is initially set to the old + * (768) values for compatibility + * + */ + + #define WKS_entry(name, ddpsock) {(name), (ddpsock), ddpWKSUnix+(ddpsock), 1} + + private struct wks wks[] = { + WKS_entry("at-rtmp", rtmpSkt), + WKS_entry("at-nbp", nbpNIS), + WKS_entry("at-echo", echoSkt), + WKS_entry("at-zis", zipZIS), + WKS_entry(NULL, 0) + }; + + /* + * Translate ddp socket to UDP port: returns 0 if no mapping + * + */ + + ddp2ipskt(ddpskt) + int ddpskt; + { + struct wks *wksp; + struct servent *serv; + + if (ddpskt < 0 || ddpskt > ddpMaxSkt) + return(0); + + if (ddpskt & ddpWKS) /* 128+x means non-wks */ + return(ddpskt + ddpNWKSUnix); + + if (ddpskt2udpport[ddpskt] < 0) { + for (wksp = wks; wksp->name != NULL; wksp++) + if (wksp->ddpport == ddpskt) { + if ((serv = getservbyname(wksp->name, "udp")) != NULL) + wksp->udpport = ntohs(serv->s_port); /* replace with new */ + if (dbug.db_ini) + fprintf(stderr, "port for %s is %d\n",wksp->name,wksp->udpport); + endservent(); + ddpskt2udpport[ddpskt] = wksp->udpport; + return(wksp->udpport); + } + ddpskt2udpport[ddpskt] = 0; + } + return(ddpskt2udpport[ddpskt]); + } + + #ifdef NEEDNETBUF + #ifdef NEEDMSGHDR + struct msghdr { + caddr_t msg_name; /* name to send to */ + int msg_namelen; /* size of name */ + struct iovec *msg_iov; /* io vec */ + int msg_iovlen; /* length */ + int msg_accrights; /* dummy */ + int msg_accrightslen; + }; + #endif NEEDMSGHDR + + /* + * buffer larger than maximum ddp pkt by far + * + */ + + private char net_buffer[ddpMaxData*2]; + + #ifdef NOSENDMSG + /* + * limited sendmsg - limits to sizeof(net_buffer) + * + */ + + sendmsg(fd, msg, flags) + int fd; + struct msghdr *msg; + int flags; + { + int err; + int i, pos, len; + struct iovec *iov; + + iov = msg->msg_iov; + for (i=0, pos=0; i < msg->msg_iovlen; i++, iov++) { + len = iov->iov_len; + if (len+pos > sizeof(net_buffer)) /* if overflow */ + len = sizeof(net_buffer)-pos; /* then limit */ + bcopy(iov->iov_base, net_buffer+pos, len); + pos+= len; + if (len != iov->iov_len) /* we don't have any more space */ + break; + } + len = pos; + if ((err=sendto(fd,net_buffer,len,0,msg->msg_name,msg->msg_namelen)) < 0) + perror("sendmsg()"); + return(err); + } + #endif NOSENDMSG + + #ifdef NORECVMSG + recvmsg(fd, msg, flags) + int fd; + struct msghdr *msg; + int flags; + { + int err; + int i, pos, len, blen; + struct iovec *iov; + + err = recvfrom(fd, net_buffer, sizeof(net_buffer), 0, + msg->msg_name, &msg->msg_namelen); + if (err < 0) + perror("recvfrom()"); + for (blen=err,pos=0,i=0,iov=msg->msg_iov; i < msg->msg_iovlen; i++, iov++) { + len = min(iov->iov_len, blen); + if ((pos + len) > sizeof(net_buffer)) /* if asking for too much */ + len = sizeof(net_buffer) - pos; /* then limit */ + bcopy(net_buffer+pos, iov->iov_base, len); + pos += len; + blen -= len; + /* either no more room or no more data */ + if (len != iov->iov_len) + break; + } + return(err); + } + #endif NORECVMSG + #endif NEEDNETBUF + + /* + * OSErr GetNodeAddress(int *myNode,*myNet) + * + * GetNodeAddress returns the net and node numbers for the current host. + * + */ + + export OSErr + GetNodeAddress(myNode,myNet) + int *myNode,*myNet; + { + *myNode = this_node; + *myNet = this_net; + return(noErr); /* is ok */ + } + + /* + * Set Node Address + * + */ + + OSErr + SetNodeAddress(myNet, myNode) + int myNet, myNode; + { + if (ifconfig(&myNet, &myNode) == 0) { + this_net = nis_net = myNet; + this_node = nis_node = myNode; + etalkdbupdate(NULL); + } + return(noErr); + } + + /* + * Get Bridge Address + * + */ + + OSErr + GetBridgeAddress(baddr) + AddrBlock *baddr; + { + baddr->net = bridge_net; + baddr->node = bridge_node; + return(noErr); + } + + /* + * Set Bridge Address + * + */ + + OSErr + SetBridgeAddress(baddr) + AddrBlock *baddr; + { + bridge_net = baddr->net; + bridge_node = baddr->node; + if (this_net == 0) + SetNodeAddress(bridge_net, 0); + etalkdbupdate(NULL); + return(noErr); + } + + #ifdef PHASE2 + /* + * Set Network Range + * + */ + + OSErr + SetNetRange(range_start, range_end) + u_short range_start, range_end; + { + this_net = nis_net = net_range_start = range_start; + net_range_end = range_end; + etalkdbupdate(NULL); + return(noErr); + } + #endif PHASE2 *** lib/cap/abversion.c.orig Thu Feb 28 23:43:00 1991 --- lib/cap/abversion.c Sat Mar 7 21:07:46 1992 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 91/02/15 22:49:29 $ ! * $Header: abversion.c,v 2.1 91/02/15 22:49:29 djh Rel $ ! * $Revision: 2.1 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1992/03/07 11:07:25 $ ! * $Header: /mac/src/cap60/lib/cap/RCS/abversion.c,v 2.2 1992/03/07 11:07:25 djh Rel djh $ ! * $Revision: 2.2 $ */ /* *************** *** 41,50 **** myversion.cv_type = "Modified UDP encapsulation"; break; case LAP_ETALK: myversion.cv_type = "EtherTalk encapsulation"; break; ! case LAP_ETALK2: ! myversion.cv_type = "EtherTalk Phase 2 encapsulation"; break; } return(&myversion); --- 41,54 ---- myversion.cv_type = "Modified UDP encapsulation"; break; case LAP_ETALK: + #ifdef PHASE2 + myversion.cv_type = "EtherTalk Phase 2 encapsulation"; + #else PHASE2 myversion.cv_type = "EtherTalk encapsulation"; + #endif PHASE2 break; ! case LAP_KERNEL: ! myversion.cv_type = "Kernel Based EtherTalk encapsulation"; break; } return(&myversion); *** netat/appletalk.h.orig Thu Feb 28 23:43:37 1991 --- netat/appletalk.h Sat Mar 7 21:08:12 1992 *************** *** 1,7 **** /* ! * $Author: djh $ $Date: 91/02/15 22:59:06 $ ! * $Header: appletalk.h,v 2.1 91/02/15 22:59:06 djh Rel $ ! * $Revision: 2.1 $ */ /* --- 1,7 ---- /* ! * $Author: djh $ $Date: 1992/03/07 11:08:05 $ ! * $Header: /mac/src/cap60/netat/RCS/appletalk.h,v 2.2 1992/03/07 11:08:05 djh Rel djh $ ! * $Revision: 2.2 $ */ /* *************** *** 98,105 **** #define LAP_KIP 1 /* "standard" KIP */ #define LAP_MKIP 2 /* modified KIP for UAB */ ! #define LAP_ETALK 3 /* EtherTalk phase 1 */ ! #define LAP_ETALK2 4 /* EtherTalk phase 2 */ /* * Masterbridge routing protocol --- 98,105 ---- #define LAP_KIP 1 /* "standard" KIP */ #define LAP_MKIP 2 /* modified KIP for UAB */ ! #define LAP_ETALK 3 /* EtherTalk phase 1/2 */ ! #define LAP_KERNEL 4 /* kernel EtherTalk */ /* * Masterbridge routing protocol *** etc/atis.c.orig Sat Aug 31 19:44:49 1991 --- etc/atis.c Sat Mar 7 21:08:41 1992 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1991/08/31 09:44:40 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/etc/RCS/atis.c,v 2.6 1991/08/31 09:44:40 djh Rel djh $"; ! static char revision[] = "$Revision: 2.6 $"; /* * atis.c - a simple appletalk information server --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1992/03/07 11:08:32 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/etc/RCS/atis.c,v 2.7 1992/03/07 11:08:32 djh Rel djh $"; ! static char revision[] = "$Revision: 2.7 $"; /* * atis.c - a simple appletalk information server *************** *** 456,462 **** logit(L_UERR|0, "ECHO: ECHO socket not available: error %d", echoerr); } ! if (lap_proto == LAP_ETALK && rtmpskt) { if ((rtmperr = DDPOpenSocket(&rtmpskt, rtmp_listener)) != noErr) logit(L_UERR|0, "RTMP: RTMP socket not available: error %d", rtmperr); } --- 456,462 ---- logit(L_UERR|0, "ECHO: ECHO socket not available: error %d", echoerr); } ! if ((lap_proto == LAP_ETALK || lap_proto == LAP_KERNEL) && rtmpskt) { if ((rtmperr = DDPOpenSocket(&rtmpskt, rtmp_listener)) != noErr) logit(L_UERR|0, "RTMP: RTMP socket not available: error %d", rtmperr); } *** support/capd/Makefile.m4.orig Sat Mar 7 20:58:30 1992 --- support/capd/Makefile.m4 Sat Mar 7 21:00:10 1992 *************** *** 0 **** --- 1,39 ---- + CFLAGS=-DDEBUG cflags() specialcflags() + DESTDIR=capsrvrdestdir() + PROGS=capdprogs() + POBJS=capdpobjs() + CAPLIB=libcap() + LFLAGS= + + SRCS=capd.c + OBJS=capd.o + + all: ${PROGS} + + capd: ${OBJS} ${POBJS} + ${CC} ${LFLAGS} -o capd ${OBJS} ${POBJS} ${CAPLIB} + + install: ${PROGS}.install + + .install: + + capd.install: capd + -strip capd + ifdef([sysvinstall],[install -f $(DESTDIR) capd], + [${INSTALLER} capd ${DESTDIR}]) + + lint: + lint -h capd.c ${SRCS} + + clean: + rm -f *.o capd + + spotless: + rm -f *.o *.orig capd + + capd.o: capd.c + ${CC} -c capd.c ${CFLAGS} + + capd.kas.o: capd.kas.c + ${CC} -c capd.kas.c ${CFLAGS} + *** support/capd/capd.c.orig Sat Mar 7 20:58:30 1992 --- support/capd/capd.c Sat Mar 7 21:03:47 1992 *************** *** 0 **** --- 1,153 ---- + /* + * $Author: djh $ $Date: 1992/03/07 11:03:35 $ + * $Header: /mac/src/cap60/support/capd/RCS/capd.c,v 2.1 1992/03/07 11:03:35 djh Rel djh $ + * $Revision: 2.1 $ + */ + + /* + * capd - general purpose CAP daemon + * + * djh@munnari.OZ.AU + * + */ + + #include + #include + #include + #include + #ifdef PHASE2 + #include + #ifndef ultrix + #include + #endif ultrix + #include + #endif PHASE2 + #include + #include + #include + + extern char interface[50]; /* which ethernet device */ + extern char this_zone[34]; /* zone for this host */ + extern struct in_addr bridge_addr; /* IP address for local bridge */ + extern byte bridge_node; /* the local bridge */ + extern word bridge_net; /* the local bridge */ + extern byte this_node; /* this host node */ + extern word this_net; /* this host node */ + extern byte nis_node; /* atis running here */ + extern word nis_net; /* atis running here */ + #ifdef PHASE2 + extern word net_range_start; /* phase 2 network range start */ + extern word net_range_end; /* phase 2 network range end */ + #endif PHASE2 + + extern short lap_proto; /* our LAP mechanism */ + + int dlevel=0; /* debug level */ + + main(argc, argv) + int argc; + char *argv[]; + { + int c; + char *cp, *ep; + extern int optind; + extern char *optarg; + short capdIdent(); + void run(); + + while ((c = getopt(argc, argv, "D:d:l:")) != EOF) { + switch (c) { + case 'D': + dlevel = atoi(optarg); + if (dlevel > L_LVLMAX) + dlevel = L_LVLMAX; + break; + case 'd': + dbugarg(optarg); + dlevel = 1; + break; + case 'l': + logitfileis(optarg, "w"); + break; + } + } + set_debug_level(dlevel); + + openetalkdb(NULL); /* open/create etalk.local */ + + nis_net = this_net = 0; /* assume that we don't know */ + nis_node = this_node = 0; + bridge_net = bridge_node = 0; + bridge_addr.s_addr = inet_addr("127.0.0.1"); + + #ifdef PHASE2 + this_net = htons(0xff00); /* the startup range */ + net_range_start = htons(0); /* the total range */ + net_range_end = htons(0xfffe); + #endif PHASE2 + + lap_proto = capdIdent(); + + if (argc == (optind+2)) { + /* arg list supplied interface & zone names */ + strncpy(interface, argv[optind++], sizeof(interface)); + strncpy(this_zone, argv[optind++], sizeof(this_zone)); + } + + if (optind != argc) { + fprintf(stderr, + "usage: capd [-D level] [-d opt] [-l log] [interface zone]\n"); + exit(1); + } + + if (*interface == '\0') { + fprintf(stderr, "No ethernet interface specified\n"); + exit(1); + } + ep = NULL; + for (cp = interface; *cp != '\0'; cp++) { + if (*cp >= '0' && *cp <= '9') + ep = cp; + } + if (ep == NULL) { /* interface, but no number */ + fprintf(stderr, "Specified interface invalid: %s\n", interface); + exit(1); + } + if (*this_zone == '\0') { + fprintf(stderr, "No zone name specified\n"); + exit(1); + } + + etalkdbupdate(NULL); /* rewrite gleaned information */ + + if (!dbug.db_flgs && (dlevel == 0)) + disassociate(); + + run(); /* do all the CAPD work */ + + (void)fprintf(stderr, "capd: run() returned!\n"); + exit(1); + } + + disassociate() + { + int i; + /* disassociate */ + if (fork()) + _exit(0); /* kill parent */ + for (i=0; i < 3; i++) close(i); /* kill */ + (void)open("/",0); + #ifdef NODUP2 + (void)dup(0); /* slot 1 */ + (void)dup(0); /* slot 2 */ + #else NODUP2 + (void)dup2(0,1); + (void)dup2(0,2); + #endif NODUP2 + #ifdef TIOCNOTTY + if ((i = open("/dev/tty",2)) > 0) { + (void)ioctl(i, TIOCNOTTY, (caddr_t)0); + (void)close(i); + } + #endif TIOCNTTY + } *** support/capd/capd.kas.c.orig Sat Mar 7 20:58:30 1992 --- support/capd/capd.kas.c Sat Mar 7 21:03:56 1992 *************** *** 0 **** --- 1,29 ---- + /* + * $Author: djh $ $Date: 1992/03/07 11:03:35 $ + * $Header: /mac/src/cap60/support/capd/RCS/capd.kas.c,v 2.1 1992/03/07 11:03:35 djh Rel djh $ + * $Revision: 2.1 $ + */ + + #include + + /* + * CAPD dummy run routine for Kernel AppleTalk + * + */ + + void + run() + { + exit(0); + } + + /* + * identify LAP method being used + * + */ + + short + capdIdent() + { + return(LAP_KERNEL); + } *** support/capd/README.orig Sat Mar 7 21:35:28 1992 --- support/capd/README Sat Mar 7 21:35:16 1992 *************** *** 0 **** --- 1,11 ---- + CAPD + ---- + + CAPD is a general purpose CAP daemon. The initial version for use with + Kernel AppleTalk simply sets up reasonable values in the etalk.local + configuration file and exits. + + The usual arguments are identical to those used with aarpd, ie: + + capd [-D level] [-d opt] [-l log] interface zone + *** README.orig Sat Mar 7 21:09:27 1992 --- README Sat Mar 7 21:09:55 1992 *************** *** 3,9 **** (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 93, February 1992 Introduction ------------ --- 3,9 ---- (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 94, March 1992 Introduction ------------