home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.unix.bsd
- Path: sparky!uunet!news.univie.ac.at!news.tu-graz.ac.at!fstgds01!chmr
- From: chmr@fstgds01.tu-graz.ac.at (Christoph Robitschko)
- Subject: [386bsd] correct handling of trailers in if_we.c (PATCH)
- Message-ID: <1992Dec16.100515.11198@news.tu-graz.ac.at>
- Sender: news@news.tu-graz.ac.at (USENET News System)
- Nntp-Posting-Host: fstgds01
- Organization: Technical University of Graz, Austria
- Date: Wed, 16 Dec 92 10:05:15 GMT
- Lines: 170
-
-
- My machine crashed with a type 12 trap when ftping to a local workstation.
- This problem was not easy to fix, because there were three bugs:
-
- First, there was a calculation of the start address of the (trailing)
- header of a packet, without checking if this address was inside the
- ethernet card ring buffer. That caused the length parameter to a bcopy
- call to become negative -- crash.
-
- Second, the length of the packet was read from the ethernet card
- memory as a short. This did not work, but to assemble it from two
- bytes does work (??). I think the compiler was generating bad code.
- Anyway, that caused the header offset to become bigger that the length
- of the packet, same symptoms as above.
-
- Third, the length of trailer packets was truncated by sizeof(ether_header),
- which caused the packet to be dropped.
-
- But finally, I have fixed these problems in the if_we driver. I don't know
- if the peoblems exist in other ethernet drivers, if you have used
- if_we.c as a porting base, you will want to check.
-
- Christoph
-
- Here's the patch:
- *** /sys/i386/isa/if_we.c.patchkit58 Wed Dec 16 10:26:17 1992
- --- /sys/i386/isa/if_we.c Wed Dec 16 10:25:18 1992
- ***************
- *** 55,60 ****
- --- 55,63 ----
- * Allowed interupt handler to look at unit other than 0
- * Bdry was static, made it into an array w/ one entry per
- * interface. nerd@percival.rain.com (Michael Galassi)
- + *
- + * 15.12.92 - fixed trailer handling in weread() and weget()
- + * chmr@edvz.tu-graz.ac.at (Christoph Robitschko)
- */
-
- #include "we.h"
- *************** werint(unit)
- *** 572,578 ****
- if (len > 30 && len <= ETHERMTU+100
- /*&& (*(char *)wer == 1 || *(char *) wer == 0x21)*/)
- weread(sc, (caddr_t)(wer + 1), len);
- ! else printf("reject %d", len);
-
- outofbufs:
- wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
- --- 575,581 ----
- if (len > 30 && len <= ETHERMTU+100
- /*&& (*(char *)wer == 1 || *(char *) wer == 0x21)*/)
- weread(sc, (caddr_t)(wer + 1), len);
- ! else printf("we%d: rejected packet with bogus len %d", unit, len);
-
- outofbufs:
- wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
- *************** wesetaddr(physaddr, unit)
- *** 709,714 ****
- --- 712,718 ----
- (((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \
- + (sc)->we_vmem_ring: \
- ((caddr_t)((eh)+1)+(off)))
- +
- /*
- * Pass a packet to the higher levels.
- * We deal with the trailer protocol here.
- *************** weread(sc, buf, len)
- *** 720,726 ****
- {
- register struct ether_header *eh;
- struct mbuf *m, *weget();
- ! int off, resid;
-
- /*
- * Deal with trailer protocol: if type is trailer type
- --- 724,730 ----
- {
- register struct ether_header *eh;
- struct mbuf *m, *weget();
- ! int off;
-
- /*
- * Deal with trailer protocol: if type is trailer type
- *************** weread(sc, buf, len)
- *** 731,750 ****
- eh->ether_type = ntohs((u_short)eh->ether_type);
- if (eh->ether_type >= ETHERTYPE_TRAIL &&
- eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
- off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
- if (off >= ETHERMTU) return; /* sanity */
- ! eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *));
- ! resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *)));
- if (off + resid > len) return; /* sanity */
- len = off + resid;
- ! } else off = 0;
- !
- ! len -= sizeof(struct ether_header);
- if (len <= 0) return;
-
- /*
- * Pull packet off interface. Off is nonzero if packet
- ! * has trailing header; neget will then force this header
- * information to be at the front, but we still have to drop
- * the type and length which are at the front of any trailer data.
- */
- --- 735,761 ----
- eh->ether_type = ntohs((u_short)eh->ether_type);
- if (eh->ether_type >= ETHERTYPE_TRAIL &&
- eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
- + caddr_t trailhead;
- + int resid;
- +
- off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
- if (off >= ETHERMTU) return; /* sanity */
- ! /* eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *)); */
- ! /* resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *))); */
- ! trailhead = wedataaddr(sc, eh, off, caddr_t);
- ! eh->ether_type = trailhead[0] * 256 + trailhead[1];
- ! resid = trailhead[2] * 256 + trailhead[3];
- if (off + resid > len) return; /* sanity */
- len = off + resid;
- ! } else {
- ! off = 0;
- ! len -= sizeof(struct ether_header);
- ! }
- if (len <= 0) return;
-
- /*
- * Pull packet off interface. Off is nonzero if packet
- ! * has trailing header; weget will then force this header
- * information to be at the front, but we still have to drop
- * the type and length which are at the front of any trailer data.
- */
- *************** weget(buf, totlen, off0, ifp, sc)
- *** 828,840 ****
- totlen -= len;
- /* only do up to end of buffer */
- if (cp+len > sc->we_vmem_end) {
- ! unsigned toend = sc->we_vmem_end - cp;
-
- - bcopy(cp, mtod(m, caddr_t), toend);
- - cp = sc->we_vmem_ring;
- bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
- cp += len - toend;
- - epkt = cp + totlen;
- } else {
- bcopy(cp, mtod(m, caddr_t), (unsigned)len);
- cp += len;
- --- 839,855 ----
- totlen -= len;
- /* only do up to end of buffer */
- if (cp+len > sc->we_vmem_end) {
- ! long toend = sc->we_vmem_end - cp;
- !
- ! if (toend > 0)
- ! bcopy(cp, mtod(m, caddr_t), toend);
- ! else
- ! toend = 0;
- ! cp -= (sc->we_vmem_end - sc->we_vmem_ring);
- ! epkt -= (sc->we_vmem_end - sc->we_vmem_ring);
-
- bcopy(cp, mtod(m, caddr_t)+toend, len - toend);
- cp += len - toend;
- } else {
- bcopy(cp, mtod(m, caddr_t), (unsigned)len);
- cp += len;
-
- --- End of patch ---
- --
- .signature: Too many levels of symbolic links
-