From owner-freebsd-bugs Tue Oct 5 2:12:20 1999 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 14439152D6 for ; Tue, 5 Oct 1999 02:12:13 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id CAA69472; Tue, 5 Oct 1999 02:10:02 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Date: Tue, 5 Oct 1999 02:10:02 -0700 (PDT) Message-Id: <199910050910.CAA69472@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: "Christopher N . Harrell" Subject: Re: kern/10860: bpf overwrites source ethernet addresses when writing to a bpf descriptor Reply-To: "Christopher N . Harrell" Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR kern/10860; it has been noted by GNATS. From: "Christopher N . Harrell" To: freebsd-gnats-submit@freebsd.org Cc: imp@village.org, dima@rdy.com, security-officer@freebsd.org, pst@juniper.net, cmsedore@maxwell.syr.edu Subject: Re: kern/10860: bpf overwrites source ethernet addresses when writing to a bpf descriptor Date: Tue, 5 Oct 1999 05:04:55 -0400 I just ported the netbsd solution and added a manpage update. This solution works, and is already a bsd-ish standard. cheers, Christopher *** /usr/src/sys/net/bpf.c Sat Sep 25 14:24:29 1999 --- /usr/modsrc/net/bpf.c Tue Oct 5 03:06:24 1999 *************** *** 579,584 **** --- 579,587 ---- if (datlen > ifp->if_mtu) return (EMSGSIZE); + if (d->bd_hdrcmplt) + dst.sa_family = pseudo_AF_HDRCMPLT; + s = splnet(); #if BSD >= 199103 error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0); *************** *** 626,631 **** --- 629,636 ---- * BIOCGSTATS Get packet stats. * BIOCIMMEDIATE Set immediate mode. * BIOCVERSION Get filter language version. + * BIOCGHDRCMPLT Get "header already complete" flag + * BIOCSHDRCMPLT Set "header already complete" flag */ /* ARGSUSED */ static int *************** *** 821,826 **** --- 826,845 ---- bv->bv_minor = BPF_MINOR_VERSION; break; } + + /* + * Get "header already complete" flag + */ + case BIOCGHDRCMPLT: + *(u_int *)addr = d->bd_hdrcmplt; + break; + + /* + * Set "header already complete" flag + */ + case BIOCSHDRCMPLT: + d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0; + break; case FIONBIO: /* Non-blocking I/O */ break; *** /usr/src/sys/net/bpf.h Fri Aug 27 20:48:13 1999 --- /usr/modsrc/net/bpf.h Tue Oct 5 03:44:32 1999 *************** *** 111,116 **** --- 111,118 ---- #define BIOCVERSION _IOR('B',113, struct bpf_version) #define BIOCGRSIG _IOR('B',114, u_int) #define BIOCSRSIG _IOW('B',115, u_int) + #define BIOCGHDRCMPLT _IOR('B',116, u_int) + #define BIOCSHDRCMPLT _IOW('B',117, u_int) /* * Structure prepended to each packet. *** /usr/src/sys/net/bpfdesc.h Fri Aug 27 20:48:14 1999 --- /usr/modsrc/net/bpfdesc.h Tue Oct 5 03:02:44 1999 *************** *** 76,81 **** --- 76,82 ---- u_char bd_promisc; /* true if listening promiscuously */ u_char bd_state; /* idle, waiting, or timed out */ u_char bd_immediate; /* true to return on packet arrival */ + int bd_hdrcmplt; /* false to fill in src lladdr automatically */ int bd_async; /* non-zero if packet reception should generate signal */ int bd_sig; /* signal to send upon packet reception */ struct sigio * bd_sigio; /* information for async I/O */ *** /usr/src/sys/net/if_ethersubr.c Fri Aug 27 20:48:17 1999 --- /usr/modsrc/net/if_ethersubr.c Tue Oct 5 02:53:04 1999 *************** *** 132,139 **** struct rtentry *rt0; { short type; ! int s, error = 0; ! u_char edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; register struct ether_header *eh; --- 132,139 ---- struct rtentry *rt0; { short type; ! int s, error = 0, hdrcmplt = 0; ! u_char esrc[6], edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; register struct ether_header *eh; *************** *** 326,331 **** --- 326,337 ---- } break; #endif /* LLC */ + case pseudo_AF_HDRCMPLT: + hdrcmplt = 1; + eh = (struct ether_header *)dst->sa_data; + (void)memcpy(esrc, eh->ether_shost, sizeof (esrc)); + /* FALLTHROUGH */ + case AF_UNSPEC: loop_copy = -1; /* if this is for us, don't do it */ eh = (struct ether_header *)dst->sa_data; *************** *** 333,338 **** --- 339,345 ---- type = eh->ether_type; break; + default: printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, dst->sa_family); *************** *** 350,357 **** (void)memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); ! (void)memcpy(eh->ether_shost, ac->ac_enaddr, ! sizeof(eh->ether_shost)); /* * If a simplex interface, and the packet is being sent to our --- 357,368 ---- (void)memcpy(&eh->ether_type, &type, sizeof(eh->ether_type)); (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); ! if (hdrcmplt) ! (void)memcpy(eh->ether_shost, esrc, ! sizeof(eh->ether_shost)); ! else ! (void)memcpy(eh->ether_shost, ac->ac_enaddr, ! sizeof(eh->ether_shost)); /* * If a simplex interface, and the packet is being sent to our *** /usr/src/sys/net/if_fddisubr.c Sat Sep 25 08:05:56 1999 --- /usr/modsrc/net/if_fddisubr.c Tue Oct 5 03:22:39 1999 *************** *** 136,143 **** struct rtentry *rt0; { u_int16_t type; ! int s, loop_copy = 0, error = 0; ! u_char edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; register struct fddi_header *fh; --- 136,143 ---- struct rtentry *rt0; { u_int16_t type; ! int s, loop_copy = 0, error = 0, hdrcmplt = 0; ! u_char esrc[6], edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; register struct fddi_header *fh; *************** *** 295,300 **** --- 295,309 ---- } break; #endif /* LLC */ + case pseudo_AF_HDRCMPLT: + { + struct ether_header *eh; + hdrcmplt = 1; + eh = (struct ether_header *)dst->sa_data; + (void)memcpy((caddr_t)esrc, (caddr_t)eh->ether_shost, sizeof (esrc)); + /* FALLTHROUGH */ + } + case AF_UNSPEC: { struct ether_header *eh; *************** *** 370,378 **** fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); queue_it: ! (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, ! sizeof(fh->fddi_shost)); ! /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. --- 379,390 ---- fh->fddi_fc = FDDIFC_LLC_ASYNC|FDDIFC_LLC_PRIO4; (void)memcpy((caddr_t)fh->fddi_dhost, (caddr_t)edst, sizeof (edst)); queue_it: ! if (hdrcmplt) ! (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)esrc, ! sizeof(fh->fddi_shost)); ! else ! (void)memcpy((caddr_t)fh->fddi_shost, (caddr_t)ac->ac_enaddr, ! sizeof(fh->fddi_shost)); /* * If a simplex interface, and the packet is being sent to our * Ethernet address or a broadcast address, loopback a copy. *** /usr/src/sys/sys/mount.h Wed Sep 29 16:05:30 1999 --- /usr/modsrc/sys/mount.h Tue Oct 5 03:29:56 1999 *************** *** 355,361 **** #include ! #define AF_MAX 31 /* XXX */ /* * Network address lookup element --- 355,361 ---- #include ! #define AF_MAX 32 /* XXX */ /* * Network address lookup element *** /usr/src/sys/sys/socket.h Fri Aug 27 20:52:01 1999 --- /usr/modsrc/sys/socket.h Tue Oct 5 03:15:55 1999 *************** *** 128,135 **** #define AF_INET6 28 /* IPv6 */ #define AF_NATM 29 /* native ATM access */ #define AF_ATM 30 /* ATM */ ! #define AF_MAX 31 /* * Structure used by kernel to store most --- 128,138 ---- #define AF_INET6 28 /* IPv6 */ #define AF_NATM 29 /* native ATM access */ #define AF_ATM 30 /* ATM */ + #define pseudo_AF_HDRCMPLT 31 /* Used by BPF to not rewrite headers + * in interface output routine + */ ! #define AF_MAX 32 /* * Structure used by kernel to store most *** /usr/src/share/man/man4/bpf.4 Fri Aug 27 20:19:46 1999 --- share/man/man4/bpf.4 Tue Oct 5 04:21:42 1999 *************** *** 276,281 **** --- 276,289 ---- may result in undefined behavior (most likely, an error returned by .Fn ioctl or haphazard packet matching). + .It Dv BIOCSHDRCMPLT + .It Dv BIOCGHDRCMPLT + .Pq Li u_int + Set or get the status of the ``header complete'' flag. + Set to zero if the link level source address should be filled in automatically + by the the interface output routine. Set to one if the link level source + address will be written, as provided, to the wire. This flag is initialized + to zero by default. .Sh BPF HEADER The following structure is prepended to each packet returned by .Xr read 2 : To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message