Patch #: 13 Type: update Priority: none Submitted: David Hornsby Submitted: Dave Platt Submitted: Rob Newberry Submitted: Bill Hart Submitted: Ernie Elu Modification: add support for BSDI 1.1, FreeBSD 2.0, Linux (kernel > 1.1.70) Archived: munnari.OZ.AU mac/cap.patches/uar.1.0.patch13 Application: 'cd arns; patch -p < uar.1.0.patch13' *** uar.c.orig Tue Oct 18 11:39:28 1994 --- uar.c Sat Dec 17 17:50:08 1994 *************** *** 15,21 **** * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.1.1.5 $ * */ --- 15,21 ---- * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.1.1.6 $ * */ *************** *** 234,240 **** if (iflist[i].itype == ITYPE_ETHERTALK) /* get interface ethernet address */ ! eth_addr(etfd, iflist[i].eaddr); if (iflist[i].phase == PHASE2) { if (iflist[i].node == 0xfe) /* invalid node number */ --- 234,240 ---- if (iflist[i].itype == ITYPE_ETHERTALK) /* get interface ethernet address */ ! eth_addr(etfd, iflist[i].if_name, iflist[i].eaddr); if (iflist[i].phase == PHASE2) { if (iflist[i].node == 0xfe) /* invalid node number */ *************** *** 258,265 **** nfds = MAXIF*2; FD_ZERO(&fdset); - to.tv_sec = 0; - to.tv_usec = 200000; /* 200 ms */ /* * disassociate --- 258,263 ---- *************** *** 316,321 **** --- 314,322 ---- } if (capfd >= 0) FD_SET(capfd, &fdset); + + to.tv_sec = 0; + to.tv_usec = 200000; /* 200 ms */ if ((res = select(nfds, &fdset, (fd_set *)0, (fd_set *)0, &to))>=0){ gettimeofday(&tn, NULL); *** pf.c.orig Tue Oct 18 10:58:27 1994 --- pf.c Sat Dec 17 17:20:14 1994 *************** *** 23,31 **** * Hewlett Packard HP-UX Link Level Access (LLAPF) * Berkeley Packet Filter (BPFILT) * AIX Ethernet Device (AIXETH) * * $Author: djh $ ! * $Revision: 1.16 $ * */ --- 23,32 ---- * Hewlett Packard HP-UX Link Level Access (LLAPF) * Berkeley Packet Filter (BPFILT) * AIX Ethernet Device (AIXETH) + * Linux SOCK_PACKET * * $Author: djh $ ! * $Revision: 1.18 $ * */ *************** *** 67,72 **** --- 68,84 ---- #define BPFILT #endif __386BSD__ + #ifdef FreeBSD + #define BPFILT + #endif FreeBSD + + #ifdef bsdi + #define BPFILT + #endif bsdi + + #ifdef linux + #endif linux + /* * include header files * *************** *** 104,110 **** --- 116,124 ---- #ifdef BPFILT #include #include + #if (!(defined(bsdi) || defined(FreeBSD) || defined(__386BSD__))) #include + #endif /* bsdi || FreeBSD || __386BSD__ */ #endif BPFILT #ifdef UPFILT *************** *** 153,158 **** --- 167,182 ---- #include #endif SOLARIS + #ifdef bsdi + #include + #include + #endif bsdi + + #ifdef linux + #include + #include + #endif linux + #include #include *************** *** 190,198 **** #ifdef BPFILT #define USE_WRITEV #define USE_GIFADDR - #ifndef __386BSD__ /* no multicast support, yet */ #define USE_SADDMULTI - #endif __386BSD__ #endif BPFILT #ifdef UPFILT --- 214,220 ---- *************** *** 219,224 **** --- 241,261 ---- #ifdef AIXETH #endif AIXETH + #ifdef __386BSD__ + #undef USE_SADDMULTI + #endif __386BSD__ + + #ifdef FreeBSD + #endif FreeBSD + + #ifdef bsdi + #undef USE_GIFADDR + #endif bsdi + + #ifdef linux + #define USE_SADDMULTI + #endif linux + /* * definitions * *************** *** 250,255 **** --- 287,298 ---- u_int pf_bufsize = READBUFSIZ; #endif BPFILT + #ifdef linux + struct socklist { + struct sockaddr sa; + } socklist[32 /* ZZ */]; + #endif linux + struct ifreq ifr; extern int errno; extern int promisc; *************** *** 421,426 **** --- 464,487 ---- } #endif AIXETH + + #ifdef linux + { u_short prot; + + prot = ((typ == 2) ? htons(ETH_P_ALL) : htons(protocol)); + if ((s = socket(AF_INET, SOCK_PACKET, prot)) < 0) { + perror(interface); + return(-1); + } + /* ZZ */ + if (s >= 32) { + fprintf(stderr, "OOPS: socket() returned %d\n", s); + return(-1); + } + /* ZZ */ + } + #endif linux + /* * set filter for protocol and type (IPTalk, Phase 1/2) * *************** *** 606,611 **** --- 667,678 ---- #ifdef AIXETH #endif AIXETH + + #ifdef linux + /* record socket interface name */ + strncpy(socklist[s].sa.sa_data, interface, sizeof(socklist[s].sa.sa_data)); + #endif linux + return(s); } *************** *** 898,903 **** --- 965,974 ---- } #endif AIXETH + + #ifdef linux + #endif linux + return(0); } *************** *** 907,941 **** */ int ! eth_addr(s, addr) int s; u_char *addr; { #ifdef USE_GIFADDR ! struct sockaddr *sa; ! if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { ! perror("SIOCGIFADDR"); ! return(-1); } - #if (defined(sgi) || defined(__386BSD__)) - sa = (struct sockaddr *)&ifr.ifr_data; - #else sgi - sa = (struct sockaddr *)ifr.ifr_data; - #endif sgi - bcopy((char *)sa->sa_data, (char *)addr, 6); #endif USE_GIFADDR #ifdef USE_ENET ! struct endevp endev; ! if (ioctl(s, EIOCDEVP, &endev) < 0) { ! perror("EIOCDEVP"); ! return(-1); } - bcopy(endev.end_addr, addr, 6); #endif USE_ENET --- 978,1021 ---- */ int ! eth_addr(s, interface, addr) int s; + char *interface; u_char *addr; { + #ifdef bsdi + return(get_eth_addr(s, interface, addr)); + #endif bsdi + + #ifdef USE_GIFADDR ! { struct sockaddr *sa; ! strcpy(ifr.ifr_name, interface); ! if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { ! perror("SIOCGIFADDR"); ! return(-1); ! } ! #if (defined(sgi) || defined(__386BSD__) || defined(FreeBSD)) ! sa = (struct sockaddr *)&ifr.ifr_data; ! #else /* sgi || __386BSD__ || FreeBSD */ ! sa = (struct sockaddr *)ifr.ifr_data; ! #endif /* sgi || __386BSD__ || FreeBSD */ ! bcopy((char *)sa->sa_data, (char *)addr, 6); } #endif USE_GIFADDR #ifdef USE_ENET ! { struct endevp endev; ! if (ioctl(s, EIOCDEVP, &endev) < 0) { ! perror("EIOCDEVP"); ! return(-1); ! } ! bcopy(endev.end_addr, addr, 6); } #endif USE_ENET *************** *** 993,998 **** --- 1073,1092 ---- } #endif DLPIPF + + #ifdef linux + strcpy(ifr.ifr_name, interface); + if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { + perror("SIOCGIFHWADDR"); + return(-1); + } + #ifdef OLD_SIOCGIFHWADDR + memcpy((char *)addr, ifr.ifr_hwaddr.sa_data, 6); + #else OLD_SIOCGIFHWADDR + memcpy((char *)addr, ifr.ifr_hwaddr, 6); + #endif OLD_SIOCGIFHWADDR + #endif linux + return(0); } *************** *** 1265,1270 **** --- 1359,1370 ---- return(0); #endif sgi + + #ifdef linux + if (phase == 2) + return(0); + #endif linux + return(1); } *************** *** 1374,1380 **** return(cc+off); #endif hpux ! #if (!(defined(BPFILT) || defined(sgi) || defined(hpux))) RDS[0].dataLen = 0; if ((cc = read(fd, (char *)buf, len)) <= 0) --- 1474,1516 ---- return(cc+off); #endif hpux ! ! #ifdef linux ! int fromlen; ! struct sockaddr sa; ! /* ! * this is slightly less than optimal due to Linux SOCK_PACKET limitations ! * ! */ ! RDS[0].dataLen = 0; ! fromlen = sizeof(struct sockaddr); ! ! #ifdef USE_MSG_PEEK ! if ((cc = recvfrom(fd, (char *)buf, 22, MSG_PEEK, &sa, &fromlen)) <= 0) ! return(cc); ! #else USE_MSG_PEEK ! if ((cc = recvfrom(fd, (char *)buf, len, 0, &sa, &fromlen)) <= 0) ! return(cc); ! #endif USE_MSG_PEEK ! ! /* check if right interface */ ! if (strcmp(sa.sa_data, socklist[fd].sa.sa_data)) ! return(0); ! ! #ifdef USE_MSG_PEEK ! if ((cc = recvfrom(fd, (char *)buf, len, 0, NULL, NULL)) <= 0) ! return(cc); ! #endif USE_MSG_PEEK ! ! RDS[0].dataLen = cc; ! RDS[0].dataPtr = buf; ! RDS[1].dataLen = 0; ! ! return(cc); ! #endif linux ! ! ! #if (!(defined(BPFILT) || defined(sgi) || defined(hpux) || defined(linux))) RDS[0].dataLen = 0; if ((cc = read(fd, (char *)buf, len)) <= 0) *************** *** 1419,1424 **** --- 1555,1567 ---- #ifdef USE_WRITEV struct iovec iov[2]; + #ifdef FreeBSD_SWAP_BUG + u_char swap; + + swap = buf[12]; + buf[12] = buf[13]; + buf[13] = swap; + #endif FreeBSD_SWAP_BUG iov[0].iov_base = (caddr_t)buf; iov[0].iov_len = 14; *************** *** 1461,1469 **** --- 1604,1619 ---- return(len); #endif AIXETH + + #ifdef linux + if (sendto(fd, buf, len, 0, &socklist[fd].sa, sizeof(struct sockaddr)) == len) + return(len); + #endif linux + return(-1); } + #ifdef sgi /* * NB: in non-promiscuous mode using DRAIN, we can't see typ==0 (IPTalk) *************** *** 1697,1699 **** --- 1847,1950 ---- return(0); } #endif DLPIPF + + #ifdef bsdi + struct nlist nlst[] = { + { "_ifnet" }, + "", + }; + + /* + * BSDI + * + * Get interface address from the kernel since the SIOCGIFADDR + * ioctl isn't implemented in a number of ethernet drivers. + * + */ + + int + get_eth_addr(s, interface, addr) + int s; + char *interface; + u_char *addr; + { + kvm_t *kvmd; + int err = -1; + off_t ifnetptr; + off_t aifnetptr; + off_t ifaddrptr; + struct sockaddr sa; + struct ifnet ifnet; + struct ifaddr ifaddr; + struct arpcom arpcom; + struct sockaddr_dl *sdl; + char *cp, if_name[16]; + + if ((kvmd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL) { + fprintf(stderr, "kvm_open: can't open kernel!\n"); + return(-1); + } + if (kvm_nlist(kvmd, nlst) < 0 || nlst[0].n_type == 0) { + fprintf(stderr, "kvm_list: can't find namelist!\n"); + kvm_close(kvmd); + return(-1); + } + if (nlst[0].n_value == 0) { + fprintf(stderr, "kvm_list: _ifnet symbol not defined!\n"); + kvm_close(kvmd); + return(-1); + } + if (kvm_read(kvmd, nlst[0].n_value, (char *)&ifnetptr, + sizeof(ifnetptr)) != sizeof(ifnetptr)) { + fprintf(stderr, "kvm_read: bogus read!\n"); + kvm_close(kvmd); + return(-1); + } + while (ifnetptr) { + aifnetptr = ifnetptr; + if (kvm_read(kvmd, ifnetptr, (char *)&ifnet, + sizeof(ifnet)) == sizeof(ifnet)) { + if (kvm_read(kvmd, (off_t)ifnet.if_name, if_name, + sizeof(if_name)) == sizeof(if_name)) { + ifnetptr = (off_t)ifnet.if_next; + if_name[15] = '\0'; + cp = (char *)index(if_name, '\0'); + sprintf(cp, "%d", ifnet.if_unit); + if (strcmp(if_name, interface) != 0) + continue; + ifaddrptr = (off_t)ifnet.if_addrlist; + while (ifaddrptr) { + if (kvm_read(kvmd, ifaddrptr, (char *)&ifaddr, + sizeof(ifaddr)) == sizeof(ifaddr)) { + ifaddrptr = (off_t)ifaddr.ifa_next; + if (kvm_read(kvmd, (off_t)ifaddr.ifa_addr, (char *)&sa, + sizeof(sa)) == sizeof(sa)) { + if (sa.sa_family == AF_LINK) { + sdl = (struct sockaddr_dl *)&sa; + cp = (char *)LLADDR(sdl); + if (sdl->sdl_alen == 0) { + /* no address here, try ethernet driver */ + if (kvm_read(kvmd, aifnetptr, (char *)&arpcom, + sizeof(arpcom)) == sizeof(arpcom)) + cp = (char *)arpcom.ac_enaddr; + } + bcopy(cp, (char *)addr, 6); + fprintf(stderr, "BSDI: %-5s eth address %x:%x:%x:%x:%x:%x\n", + interface, addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); + err = 0; + break; + } + continue; + } + } + break; + } + } + } + break; + } + kvm_close(kvmd); + return(err); + } + #endif bsdi *** Makefile.orig Tue Oct 18 11:34:52 1994 --- Makefile Fri Dec 16 15:39:15 1994 *************** *** 34,44 **** # LFLAGS= # LIBS=pfopen.o # ! # For 386BSD, FreeBSD ! # CFLAGS=-DBPFILT # LFLAGS= # LIBS= # # For HP 9000/700 HP-UX 9.x, with HP cc, (optimization suggestion only) # Using Archive libraries does not result in noticeable performance gain. # CFLAGS=+ESlit -J +O3 --- 34,55 ---- # LFLAGS= # LIBS=pfopen.o # ! # For 386BSD, FreeBSD 1.0, Phase 1 only ! # CFLAGS=-D__386BSD__ # LFLAGS= # LIBS= # + # For FreeBSD 2.0, Phase 1 or Phase 2 + # Also define FreeBSD_SWAP_BUG to workaround ethernet driver bug + # CFLAGS=-DFreeBSD -DFreeBSD_SWAP_BUG + # LFLAGS= + # LIBS= + # + # For BSDI BSD/386, Phase 1 or Phase 2 + # CFLAGS= + # LFLAGS= + # LIBS=-lkvm + # # For HP 9000/700 HP-UX 9.x, with HP cc, (optimization suggestion only) # Using Archive libraries does not result in noticeable performance gain. # CFLAGS=+ESlit -J +O3 *************** *** 49,54 **** --- 60,66 ---- CFLAGS= LFLAGS= LIBS= + CC=cc all: uar *** README.orig Wed Nov 2 11:53:05 1994 --- README Fri Dec 16 16:02:47 1994 *************** *** 4,10 **** The University of Melbourne djh@munnari.OZ.AU October, 1993 ! version 1.0.12 --- 4,10 ---- The University of Melbourne djh@munnari.OZ.AU October, 1993 ! version 1.0.13 *************** *** 17,30 **** Native EtherTalk mode, but on a wider variety of host types. UAR currently supports Phase 1 and Phase 2 EtherTalk networks connected ! to SUN, DEC ULTRIX/Alpha, SGI IRIX, Sony NEWS 4.2, HP-UX 8.07 and IBM RS6000 ! AIX workstations, and Phase 1 only on Sony NEWS pre-4.2 and 386BSD/FreeBSD ! workstations. NOTICE ! Copyright (c) 1993, The University of Melbourne. All Rights Reserved. --- 17,31 ---- Native EtherTalk mode, but on a wider variety of host types. UAR currently supports Phase 1 and Phase 2 EtherTalk networks connected ! to SUN SunOS/Solaris, DEC ULTRIX/Alpha, SGI IRIX, Sony NEWS 4.2, HP-UX ! 8.07, IBM RS6000 AIX, Linux 1.1.74, BSDI BSD/386 1.1 and FreeBSD 2.0 ! workstations, and Phase 1 only on Sony NEWS pre-4.2 and 386BSD/FreeBSD ! 1.0 workstations. NOTICE ! Copyright (c) 1993-1994, The University of Melbourne. All Rights Reserved. *************** *** 309,321 **** You MUST manually set the define for LIBS=pfopen.o in the Makefile and copy /usr/lib/examples/packetfilter/pfopen.c to the UAR directory. ----------------------- Notes for 386BSD users: You must install the Berkeley Packet Filter on your system and define ! -DBPFILT in the CFLAGS= line in the Makefile. At this stage, 386BSD supports only Phase 1 EtherTalk due to limitations in multicast support in the 386BSD ethernet driver. -------------------------- (edited ARNS version, as of July '93 UAR is untested on Sony NEWS) --- 310,336 ---- You MUST manually set the define for LIBS=pfopen.o in the Makefile and copy /usr/lib/examples/packetfilter/pfopen.c to the UAR directory. + ---------------------- + Notes for HP-UX users: + + If you receive the message "/dev/lan0: device busy" then you may need + to upgrade your operating system to HP-UX 9.04 or greater. + ----------------------- Notes for 386BSD users: You must install the Berkeley Packet Filter on your system and define ! -D__386BSD__ in the CFLAGS= line in the Makefile. At this stage, 386BSD supports only Phase 1 EtherTalk due to limitations in multicast support in the 386BSD ethernet driver. + + ----------------------- + Notes for FreeBSD 2.0 users: + + You must define -DFreeBSD in the CFLAGS= line in the Makefile. There + appears to be an error in the ethernet driver (at least in the ed0 version) + which causes the IEEE 802.3 length bytes to be reversed. You may also need + to define -DFreeBSD_SWAP_BUG in the Makefile. -------------------------- (edited ARNS version, as of July '93 UAR is untested on Sony NEWS)