* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)if_ethersubr.c 1.1 (Berkeley) %G%
#include "../machine/mtpr.h"
#include "../netinet/in.h"
#include "../netinet/in_var.h"
#include "../netinet/if_ether.h"
#include "../netns/ns_if.h"
u_char etherbroadcastaddr
[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
* Assumes that ifp is actually pointer to arpcom structure.
register struct ifnet
*ifp
;
register struct mbuf
*m
= m0
;
register struct ether_header
*eh
;
#define ac ((struct arpcom *)ifp)
if ((ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) != (IFF_UP
|IFF_RUNNING
)) {
switch (dst
->sa_family
) {
idst
= ((struct sockaddr_in
*)dst
)->sin_addr
;
if (!arpresolve(ac
, m
, &idst
, edst
, &usetrailers
))
return (0); /* if not yet resolved */
off
= m
->m_pkthdr
.len
- m
->m_len
;
if (usetrailers
&& off
> 0 && (off
& 0x1ff) == 0 &&
(m
->m_flags
& M_EXT
) == 0 &&
m
->m_data
>= m
->m_pktdat
+ 2 * sizeof (u_short
)) {
type
= ETHERTYPE_TRAIL
+ (off
>>9);
m
->m_data
-= 2 * sizeof (u_short
);
m
->m_len
+= 2 * sizeof (u_short
);
*mtod(m
, u_short
*) = htons((u_short
)ETHERTYPE_IP
);
*(mtod(m
, u_short
*) + 1) = htons((u_short
)m
->m_len
);
bcopy((caddr_t
)&(((struct sockaddr_ns
*)dst
)->sns_addr
.x_host
),
(caddr_t
)edst
, sizeof (edst
));
eh
= (struct ether_header
*)dst
->sa_data
;
bcopy((caddr_t
)eh
->ether_dhost
, (caddr_t
)edst
, sizeof (edst
));
printf("%s%d: can't handle af%d\n", ifp
->if_name
, ifp
->if_unit
,
* Packet to be sent as trailer: move first packet
* (control information) to end of chain.
* Add local net header. If no space in first mbuf,
M_PREPEND(m
, sizeof (struct ether_header
), M_DONTWAIT
);
eh
= mtod(m
, struct ether_header
*);
eh
->ether_type
= htons((u_short
)type
);
bcopy((caddr_t
)edst
, (caddr_t
)eh
->ether_dhost
, sizeof (edst
));
bcopy((caddr_t
)ac
->ac_enaddr
, (caddr_t
)eh
->ether_shost
,
sizeof(eh
->ether_shost
));
* Queue message on interface, and start output if interface
if (IF_QFULL(&ifp
->if_snd
)) {
IF_ENQUEUE(&ifp
->if_snd
, m
);
if ((ifp
->if_flags
& IFF_OACTIVE
) == 0)
(*ifp
->if_start
)(ifp
->if_unit
);
* Pull packet off interface. Off is nonzero if packet
* has trailing header; we still have to drop
* the type and length which are at the front of any trailer data.
register struct ether_header
*eh
;
register struct ifqueue
*inq
;
if (bcmp((caddr_t
)etherbroadcastaddr
, (caddr_t
)eh
->ether_shost
,
sizeof(etherbroadcastaddr
)) == 0)
switch (eh
->ether_type
) {
arpinput((struct arpcom
*)ifp
, m
);
* Convert Ethernet address to printable (loggable) representation.
static char etherbuf
[18];
register char *cp
= etherbuf
;
static char digits
[] = "0123456789abcdef";
for (i
= 0; i
< 6; i
++) {
*cp
++ = digits
[*ap
>> 4];
*cp
++ = digits
[*ap
++ & 0xf];