Patch #: 35 Type: operational change Priority: none Modification: Phase 2 support for SUN enet driver Submitted: Rakesh Patel Submitted: David Hornsby Archived: munnari.OZ.AU mac/cap.patches/cap60.patch035 Application: 'cd cap60; patch -p < cap60.patches/cap60.patch035' Summary: add code to senetp.c File: cap60/support/ethertalk/senetp.c File: cap60/Configure *** support/ethertalk/senetp.c.orig Sat May 18 17:50:12 1991 --- support/ethertalk/senetp.c Sun Jul 14 21:14:07 1991 *************** *** 1,6 **** ! static char rcsid[] = "$Author: djh $ $Date: 1991/05/18 07:49:53 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/support/ethertalk/RCS/senetp.c,v 2.3 1991/05/18 07:49:53 djh Exp djh $"; ! static char revision[] = "$Revision: 2.3 $"; /* * senetp.c - Simple "protocol" level interface to enet --- 1,6 ---- ! static char rcsid[] = "$Author: djh $ $Date: 1991/07/14 11:13:57 $"; ! static char rcsident[] = "$Header: /mac/src/cap60/support/ethertalk/RCS/senetp.c,v 2.4 1991/07/14 11:13:57 djh Rel djh $"; ! static char revision[] = "$Revision: 2.4 $"; /* * senetp.c - Simple "protocol" level interface to enet *************** *** 22,27 **** --- 22,28 ---- * Edit History: * * July 1988 CCKim Created + * June 1991 Rakesh Patel/David Hornsby Add Phase 2 support * */ *************** *** 55,60 **** --- 56,68 ---- #include #include "../uab/proto_intf.h" + #ifdef PHASE2 + #include + #include + #include + #include + #endif PHASE2 + typedef struct ephandle { /* ethernet protocol driver handle */ int inuse; /* true if inuse */ int fd; /* file descriptor of socket */ *************** *** 119,125 **** sprintf(devnamebuf, "%s%d",dev,devno); strncpy(eph->ifr.ifr_name, devnamebuf, sizeof eph->ifr.ifr_name); - eph->ifr.ifr_name[sizeof eph->ifr.ifr_name - 1] = ' '; if ((s = init_nit(1024, protocol, socket, &eph->ifr)) < 0) { return(-1); --- 127,132 ---- *************** *** 153,162 **** /* * Initialize nit on a particular protocol type - * - * Runs in promiscous mode for now. - * * Return: socket if no error, < 0 o.w. */ private int init_nit(chunksize, protocol, socket, ifr) --- 160,167 ---- /* * Initialize nit on a particular protocol type * Return: socket if no error, < 0 o.w. + * */ private int init_nit(chunksize, protocol, socket, ifr) *************** *** 165,176 **** int socket; struct ifreq *ifr; { - u_long if_flags; int s; char device[64]; ! strcpy(device, "/dev/"); ! strcat(device, interface); #ifdef EIOCETHERT --- 170,180 ---- int socket; struct ifreq *ifr; { int s; + u_long if_flags; char device[64]; ! sprintf(device, "/dev/%s", interface); #ifdef EIOCETHERT *************** *** 226,231 **** --- 230,387 ---- return(s); } + #ifdef PHASE2 + /* + * add a multicast address to the interface + */ + int + pi_addmulti(s, multi, ifr) + int s; + char *multi; + struct ifreq *ifr; + { + int sock; + char device[64]; + + sprintf(device, "/dev/%s", interface); + + if (s < 0) { + /* get clone */ + if ((s = open(device, O_RDWR)) < 0) { + perror("open: /dev/enetXX"); + return(-1); + } + } + + ifr->ifr_addr.sa_family = AF_UNSPEC; + bcopy(multi, ifr->ifr_addr.sa_data, EHRD); + /* place the "real" interface name (ie0, le0 etc.) into ifr */ + if (pi_ifname(device, ifr) < 0) + exit(1); + + /* + * open a socket, temporarily, to use for SIOC* ioctls + * + */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket()"); + return(-1); + } + if (ioctl(sock, SIOCADDMULTI, (caddr_t)ifr) < 0) { + perror("SIOCADDMULTI"); + close(sock); + return(-1); + } + close(sock); + + return(s); + } + + /* + * ferret around in /dev/kmem for real interface details + * (sometime it would be nice to have an ioctl to do this) + * + */ + + struct enet_info { + struct ifnet *ifp; + }; + + int + pi_ifname(devName, ifr) + char *devName; + struct ifreq *ifr; + { + int kmem; + int dataLen; + int enUnits; + int minorDev; + char *kernelfile; + char namebuf[64]; + struct stat sbuf; + struct nlist nl[3]; + struct ifnet ifnet; + struct enet_info *enet_info; + + kernelfile = "/vmunix"; + if (stat(kernelfile, &sbuf) != 0) { + perror("stat /vmunix"); + return(-1); + } + if ((kmem = open("/dev/kmem", 0)) < 0) { + perror("open /dev/kmem"); + return(-1); + } + + nl[0].n_un.n_name = "_enUnits"; + nl[1].n_un.n_name = "_enet_info"; + nl[2].n_un.n_name = ""; + + nlist(kernelfile,nl); + + if (nl[0].n_type == 0 || nl[1].n_type == 0) { + fprintf(stderr, "pi_ifname() can't find _enUnits or _enet_info\n"); + close(kmem); + return(-1); + } + + (void) lseek(kmem, (nl[0].n_value), 0); + if (read(kmem, &enUnits, sizeof(enUnits)) != sizeof(enUnits)) { + perror("read /dev/kmem #1"); + close(kmem); + return(-1); + } + dataLen = enUnits*sizeof(struct enet_info); + if ((enet_info = (struct enet_info *) malloc(dataLen)) == 0) { + fprintf(stderr, "pi_ifname() can't malloc enet_info\n"); + close(kmem); + return(-1); + } + (void) lseek(kmem, (nl[1].n_value), 0); + if (read(kmem, enet_info, dataLen) != dataLen) { + perror("read /dev/kmem #2"); + close(kmem); + return(-1); + } + + if (stat(devName, &sbuf) != 0) { + perror(devName); + close(kmem); + return(-1); + } + if (!S_ISCHR(sbuf.st_mode)) { + fprintf(stderr, "%s: not character special device!\n", devName); + close(kmem); + return(-1); + } + minorDev = sbuf.st_rdev & 0xff; /* minor device number */ + + if (minorDev >= enUnits) { + fprintf(stderr,"%s: invalid minor device number %d\n", devName, minorDev); + close(kmem); + return(-1); + } + (void) lseek(kmem, enet_info[minorDev].ifp, 0); + if (read(kmem, &ifnet, sizeof(ifnet)) != sizeof(ifnet)) { + perror("read /dev/kmem #3"); + close(kmem); + return(-1); + } + (void) lseek(kmem, ifnet.if_name, 0); + if (read(kmem, namebuf, sizeof(namebuf)) != sizeof(namebuf)) { + perror("read /dev/kmem #4"); + close(kmem); + return(-1); + } + sprintf(ifr->ifr_name, "%s%d", namebuf, ifnet.if_unit); + logit(7, "ENET %s maps to interface %s", devName, ifr->ifr_name); + + free(enet_info); + close(kmem); + return(0); + } + #endif PHASE2 + #ifndef NOBUF /* * setup buffering (not wanted) *************** *** 281,287 **** --- 437,447 ---- register u_short *fwp = pf.enf_Filter; extern int errno; + #ifdef PHASE2 + ethert = htons(EF_8023_TYPE); /* special 802.3 type */ + #else PHASE2 ethert = htons(prot); + #endif PHASE2 #ifdef EIOCETHERT if (ioctl(s, EIOCETHERT, ðert) < 0 && errno != EEXIST ) { perror("ioctl: protocol filter"); *************** *** 299,314 **** #define s_offset(structp, element) (&(((structp)0)->element)) offset = ((int)s_offset(struct ether_header *, ether_type))/sizeof(u_short); ! #ifdef undef ! *fwp++ = ENF_PUSHLIT ; ! *fwp++ = 1; ! pf.enf_FilterLen = 2; ! #endif *fwp++ = ENF_PUSHWORD + offset; *fwp++ = ENF_PUSHLIT | (sock >= 0 ? ENF_CAND : ENF_EQ); *fwp++ = htons(prot); pf.enf_FilterLen = 3; if (sock >= 0) { /* short form */ *fwp++ = ENF_PUSHWORD + offset + 2; *fwp++ = ENF_PUSHLIT | ENF_AND; --- 459,483 ---- #define s_offset(structp, element) (&(((structp)0)->element)) offset = ((int)s_offset(struct ether_header *, ether_type))/sizeof(u_short); ! #ifdef PHASE2 ! offset += 4; /* shorts: 2 bytes length + 6 bytes of 802.2 and SNAP */ ! #endif PHASE2 *fwp++ = ENF_PUSHWORD + offset; *fwp++ = ENF_PUSHLIT | (sock >= 0 ? ENF_CAND : ENF_EQ); *fwp++ = htons(prot); pf.enf_FilterLen = 3; if (sock >= 0) { + #ifdef PHASE2 + *fwp++ = ENF_PUSHWORD + offset + 6; + *fwp++ = ENF_PUSHLIT | ENF_AND; + *fwp++ = htons(0xff00); /* now have dest socket */ + *fwp++ = ENF_PUSHLIT | ENF_COR; + *fwp++ = htons((sock & 0xff) << 8); + /* if not wanted, fail it */ + *fwp++ = ENF_PUSHLIT ; + *fwp++ = 0; + pf.enf_FilterLen += 7; + #else PHASE2 /* short form */ *fwp++ = ENF_PUSHWORD + offset + 2; *fwp++ = ENF_PUSHLIT | ENF_AND; *************** *** 333,339 **** *fwp++ = ENF_PUSHLIT ; *fwp++ = 0; pf.enf_FilterLen += 20; ! } if (ioctl(s, EIOCSETF, &pf) < 0) { --- 502,508 ---- *fwp++ = ENF_PUSHLIT ; *fwp++ = 0; pf.enf_FilterLen += 20; ! #endif PHASE2 } if (ioctl(s, EIOCSETF, &pf) < 0) { *************** *** 420,436 **** caddr_t buf; int bufsiz; { ! struct iovec iov[2]; struct ethernet_addresses ea; int cc; iov[0].iov_base = (caddr_t)&ea; ! /*iov[0].iov_len = sizeof(ea);*/ ! iov[0].iov_len = 14; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = bufsiz; cc = pi_readv(edx, iov, 2); return(cc - sizeof(ea)); } pi_reada(fd, buf, bufsiz, eaddr) --- 589,618 ---- caddr_t buf; int bufsiz; { ! struct iovec iov[3]; struct ethernet_addresses ea; + #ifdef PHASE2 + char header[8]; + #endif PHASE2 int cc; + #ifdef PHASE2 iov[0].iov_base = (caddr_t)&ea; ! iov[0].iov_len = sizeof(ea); ! iov[1].iov_base = (caddr_t)header; /* consume 802.2 hdr & SNAP */ ! iov[1].iov_len = sizeof(header); ! iov[2].iov_base = (caddr_t)buf; ! iov[2].iov_len = bufsiz; ! cc = pi_readv(edx, iov, 3); ! return(cc - sizeof(ea) - sizeof(header)); ! #else PHASE2 ! iov[0].iov_base = (caddr_t)&ea; ! iov[0].iov_len = sizeof(ea); iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = bufsiz; cc = pi_readv(edx, iov, 2); return(cc - sizeof(ea)); + #endif PHASE2 } pi_reada(fd, buf, bufsiz, eaddr) *************** *** 440,458 **** char *eaddr; { struct iovec iov[2]; int cc; iov[0].iov_base = (caddr_t)eaddr; iov[0].iov_len = 14; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = bufsiz; if ((cc = readv(fd, iov, 2)) < 0) { perror("abread"); return(cc); } ! return(cc - 14); } export int --- 622,663 ---- char *eaddr; { struct iovec iov[2]; + #ifdef PHASE2 + char header[5]; /* must be 5! */ + #endif PHASE2 int cc; + #ifdef PHASE2 iov[0].iov_base = (caddr_t)eaddr; iov[0].iov_len = 14; + iov[1].iov_base = (caddr_t)header; /* consume 802.2 hdr & SNAP but */ + iov[1].iov_len = sizeof(header); /* make room for our fake LAP header */ + iov[2].iov_base = (caddr_t)buf; + iov[2].iov_len = bufsiz; + #else PHASE2 + iov[0].iov_base = (caddr_t)eaddr; + iov[0].iov_len = 14; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = bufsiz; + #endif PHASE2 + #ifdef PHASE2 + if ((cc = readv(fd, iov, 3)) < 0) { + #else PHASE2 if ((cc = readv(fd, iov, 2)) < 0) { + #endif PHASE2 perror("abread"); return(cc); } ! #ifdef PHASE2 ! /* make a fake LAP header to fool the higher levels */ ! buf[0] = buf[11]; /* destination node ID */ ! buf[1] = buf[12]; /* source node ID */ ! buf[2] = 0x02; /* always long DDP */ ! return(cc - 14 - sizeof(header)); ! #else PHASE2 return(cc - 14); + #endif PHASE2 } export int *************** *** 466,474 **** struct ether_header eh; struct sockaddr sa; struct iovec iov[2]; iov[0].iov_base = (caddr_t)&eh; ! iov[0].iov_len = 14; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; --- 671,682 ---- struct ether_header eh; struct sockaddr sa; struct iovec iov[2]; + #ifdef PHASE2 + char *q; + #endif PHASE2 iov[0].iov_base = (caddr_t)&eh; ! iov[0].iov_len = sizeof(struct ether_header); iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; *************** *** 480,487 **** return(-1); bcopy(eaddr, &eh.ether_dhost, 6); eh.ether_type = htons(eph->protocol); ! if (writev(eph->fd, iov, 2) < 0) { return(-1); } --- 688,713 ---- return(-1); bcopy(eaddr, &eh.ether_dhost, 6); + #ifdef PHASE2 + eh.ether_type = htons(buflen); + /* + * Fill in the remainder of the 802.2 and SNAP header bytes. + * Clients have to leave 8 bytes free at the start of buf as + * we can't send more than 14 bytes of header :-( + */ + q = (char *) buf; + *q++ = 0xaa; /* destination SAP */ + *q++ = 0xaa; /* source SAP */ + *q++ = 0x03; /* control byte */ + *q++ = (eph->protocol == 0x809b) ? 0x08 : 0x00; + *q++ = 0x00; /* always zero */ + *q++ = (eph->protocol == 0x809b) ? 0x07 : 0x00; + *q++ = (htons(eph->protocol) >> 8) & 0xff; + *q++ = (htons(eph->protocol) & 0xff); + #else PHASE2 eh.ether_type = htons(eph->protocol); ! #endif PHASE2 ! if (writev(eph->fd, iov, 2) < 0) { return(-1); } *************** *** 506,512 **** --- 732,742 ---- if (!ephlist[edx-1].inuse) return(-1); + #ifdef PHASE2 /* leave room for rest of ELAP hdr */ + for (len = 8, p = ebuf+8, i = 0 ; i < iovlen ; i++) + #else PHASE2 for (len = 0, p = ebuf, i = 0 ; i < iovlen ; i++) + #endif PHASE2 if (iov[i].iov_base && iov[i].iov_len >= 0) { bcopy(iov[i].iov_base, p, iov[i].iov_len); p += iov[i].iov_len; /* advance */ *** Configure.orig Wed Jul 10 22:49:36 1991 --- Configure Sun Jul 14 21:26:52 1991 *************** *** 1,7 **** #!/bin/sh ! # $Author: djh $ $Date: 1991/07/10 12:49:26 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.13 1991/07/10 12:49:26 djh Rel djh $ ! # $Revision: 2.13 $ # 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: 1991/07/14 11:26:42 $ ! # $Header: /mac/src/cap60/RCS/Configure,v 2.14 1991/07/14 11:26:42 djh Rel djh $ ! # $Revision: 2.14 $ # 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) # *************** *** 390,417 **** case ${ans} in "yes"|"y") result=0 ! usephase2=1;; *) ! echo "Using EtherTalk Phase 1" ! echo ! echo $newl "Have you installed the 'enet' driver (no) ? " ! read ans ! if [ -z "${ans}" ]; then ans="no" ! fi ! case ${ans} in "yes"|"y") result=1;; *) result=0;; ! esac ! ;; ! esac if [ $result -eq 0 ]; then ! echo "OK, using the NIT ethernet interface." etherpobjs="define([etherpobjs],[snitp.o])" else ! echo "OK, using the 'enet' ethernet interface." etherpobjs="define([etherpobjs],[senetp.o])" fi esac fi fi --- 390,422 ---- case ${ans} in "yes"|"y") result=0 ! usephase2=1 ! ;; *) ! ;; ! esac ! echo $newl "Have you installed the 'enet' driver (no) ? " ! read ans ! if [ -z "${ans}" ]; then 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 ! echo $newl "OK, using the 'enet' ethernet interface" etherpobjs="define([etherpobjs],[senetp.o])" fi + if [ $usephase2 -eq 1 ]; then + echo " with Phase 2." + else + echo "." + fi + ;; esac fi fi *** README.orig Sun Jul 14 21:15:07 1991 --- README Sun Jul 14 21:16:01 1991 *************** *** 3,9 **** (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 34, July 1991 Introduction ------------ --- 3,9 ---- (For use with AppleTalk/Ethernet bridge) o RELEASE NOTES ! o CAP Distribution 6.0, Patch Level 35, July 1991 Introduction ------------