Patch #: 4 Type: update Priority: medium Reported: David Hornsby Modification: add "*" mode in IP filter file for trusted hosts (no passwd) Modification: handle Phase 2 in non-promiscuous mode (DRAIN) under SGI/IRIX Modification: work around Network Control Panel 3.0 problem on Phase 1 nets Modification: update to latest pf.c code (may even work under Solaris 2.1) Archived: munnari.OZ.AU mac/cap.patches/arns.patch004 Application: 'cd arns; patch -p < arns.patch004' *** Makefile.orig Mon Nov 2 19:54:49 1992 --- Makefile Fri Jan 22 00:56:48 1993 *************** *** 18,23 **** --- 18,26 ---- # # For IBM RS6000 AIX, Phase 1 or Phase 2 # CFLAGS=-DAIX + # + # For SUN Solaris 2.N, Phase 1 or Phase 2 + # CFLAGS=-DSOLARIS # CFLAGS= *** arns.c.orig Mon Nov 2 19:53:18 1992 --- arns.c Tue Mar 9 14:10:52 1993 *************** *** 16,22 **** * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.4 $ * */ --- 16,22 ---- * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.5 $ * */ *************** *** 206,212 **** if (phase == 2) { thisNet = P2STARTUP; /* startup range 255.0 */ infoTimer = INFOTimer; /* GetNetInfo period */ ! eth_addmulti(etfd, maddr); /* add m/cast to iface */ nodeTab[254].connType = ARNS_ETALK; /* illegal node number */ nodeTab[254].aarpState = AARP_UNKNOWN;/* illegal node number */ } --- 206,212 ---- if (phase == 2) { thisNet = P2STARTUP; /* startup range 255.0 */ infoTimer = INFOTimer; /* GetNetInfo period */ ! eth_addmulti(etfd, interface, maddr); /* add m/cast to iface */ nodeTab[254].connType = ARNS_ETALK; /* illegal node number */ nodeTab[254].aarpState = AARP_UNKNOWN;/* illegal node number */ } *************** *** 285,290 **** --- 285,291 ---- { u_char *bufp; u_char *data; + int trusted = 0; int i, cc, fromlen; int srcNode, dstNode; int request, reqType; *************** *** 336,354 **** case CONN_PROBE: if (needIPFilter) buildIPFilterList(); ! if (illegalIP(&from, fromlen)) return(reply(&from, fromlen, srcNode, ARNS_ERROR, ERR_ILLEGAL, "Access Denied (IP Address Filter).")); if (users > maxusers) return(reply(&from, fromlen, srcNode, ARNS_ERROR, ERR_TOOBUSY, "Too Many Users Now, Try Later ...")); ! if (password[0] != '\0' && data[0] == '\0') ! return(reply(&from, fromlen, srcNode, ARNS_ERROR, ! ERR_NEEDPASS, "The Server Requires a Password.")); ! if (password[0] != '\0' && passChk(password, data) != 0) { ! record(LOG_BADPASS, &from, srcNode, data); ! return(reply(&from, fromlen, srcNode, ARNS_ERROR, ! ERR_BADPASS, "Server Password Incorrect.")); } if (reqType == CONN_PROBE) return(reply(&from, fromlen, srcNode, ARNS_ERROR, --- 337,357 ---- case CONN_PROBE: if (needIPFilter) buildIPFilterList(); ! if (illegalIP(&from, fromlen, &trusted)) return(reply(&from, fromlen, srcNode, ARNS_ERROR, ERR_ILLEGAL, "Access Denied (IP Address Filter).")); if (users > maxusers) return(reply(&from, fromlen, srcNode, ARNS_ERROR, ERR_TOOBUSY, "Too Many Users Now, Try Later ...")); ! if (!trusted) { ! if (password[0] != '\0' && data[0] == '\0') ! return(reply(&from, fromlen, srcNode, ARNS_ERROR, ! ERR_NEEDPASS, "The Server Requires a Password.")); ! if (password[0] != '\0' && passChk(password, data) != 0) { ! record(LOG_BADPASS, &from, srcNode, data); ! return(reply(&from, fromlen, srcNode, ARNS_ERROR, ! ERR_BADPASS, "Server Password Incorrect.")); ! } } if (reqType == CONN_PROBE) return(reply(&from, fromlen, srcNode, ARNS_ERROR, *************** *** 812,818 **** buildIPFilterList() { FILE *fd; ! char *q, line[160]; if (filter != NULL) { if ((fd = fopen(filter, "r")) == NULL) { --- 815,822 ---- buildIPFilterList() { FILE *fd; ! char line[160]; ! char *mask, *addr; if (filter != NULL) { if ((fd = fopen(filter, "r")) == NULL) { *************** *** 824,837 **** while (fgets(line, sizeof(line), fd) != NULL) { if (line[0] == '#') continue; ! if ((q = (char *) index(line, '\n')) != NULL) ! *q = '\0'; ! q = line+1; ! while (*q != '\0' && isspace(*q)) ! q++; ! if (line[0] == '+' || line[0] == '-') { ! ipFilter[filters].perm = (line[0] == '-'); ! ipFilter[filters].addr = inet_addr(q); if (++filters >= MAXFILTERS) break; } --- 828,847 ---- while (fgets(line, sizeof(line), fd) != NULL) { if (line[0] == '#') continue; ! if ((mask = (char *) index(line, '\n')) != NULL) ! *mask = '\0'; ! mask = line+1; ! while (*mask != '\0' && isspace(*mask)) ! mask++; /* skip spaces */ ! addr = mask; ! while (*addr != '\0' && !isspace(*addr)) ! addr++; /* skip mask */ ! while (*addr != '\0' && isspace(*addr)) ! addr++; /* skip spaces */ ! if (line[0] == '+' || line[0] == '*' || line[0] == '-') { ! ipFilter[filters].perm = line[0]; ! ipFilter[filters].addr = (*addr == '\0') ? 0L : inet_addr(addr); ! ipFilter[filters].mask = (*mask == '\0') ? 0L : inet_addr(mask); if (++filters >= MAXFILTERS) break; } *************** *** 847,864 **** */ int ! illegalIP(sin, fromlen) struct sockaddr_in *sin; ! int fromlen; { int i; if (filters == 0) return(0); ! for (i = 0 ; i < filters ; i++) ! if ((sin->sin_addr.s_addr & ipFilter[i].addr) == sin->sin_addr.s_addr) ! return(ipFilter[i].perm); return(0); } --- 857,889 ---- */ int ! illegalIP(sin, fromlen, trusted) struct sockaddr_in *sin; ! int fromlen, *trusted; { int i; + unsigned long addr; + *trusted = 0; + if (filters == 0) return(0); ! addr = sin->sin_addr.s_addr; ! ! for (i = 0 ; i < filters ; i++) { ! if (ipFilter[i].addr != 0L) { ! if ((addr & ipFilter[i].mask) == ipFilter[i].addr) { ! *trusted = (ipFilter[i].perm == '*'); ! return(ipFilter[i].perm == '-'); ! } ! } else { ! if ((addr & ipFilter[i].mask) == addr) { ! *trusted = (ipFilter[i].perm == '*'); ! return(ipFilter[i].perm == '-'); ! } ! } ! } return(0); } *** arns.h.orig Tue Mar 9 20:37:45 1993 --- arns.h Tue Mar 9 20:38:48 1993 *************** *** 16,22 **** * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.3 $ * */ --- 16,22 ---- * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.6 $ * */ *************** *** 114,119 **** --- 114,123 ---- #define TREL480 0x04 #define TRELMSK 0x07 + #define GETMYZONE 0x07 + #define GETZONELIST 0x08 + #define GETLOCALZONES 0x09 + #define IDLEN 0x08 /* ARNS debug flags */ *************** *** 240,244 **** --- 244,249 ---- struct ipFilter { short perm; + unsigned long mask; unsigned long addr; }; *** ddp.c.orig Tue Mar 9 14:22:25 1993 --- ddp.c Tue Mar 9 14:06:26 1993 *************** *** 16,22 **** * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.3 $ * */ --- 16,22 ---- * djh@munnari.OZ.AU * * $Author: djh $ ! * $Revision: 1.5 $ * */ *************** *** 43,48 **** --- 43,49 ---- extern int debug; extern int infoTimer; extern time_t brHeardFrom; + extern char *interface; extern struct timeval tn; extern struct nodeTab nodeTab[]; *************** *** 305,312 **** --- 306,315 ---- { u_char dNode; u_char dstSkt; + u_char srcSkt; u_char ddpType; u_short dstNet; + u_short TID; int atp_ctrl; if (debug & ROUTEDEBUG) *************** *** 317,322 **** --- 320,326 ---- dstNet = thisNet; dNode = dstNode; dstSkt = pkt[2]; + srcSkt = pkt[3]; ddpType = pkt[4]; atp_ctrl = 5; break; *************** *** 324,329 **** --- 328,334 ---- dstNet = (pkt[4] << 8) | pkt[5]; dNode = pkt[8]; dstSkt = pkt[10]; + srcSkt = pkt[11]; ddpType = pkt[12]; atp_ctrl = 13; break; *************** *** 375,380 **** --- 380,400 ---- } /* + * handle bogus GetLocalZones from Network Control Panel 3.0 + * I *really* wish I didn't have to do this ... + * + */ + + if (phase == PHASE1 && ddpType == ATP && dstSkt == ZIP + && (pkt[atp_ctrl] & FNMSK) == TREQ + && (pkt[atp_ctrl+1] == 0x01) + && (pkt[atp_ctrl+4] == GETLOCALZONES)) { + TID = (pkt[atp_ctrl+2] << 8) | pkt[atp_ctrl+3]; + gmzReply(srcNode, dNode, srcSkt, TID, 1); + return; + } + + /* * handle some special case phase 2 packets internally * */ *************** *** 701,708 **** */ int ! gmzReply(dstNode, srcNode, dstSkt, TID) ! u_char dstNode, srcNode, dstSkt; u_short TID; { u_char len; --- 721,728 ---- */ int ! gmzReply(dstNode, srcNode, dstSkt, TID, lastFlag) ! u_char dstNode, srcNode, dstSkt, lastFlag; u_short TID; { u_char len; *************** *** 736,742 **** buf[18] = 0x00; /* Sequence no. */ buf[19] = TID >> 8; /* TID */ buf[20] = TID&0xff; /* TID */ ! buf[21] = 0x00; /* must be zero */ buf[22] = 0x00; /* must be zero */ buf[23] = 0x00; /* tuple count */ buf[24] = 0x01; /* tuple count */ --- 756,762 ---- buf[18] = 0x00; /* Sequence no. */ buf[19] = TID >> 8; /* TID */ buf[20] = TID&0xff; /* TID */ ! buf[21] = lastFlag; /* must be zero */ buf[22] = 0x00; /* must be zero */ buf[23] = 0x00; /* tuple count */ buf[24] = 0x01; /* tuple count */ *************** *** 890,896 **** thisNode = 0; thisNet = (srcNet>=rangeStart&&srcNet<=rangeEnd) ? srcNet : rangeStart; ! eth_addmulti(etfd, zaddr); /* probe for new node ID */ for (i = 253; i >= 0; i--) --- 910,916 ---- thisNode = 0; thisNet = (srcNet>=rangeStart&&srcNet<=rangeEnd) ? srcNet : rangeStart; ! eth_addmulti(etfd, interface, zaddr); /* probe for new node ID */ for (i = 253; i >= 0; i--) *************** *** 970,976 **** if (!(ddp[5] == 0 && ddp[6] == 0 && ddp[7] == 0)) return(0); TID = (ddp[2] << 8) | ddp[3]; ! gmzReply(srcNode, dNode, srcSkt, TID); return(1); /* we've replied to this */ break; default: --- 990,996 ---- if (!(ddp[5] == 0 && ddp[6] == 0 && ddp[7] == 0)) return(0); TID = (ddp[2] << 8) | ddp[3]; ! gmzReply(srcNode, dNode, srcSkt, TID, 0); return(1); /* we've replied to this */ break; default: *** filter.orig Sun Jun 21 00:43:10 1992 --- filter Tue Mar 9 14:48:24 1993 *************** *** 2,17 **** # A Remote Network Server for AppleTalk # IP Address Access Filter List # ! # + IP_ADDR permit ! # - IP_ADDR deny # # signal SIGHUP causes list to be reread # ! # arnsrd relay daemon + 127.0.0.1 ! # macs on specific subnets ! + 192.43.207.255 ! # anybody on campus + 128.250.255.255 # nobody else - 255.255.255.255 --- 2,27 ---- # A Remote Network Server for AppleTalk # IP Address Access Filter List # ! # The filter list consists of a single character mode, an IP mask and ! # optional IP address. If the latter is included, the mask is applied ! # to the incoming IP address and tested against the provided address. ! # Otherwise the incoming IP address must be unchanged by the mask. # + # Modes: + # + # * IP_MASK [ IP_ADDR ] permit access, no password required + # + IP_MASK [ IP_ADDR ] permit access, demand password + # - IP_MASK [ IP_ADDR ] deny access + # # signal SIGHUP causes list to be reread # ! # arnsrd relay daemon or localhost + 127.0.0.1 ! # any mac on a specific subnet ! + 255.255.255.0 192.43.207.0 ! # no password required for connections from ariel ! * 128.250.255.255 128.250.20.3 ! # anybody else on campus, they need a password + 128.250.255.255 # nobody else - 255.255.255.255 *** pf.c.orig Fri Nov 13 00:06:54 1992 --- pf.c Tue Mar 9 14:11:30 1993 *************** *** 13,35 **** * djh@munnari.OZ.AU * * Supports: ! * SUN Network InterFace Tap (SNITPF) * DEC ULTRIX Packet Filter (UPFILT) * Stanford Ethernet Packet Filter (ENETPF) ! * SGI IRIX SNOOP PF for promisc & Phase 2, DRAIN PF non-promisc * Sony NEWS-OS 4.N rawether (RAWETH) [Phase 1 only for 4.0] * Hewlett Packard HP-UX Link Level Access (LLAPF) * AIX Ethernet Device (AIXETH) * * $Author: djh $ ! * $Revision: 1.7 $ * */ #ifdef sun #ifndef ENETPF #ifndef BPFILT #define SNITPF #endif BPFILT #endif ENETPF #endif sun --- 13,43 ---- * djh@munnari.OZ.AU * * Supports: ! * SunOS Network InterFace Tap (SNITPF) * DEC ULTRIX Packet Filter (UPFILT) * Stanford Ethernet Packet Filter (ENETPF) ! * Solaris STREAMS Data Link Provider Interface (DLPIPF) ! * SGI IRIX SNOOP PF for promisc, DRAIN PF for non-promisc * Sony NEWS-OS 4.N rawether (RAWETH) [Phase 1 only for 4.0] * Hewlett Packard HP-UX Link Level Access (LLAPF) * AIX Ethernet Device (AIXETH) * * $Author: djh $ ! * $Revision: 1.8 $ * */ + + #ifdef SOLARIS + #define DLPIPF + #endif SOLARIS + #ifdef sun #ifndef ENETPF #ifndef BPFILT + #ifndef DLPIPF #define SNITPF + #endif DLPIPF #endif BPFILT #endif ENETPF #endif sun *************** *** 45,51 **** #endif sony_news #ifdef AIX ! #define AIXETH #endif AIX #include --- 53,59 ---- #endif sony_news #ifdef AIX ! #define AIXETH #endif AIX #include *************** *** 57,62 **** --- 65,71 ---- #include #include + #ifdef SNITPF #define DEV_NIT "/dev/nit" #include *************** *** 84,89 **** --- 93,112 ---- #include #endif UPFILT + #ifdef DLPIPF + #define MAXDLBUF 1024 + #define OFFADDR(s, n) (u_char*)((char*)(s) + (int)(n)) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #endif DLPIPF + #ifdef sgi #include #endif sgi *************** *** 107,114 **** --- 130,140 ---- #include #endif AIXETH + #ifndef SOLARIS #include #include + #endif SOLARIS + #include #include *************** *** 143,148 **** --- 169,179 ---- #define USE_SADDMULTI #endif UPFILT + #ifdef DLPIPF + #define USE_PFILT + #define USE_WRITEV + #endif DLPIPF + #ifdef sgi #define USE_WRITEV #define USE_GIFADDR *************** *** 155,167 **** #ifdef AIXETH #endif AIXETH #ifdef hpux int ethtyp; #endif hpux ! #ifdef sgi ! int ieee802 = 0; ! #endif sgi struct ifreq ifr; extern int errno; --- 186,204 ---- #ifdef AIXETH #endif AIXETH + /* + * variables + * + */ + #ifdef hpux int ethtyp; #endif hpux ! #ifdef DLPIPF ! struct strbuf dlpictl; ! long dlpibuf[MAXDLBUF]; ! #endif DLPIPF struct ifreq ifr; extern int errno; *************** *** 227,234 **** #endif UPFILT #ifdef sgi - ieee802 = (!promisc && typ == 2) ? 1 : 0; if ((s = rawopen(interface, protocol, typ)) < 0) { perror(interface); return(-1); --- 264,336 ---- #endif UPFILT + #ifdef DLPIPF + dl_attach_req_t attach_req; + dl_bind_req_t bind_req; + union DL_primitives *dlp; + struct strioctl si; + int devno = 0; + char *p; + + sprintf(device, "/dev/%s", interface); + for (p = device; *p != '\0'; p++) { + if (*p >= '0' && *p <= '9') { + devno = atoi(p); + *p = '\0'; + break; + } + } + + if ((s = open(device, mode)) < 0) { + perror(device); + return(-1); + } + + /* attach file descriptor to interface */ + attach_req.dl_primitive = DL_ATTACH_REQ; + attach_req.dl_ppa = devno; + + if (doDLPI(s, (char *)&attach_req, sizeof(attach_req), + sizeof(dl_ok_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_OK_ACK) { + fprintf(stderr, "DL_ATTACH_REQ: bad ack response\n"); + return(-1); + } + + /* label file descriptor with ethernet type */ + bind_req.dl_primitive = DL_BIND_REQ; + bind_req.dl_sap = (typ == 2) ? 0 : protocol; + bind_req.dl_max_conind = 0; + bind_req.dl_service_mode = DL_CLDLS; + bind_req.dl_conn_mgmt = 0; + bind_req.dl_xidtest_flg = 0; + + if (doDLPI(s, (char *)&bind_req, sizeof(bind_req), + sizeof(dl_bind_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_BIND_ACK) { + fprintf(stderr, "DL_BIND_REQ: bad ack response\n"); + return(-1); + } + + /* set raw mode */ + si.ic_cmd = DLIOCRAW; + si.ic_timout = -1; + si.ic_len = 0; + si.ic_dp = NULL; + if (ioctl(s, I_STR, &si) < 0) { + perror("DLIOCRAW"); + return(-1); + } + #endif DLPIPF + + #ifdef sgi if ((s = rawopen(interface, protocol, typ)) < 0) { perror(interface); return(-1); *************** *** 355,362 **** #endif UPFILT #ifdef sgi ! if (promisc || ieee802) { ioarg = 1; if (ioctl(s, SIOCSNOOPING, &ioarg) < 0) { perror("SIOCSNOOPING"); --- 457,485 ---- #endif UPFILT + #ifdef DLPIPF + if (promisc) { + dl_promiscon_req_t promiscon_req; + union DL_primitives *dlp; + + promiscon_req.dl_primitive = DL_PROMISCON_REQ; + promiscon_req.dl_level = DL_PROMISC_PHYS; + + if (doDLPI(s, (char *)&promiscon_req, sizeof(promiscon_req), + sizeof(dl_ok_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_OK_ACK) { + fprintf(stderr, "DL_PROMISCON_REQ: bad ack response\n"); + return(-1); + } + } + #endif DLPIPF + + #ifdef sgi ! if (promisc) { ioarg = 1; if (ioctl(s, SIOCSNOOPING, &ioarg) < 0) { perror("SIOCSNOOPING"); *************** *** 413,418 **** --- 536,556 ---- #endif SNITPF + #ifdef DLPIPF + struct packetfilt pf; + register u_short *fwp = pf.Pf_Filter; + struct strioctl si; + + /* + * we get type 1 "for free" with DLPI + * + */ + if (typ == 1) + return(0); + + #endif DLPIPF + + #ifdef USE_ENET struct enfilter pf; register u_short *fwp = pf.enf_Filter; *************** *** 478,483 **** --- 616,637 ---- #endif SNITPF + #ifdef DLPIPF + si.ic_cmd = PFIOCSETF; + si.ic_timout = 10; + si.ic_len = sizeof(pf); + si.ic_dp = (char *)&pf; + if (ioctl(s, I_PUSH, "pfmod") < 0) { + perror("I_PUSH"); + return(-1); + } + if (ioctl(s, I_STR, (char *)&si) < 0) { + perror("I_STR"); + return(-1); + } + #endif DLPIPF + + #ifdef USE_ENET if (ioctl(s, EIOCSETF, &pf) < 0) { perror("EIOCSETF"); *************** *** 517,523 **** struct snoopfilter sf; struct ether_header *eh; ! if (promisc || ieee802) { bzero((char *)&sf, sizeof(sf)); eh = RAW_HDR(sf.sf_mask, struct ether_header); if (typ == 2) /* EtherTalk Phase 2 */ --- 671,677 ---- struct snoopfilter sf; struct ether_header *eh; ! if (promisc) { bzero((char *)&sf, sizeof(sf)); eh = RAW_HDR(sf.sf_mask, struct ether_header); if (typ == 2) /* EtherTalk Phase 2 */ *************** *** 673,678 **** --- 827,854 ---- } #endif AIXETH + + #ifdef DLPIPF + { dl_phys_addr_req_t phys_addr_req; + union DL_primitives *dlp; + + phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ; + phys_addr_req.dl_addr_type = DL_CURR_PHYS_ADDR; + + if (doDLPI(s, (char *)&phys_addr_req, sizeof(phys_addr_req), + sizeof(dl_phys_addr_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_PHYS_ADDR_ACK) { + fprintf(stderr, "DL_PHYS_ADDR_REQ: bad ack response\n"); + return(-1); + } + + bcopy((char *)OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset), addr, 6); + } + #endif DLPIPF + return(0); } *************** *** 682,695 **** */ int ! eth_addmulti(s, addr) int s; ! char *addr; { int sock; #ifdef USE_SADDMULTI #ifdef UPFILT /* get the real interface name */ if (ioctl(s, EIOCIFNAME, &ifr) < 0) { --- 858,873 ---- */ int ! eth_addmulti(s, interface, addr) int s; ! char *interface, *addr; { int sock; #ifdef USE_SADDMULTI + strcpy(ifr.ifr_name, interface); + #ifdef UPFILT /* get the real interface name */ if (ioctl(s, EIOCIFNAME, &ifr) < 0) { *************** *** 768,777 **** --- 946,1100 ---- } #endif AIXETH + + #ifdef DLPIPF + { union DL_primitives *dlp; + + dlp = (union DL_primitives *)dlpibuf; + + dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ; + dlp->enabmulti_req.dl_addr_length = 6; + dlp->enabmulti_req.dl_addr_offset = sizeof(dl_enabmulti_req_t); + + bcopy(addr, (char *)OFFADDR(dlpibuf, sizeof(dl_enabmulti_req_t)), 6); + + if (doDLPI(s, (char *)dlpibuf, sizeof(dl_enabmulti_req_t)+6, + sizeof(dl_ok_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_OK_ACK) { + fprintf(stderr, "DL_ENABMULTI_REQ: bad ack response\n"); + return(-1); + } + } + #endif DLPIPF + return(0); } /* + * delete a multicast address from the interface + * + */ + + int + eth_delmulti(s, interface, addr) + int s; + char *interface, *addr; + { + int sock; + + #ifdef USE_SADDMULTI + + strcpy(ifr.ifr_name, interface); + + #ifdef UPFILT + /* get the real interface name */ + if (ioctl(s, EIOCIFNAME, &ifr) < 0) { + perror("EIOCIFNAME"); + return(-1); + } + #endif UPFILT + + + #ifdef ENETPF + /* get the real interface name */ + if (get_ifname(&ifr) < 0) + return(-1); + #endif ENETPF + + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy(addr, ifr.ifr_addr.sa_data, 6); + + /* + * 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, SIOCDELMULTI, (caddr_t)&ifr) < 0) { + perror("SIOCDELMULTI"); + close(sock); + return(-1); + } + close(sock); + #endif USE_SADDMULTI + + + #ifdef hpux + { struct fis fis; + + fis.vtype = 6; + fis.reqtype = DELETE_MULTICAST; + bcopy(addr, fis.value.s, 6); + if (ioctl(s, NETCTRL, &fis) < 0) { + perror("DELETE_MULTICAST"); + return(-1); + } + } + #endif hpux + + + #ifdef sony_phaseII + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket()"); + return(-1); + } + strcpy(ifr.ifr_name, IF_NAME); + bcopy(addr, ifr.ifr_addr.sa_data, 6); + + if (ioctl(sock, SIOCSMAR, &ifr) < 0) { /* ZZ */ + perror("SIOCSMAR"); /* ZZ */ + close(sock); + return(-1); + } + close(sock); + #endif /* sony_phaseII */ + + + #ifdef AIXETH + { ent_set_multi_t ent; + + ent.opcode = ENT_DEL; + bcopy(addr, ent.multi_addr, 6); + if (ioctl(s, ENT_SET_MULTI, &ent) < 0) { + perror("ENT_SET_MULTI"); + return(-1); + } + } + #endif AIXETH + + + #ifdef DLPIPF + { union DL_primitives *dlp; + + dlp = (union DL_primitives *)dlpibuf; + + dlp->disabmulti_req.dl_primitive = DL_DISABMULTI_REQ; + dlp->disabmulti_req.dl_addr_length = 6; + dlp->disabmulti_req.dl_addr_offset = sizeof(dl_disabmulti_req_t); + + bcopy(addr, (char *)OFFADDR(dlpibuf, sizeof(dl_disabmulti_req_t)), 6); + + if (doDLPI(s, (char *)dlpibuf, sizeof(dl_disabmulti_req_t)+6, + sizeof(dl_ok_ack_t)) < 0) + return(-1); + + dlp = (union DL_primitives *)dlpictl.buf; + if (dlp->dl_primitive != (u_long)DL_OK_ACK) { + fprintf(stderr, "DL_DISABMULTI_REQ: bad ack response\n"); + return(-1); + } + } + #endif DLPIPF + + return(0); + } + + /* * return 1 if ethernet interface capable of multiple opens * */ *************** *** 784,794 **** --- 1107,1124 ---- return(0); #endif sony_news + #ifdef AIXETH if (phase == 2) return(0); #endif AIXETH + + #ifdef sgi + if (phase == 2) + return(0); + #endif sgi + return(1); } *************** *** 809,815 **** char ibuf[1600]; struct snoopheader *sh; ! if (promisc || ieee802) off = sizeof(struct snoopheader)+RAW_HDRPAD(sizeof(struct ether_header)); else off = RAW_HDRPAD(sizeof(struct ether_header)); --- 1139,1145 ---- char ibuf[1600]; struct snoopheader *sh; ! if (promisc) off = sizeof(struct snoopheader)+RAW_HDRPAD(sizeof(struct ether_header)); else off = RAW_HDRPAD(sizeof(struct ether_header)); *************** *** 817,831 **** if ((cc = read(fd, ibuf, sizeof(ibuf))) <= 0) return(cc); - if (ieee802) { - sh = (struct snoopheader *)ibuf; - if (sh->snoop_flags & SN_PROMISC) - return(0); - p = (u_char *)(ibuf+off+20); - if (*p != 0x80 || (*(p+1) != 0x9b && *(p+1) != 0xf3)) - return(0); - } - if ((cc = cc - off) <= 0) return(cc); --- 1147,1152 ---- *************** *** 936,942 **** #ifdef sgi /* * NB: in non-promiscuous mode using DRAIN, we can't see typ==0 (IPTalk) - * or Phase 2 AARP packets as they don't get passed on by the kernel. * */ #define IEEE8023 1 --- 1257,1262 ---- *************** *** 950,964 **** int s; int sktsiz; int rawproto; struct sockaddr_raw sr; ! rawproto = (promisc || ieee802) ? RAWPROTO_SNOOP : RAWPROTO_DRAIN; if ((s = socket(PF_RAW, SOCK_RAW, rawproto)) < 0) { perror("socket()"); return(-1); } sr.sr_family = AF_RAW; ! if (promisc || ieee802) sr.sr_port = 0; else sr.sr_port = (typ == 2) ? IEEE8023 : htons(protocol); --- 1270,1285 ---- int s; int sktsiz; int rawproto; + struct drainmap map; struct sockaddr_raw sr; ! rawproto = (promisc) ? RAWPROTO_SNOOP : RAWPROTO_DRAIN; if ((s = socket(PF_RAW, SOCK_RAW, rawproto)) < 0) { perror("socket()"); return(-1); } sr.sr_family = AF_RAW; ! if (promisc) sr.sr_port = 0; else sr.sr_port = (typ == 2) ? IEEE8023 : htons(protocol); *************** *** 967,972 **** --- 1288,1304 ---- perror("bind()"); return(-1); } + if (rawproto == RAWPROTO_DRAIN) { + if (typ == 2) { + map.dm_minport = 10; + map.dm_maxport = 1498; + map.dm_toport = IEEE8023; + if (ioctl(s, SIOCDRAINMAP, &map) < 0) { + perror("SIOCDRAINMAP"); + return(-1); + } + } + } sktsiz = 60000; if (setsockopt(s,SOL_SOCKET,SO_RCVBUF,(char *)&sktsiz,sizeof(sktsiz)) < 0) { perror("SO_RCVBUF"); *************** *** 1086,1088 **** --- 1418,1489 ---- return(0); } #endif ENETPF + + + #ifdef DLPIPF + /* + * send message to DLPI STREAMS module and wait for a response + * + */ + + static void + sigalrm() + { + fprintf(stderr, "sigalrm(): timeout waiting for DLPI response\n"); + exit(1); + } + + int + doDLPI(s, req, reqlen, acklen) + int s; + char *req; + int reqlen, acklen; + { + int flags, rc; + + dlpictl.maxlen = 0; + dlpictl.len = reqlen; + dlpictl.buf = req; + + flags = 0; + + if (putmsg(s, &dlpictl, (struct strbuf *)NULL, flags) < 0) { + perror("putmsg()"); + return(-1); + } + + dlpictl.maxlen = MAXDLBUF; + dlpictl.buf = (char *)dlpibuf; + dlpictl.len = 0; + + flags = 0; + + (void)signal(SIGALRM, sigalrm); + + alarm(10); + + if ((rc = getmsg(s, &dlpictl, (struct strbuf *)NULL, &flags)) < 0) { + perror("getmsg()"); + exit(1); + } + + alarm(0); + + if (rc & (MORECTL | MOREDATA)) { + fprintf(stderr, "doDLPI(): extra CTL/DATA waiting for retrieval\n"); + return(-1); + } + + if (flags != RS_HIPRI) { + fprintf(stderr, "doDLPI(): expecting RS_HIPRI response\n"); + return(-1); + } + + if (dlpictl.len < acklen) { + fprintf(stderr, "doDLPI(): short response\n"); + return(-1); + } + + return(0); + } + #endif DLPIPF *** README.orig Tue Mar 9 14:22:25 1993 --- README Tue Mar 9 14:41:58 1993 *************** *** 5,11 **** The University of Melbourne djh@munnari.OZ.AU January, 1992 ! version 1.3 ARNS is 'A Remote Network Server' package for AppleTalk that allows a --- 5,11 ---- The University of Melbourne djh@munnari.OZ.AU January, 1992 ! version 1.4 ARNS is 'A Remote Network Server' package for AppleTalk that allows a