diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 6876ab21d8d2..5bd8ed57a904 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -579,6 +579,9 @@ bpfwrite(dev, uio, ioflag) 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,6 +629,8 @@ reset_d(d) * 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 @@ -822,6 +827,20 @@ bpfioctl(dev, cmd, addr, flags, p) 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; diff --git a/sys/net/bpf.h b/sys/net/bpf.h index fa5e46cc4844..64e16023542c 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -111,6 +111,8 @@ struct bpf_version { #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. diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index d87cc40b2f90..1e638f7ec9d6 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -76,6 +76,7 @@ struct bpf_d { 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 */ diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 489bcb2c3361..9d59287b81ba 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -132,8 +132,8 @@ ether_output(ifp, m0, dst, rt0) struct rtentry *rt0; { short type; - int s, error = 0; - u_char edst[6]; + 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,6 +326,12 @@ ether_output(ifp, m0, dst, rt0) } 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; @@ -350,8 +356,12 @@ ether_output(ifp, m0, dst, rt0) (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 (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 diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index 25409fdcaa98..eedc822e09d3 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -136,8 +136,8 @@ fddi_output(ifp, m0, dst, rt0) struct rtentry *rt0; { u_int16_t type; - int s, loop_copy = 0, error = 0; - u_char edst[6]; + 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,6 +295,15 @@ fddi_output(ifp, m0, dst, rt0) } 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,9 +379,12 @@ fddi_output(ifp, m0, dst, rt0) 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 (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. diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 1a68b17cc186..b1617181aa24 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -355,7 +355,7 @@ struct vfsops { #include -#define AF_MAX 31 /* XXX */ +#define AF_MAX 32 /* XXX */ /* * Network address lookup element diff --git a/sys/sys/socket.h b/sys/sys/socket.h index a7b88d464b20..430394504105 100644 --- a/sys/sys/socket.h +++ b/sys/sys/socket.h @@ -128,8 +128,11 @@ struct linger { #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 31 +#define AF_MAX 32 /* * Structure used by kernel to store most