Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Mar 2001 05:38:06 -0500 (EST)
From:      "Matthew N. Dodd" <winter@jurai.net>
To:        freebsd-tokenring@freebsd.org, freebsd-net@freebsd.org
Subject:   Token Ring and IPX.
Message-ID:  <Pine.BSF.4.21.0103090529280.54019-200000@sasami.jurai.net>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
I've got a patch against -CURRENT to get our token ring code working
against Novell 802.2 style IPX.

This patch also may enable IPv6, however additional patches (not included)
are required.

I also took the time to do some code cleanups.  :/

Anyhow, please find attached.

My test consisted of mounting a Netware share using NWFS.

# mount -a
Filesystem             1K-blocks     Used    Avail Capacity  Mounted on
...
/SEX_KITTEN:WINTER/SYS     91980    28256    63724    31%    /mnt
# cd /mnt
# du -s .
24642   .
#

Interested parties will also note that tcpdump is unable to properly
decode IPX packets over token ring; I've got a fix for this too...

-- 
| Matthew N. Dodd  | '78 Datsun 280Z | '75 Volvo 164E | FreeBSD/NetBSD  |
| winter@jurai.net |       2 x '84 Volvo 245DL        | ix86,sparc,pmax |
| http://www.jurai.net/~winter | This Space For Rent  | ISO8802.5 4ever |

[-- Attachment #2 --]
Index: if_iso88025subr.c
===================================================================
RCS file: /cvs/src/sys/net/if_iso88025subr.c,v
retrieving revision 1.14
diff -u -r1.14 if_iso88025subr.c
--- if_iso88025subr.c	2000/11/25 07:35:31	1.14
+++ if_iso88025subr.c	2001/03/09 10:18:47
@@ -41,6 +41,8 @@
  */
 
 #include "opt_inet.h"
+#include "opt_inet6.h"
+#include "opt_ipx.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -60,11 +62,19 @@
 
 #include <net/iso88025.h>
 
-#ifdef INET
+#if defined(INET) || defined(INET6)
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netinet/if_ether.h>
 #endif
+#ifdef INET6
+#include <netinet6/nd6.h>
+#endif
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
 
 #include <net/bpf.h>
 
@@ -78,6 +88,8 @@
 
 #include <net/iso88025.h>
 
+#define IFP2AC(IFP) ((struct arpcom *)IFP)
+
 void
 iso88025_ifattach(struct ifnet *ifp)
 {
@@ -103,6 +115,20 @@
         bcopy(((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);
 }
 
+/*
+ * Perform common duties while detaching a Token Ring interface
+ */
+void
+iso88025_ifdetach(ifp, bpf)
+        struct ifnet *ifp;
+        int bpf;
+{
+	if (bpf)
+                bpfdetach(ifp);
+	if_detach(ifp);
+}
+
+
 int
 iso88025_ioctl(struct ifnet *ifp, int command, caddr_t data)
 {
@@ -121,6 +147,32 @@
                         arp_ifinit((struct arpcom *)ifp, ifa);
                         break;
 #endif
+#ifdef IPX
+                /*
+                 * XXX - This code is probably wrong
+                 */
+                case AF_IPX:
+                        {
+                        register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
+                        struct arpcom *ac = IFP2AC(ifp);
+
+                        if (ipx_nullhost(*ina))
+                                ina->x_host =
+                                    *(union ipx_host *)
+                                    ac->ac_enaddr;
+                        else {
+                                bcopy((caddr_t) ina->x_host.c_host,
+                                      (caddr_t) ac->ac_enaddr,
+                                      sizeof(ac->ac_enaddr));
+                        }
+
+                        /*
+                         * Set new address
+                         */
+                        ifp->if_init(ifp->if_softc);
+                        break;
+                        }
+#endif
                 default:
                         ifp->if_init(ifp->if_softc);
                         break;
@@ -155,23 +207,27 @@
  * ISO88025 encapsulation
  */
 int
-iso88025_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt0)
+iso88025_output(ifp, m, dst, rt0)
+	struct ifnet *ifp;
+	struct mbuf *m;
+	struct sockaddr *dst;
+	struct rtentry *rt0;
 {
-	register struct iso88025_header *th;
+	u_int16_t type = 0;
+        int loop_copy = 0, error = 0, rif_len = 0;
+ 	u_char edst[ISO88025_ADDR_LEN];
+	struct iso88025_header *th;
 	struct iso88025_header gen_th;
-	register struct iso88025_sockaddr_data *sd = (struct iso88025_sockaddr_data *)dst->sa_data;
-        register struct llc *l;
-	register struct sockaddr_dl *sdl = NULL;
-        int error = 0, rif_len = 0;
- 	u_char edst[6];
-	register struct rtentry *rt;
-	int loop_copy = 0;
+	struct sockaddr_dl *sdl = NULL;
+	struct rtentry *rt;
 	struct arpcom *ac = (struct arpcom *)ifp;
 
 	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 		senderr(ENETDOWN);
+	getmicrotime(&ifp->if_lastchange);
+
 	rt = rt0;
-	if (rt) {
+	if (rt != NULL) {
 		if ((rt->rt_flags & RTF_UP) == 0) {
 			rt0 = rt = rtalloc1(dst, 1, 0UL);
 			if (rt0)
@@ -204,37 +260,61 @@
 	/* Generate a generic 802.5 header for the packet */
 	gen_th.ac = TR_AC;
 	gen_th.fc = TR_LLC_FRAME;
-	memcpy(gen_th.iso88025_shost, ac->ac_enaddr, sizeof(ac->ac_enaddr));
+	(void)memcpy((caddr_t)gen_th.iso88025_shost, (caddr_t)ac->ac_enaddr,
+		sizeof(ac->ac_enaddr));
 	if (rif_len) {
 		gen_th.iso88025_shost[0] |= TR_RII;
 		if (rif_len > 2) {
 			gen_th.rcf = sdl->sdl_rcf;
-			memcpy(gen_th.rd, sdl->sdl_route, rif_len - 2);
+			(void)memcpy((caddr_t)gen_th.rd,
+				(caddr_t)sdl->sdl_route, rif_len - 2);
 		}
 	}
 	
-
 	switch (dst->sa_family) {
 #ifdef INET
 	case AF_INET:
 		if (!arpresolve(ac, rt, m, dst, edst, rt0))
 			return (0);	/* if not yet resolved */
-		/* Add LLC and SNAP headers */
-		M_PREPEND(m, 8, M_DONTWAIT);
-		if (m == 0)
-			senderr(ENOBUFS);
-		l = mtod(m, struct llc *);
-	        l->llc_un.type_snap.ether_type = htons(ETHERTYPE_IP);
-	        l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
-		l->llc_un.type_snap.control = LLC_UI;
-		l->llc_un.type_snap.org_code[0] = 0x0;
-		l->llc_un.type_snap.org_code[1] = 0x0;
-		l->llc_un.type_snap.org_code[2] = 0x0;
-		memcpy(gen_th.iso88025_dhost, edst, sizeof(edst));
+		type = ETHERTYPE_IP;
+		break;
+#endif
+#ifdef INET6
+	case AF_INET6:
+		if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
+			/* this must be impossible, so we bark */
+			printf("nd6_storelladdr failed\n");
+			return(0);
+		}
+		type = ETHERTYPE_IPV6;
 		break;
 #endif
+#ifdef IPX
+	case AF_IPX:
+	{
+		u_int8_t	*cp;
 
+		type = 0;
+		bcopy((caddr_t)&(satoipx_addr(dst).x_host), (caddr_t)edst,
+			sizeof (edst));
+/* &(((struct sockaddr_ipx *)dst)->sipx_addr.x_host), */
+
+		M_PREPEND(m, 3, M_TRYWAIT);
+		if (m == 0)
+			senderr(ENOBUFS);
+		m = m_pullup(m, 3);
+		if (m == 0)
+			senderr(ENOBUFS);
+		cp = mtod(m, u_int8_t *);
+		*cp++ = ETHERTYPE_IPX_8022;
+		*cp++ = ETHERTYPE_IPX_8022;
+		*cp++ = 0x03;
+	}
+	break;
+#endif
 	case AF_UNSPEC:
+	{
+		struct iso88025_sockaddr_data *sd;
 		/*
 		 * For AF_UNSPEC sockaddr.sa_data must contain all of the
 		 * mac information needed to send the packet.  This allows
@@ -247,26 +327,45 @@
 		sd = (struct iso88025_sockaddr_data *)dst->sa_data;
 		gen_th.ac = sd->ac;
 		gen_th.fc = sd->fc;
-		memcpy(gen_th.iso88025_dhost, sd->ether_dhost, sizeof(sd->ether_dhost));
-		memcpy(gen_th.iso88025_shost, sd->ether_shost, sizeof(sd->ether_shost));
+		(void)memcpy((caddr_t)edst, (caddr_t)sd->ether_dhost,
+			sizeof(sd->ether_dhost));
+		(void)memcpy((caddr_t)gen_th.iso88025_shost,
+			(caddr_t)sd->ether_shost, sizeof(sd->ether_shost));
 		rif_len = 0;
 		break;
-
+	}
 	default:
 		printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
 			dst->sa_family);
 		senderr(EAFNOSUPPORT);
+		break;
 	}
 
+	if (type != 0) {
+        	struct llc *l;
+		M_PREPEND(m, sizeof (struct llc), M_DONTWAIT);
+		if (m == 0)
+			senderr(ENOBUFS);
+		l = mtod(m, struct llc *);
+		l->llc_un.type_snap.ether_type = htons(type);
+		l->llc_dsap = l->llc_ssap = LLC_SNAP_LSAP;
+		l->llc_un.type_snap.control = LLC_UI;
+		l->llc_un.type_snap.org_code[0] =
+			l->llc_un.type_snap.org_code[1] =
+			l->llc_un.type_snap.org_code[2] = 0;
+	}
+
 	/*
 	 * Add local net header.  If no space in first mbuf,
 	 * allocate another.
 	 */
-	
 	M_PREPEND(m, ISO88025_HDR_LEN + rif_len, M_DONTWAIT);
 	if (m == 0)
 		senderr(ENOBUFS);
 
+	(void)memcpy((caddr_t)&gen_th.iso88025_dhost, (caddr_t)edst,
+		     sizeof(edst));
+
 	/* Copy as much of the generic header as is needed into the mbuf */
 	th = mtod(m, struct iso88025_header *);
 	memcpy(th, &gen_th, ISO88025_HDR_LEN + rif_len);
@@ -280,21 +379,22 @@
          * on the wire). However, we don't do that here for security
          * reasons and compatibility with the original behavior.
          */     
-        if ((ifp->if_flags & IFF_SIMPLEX) &&
-           (loop_copy != -1)) {
+        if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
                 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 
-                        struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
-                        (void) if_simloop(ifp,
-			    n, dst->sa_family, ISO88025_HDR_LEN);
-                } else if (bcmp(th->iso88025_dhost,
-                    th->iso88025_shost, ETHER_ADDR_LEN) == 0) {
-                        (void) if_simloop(ifp,
-			    m, dst->sa_family, ISO88025_HDR_LEN);
-                        return(0);      /* XXX */
-                }       
+                        struct mbuf *n;
+			n = m_copy(m, 0, (int)M_COPYALL);
+                        (void)if_simloop(ifp, n, dst->sa_family,
+					  ISO88025_HDR_LEN);
+                } else
+			if (bcmp(th->iso88025_dhost, th->iso88025_shost,
+				 ETHER_ADDR_LEN) == 0) {
+				(void)if_simloop(ifp, m, dst->sa_family,
+						 ISO88025_HDR_LEN);
+                        	return(0);      /* XXX */
+			}       
         }      
 
-	if (! IF_HANDOFF_ADJ(&ifp->if_snd, m, ifp, ISO88025_HDR_LEN + 8)) {
+	if (! IF_HANDOFF_ADJ(&ifp->if_snd, m, ifp, ISO88025_HDR_LEN + (sizeof(struct llc))) ) {
 		printf("iso88025_output: packet dropped QFULL.\n");
 		senderr(ENOBUFS);
 	}
@@ -310,92 +410,151 @@
  * ISO 88025 de-encapsulation
  */
 void
-iso88025_input(struct ifnet *ifp, struct iso88025_header *th, struct mbuf *m)
+iso88025_input(ifp, th, m)
+	struct ifnet *ifp;
+	struct iso88025_header *th;
+	struct mbuf *m;
 {
 	register struct ifqueue *inq;
-	u_short ether_type;
-	register struct llc *l = mtod(m, struct llc *);
+	register struct llc *l;
 
 	if ((ifp->if_flags & IFF_UP) == 0) {
 		m_freem(m);
 		return;
 	}
 
-	switch (l->llc_control) {
-	case LLC_UI:
-		break;
-	case LLC_TEST:
-	case LLC_TEST_P:
-	{
-		struct sockaddr sa;
-		struct arpcom *ac = (struct arpcom *)ifp;
-		struct iso88025_sockaddr_data *th2;
-		int i;
-		u_char c = l->llc_dsap;
-
-		if (th->iso88025_shost[0] & TR_RII) { /* XXX */
-			printf("iso88025_input: dropping source routed LLC_TEST\n");
-			m_free(m);
-			return;
-		}
-		l->llc_dsap = l->llc_ssap;
-		l->llc_ssap = c;
-		if (m->m_flags & (M_BCAST | M_MCAST))
-			bcopy((caddr_t)ac->ac_enaddr, 
-			      (caddr_t)th->iso88025_dhost, ISO88025_ADDR_LEN);
-		sa.sa_family = AF_UNSPEC;
-		sa.sa_len = sizeof(sa);
-		th2 = (struct iso88025_sockaddr_data *)sa.sa_data;
-		for (i = 0; i < ISO88025_ADDR_LEN; i++) {
-			th2->ether_shost[i] = c = th->iso88025_dhost[i];
-			th2->ether_dhost[i] = th->iso88025_dhost[i] = th->iso88025_shost[i];
-			th->iso88025_shost[i] = c;
-		}
-		th2->ac = TR_AC;
-		th2->fc = TR_LLC_FRAME;
-		ifp->if_output(ifp, m, &sa, NULL);
-		return;
-	}
-	default:
-		printf("iso88025_input: unexpected llc control 0x%02x\n", l->llc_control);
-		m_freem(m);
-		return;
-	}
-
-        m->m_pkthdr.len -= 8;
-        m->m_len -= 8;
-        m->m_data += 8; /* Length of LLC header in our case */
-
+	getmicrotime(&ifp->if_lastchange);
 	ifp->if_ibytes += m->m_pkthdr.len + sizeof(*th);
+
 	if (th->iso88025_dhost[0] & 1) {
-		if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)th->iso88025_dhost, sizeof(etherbroadcastaddr)) == 0)
+		if (bcmp((caddr_t)etherbroadcastaddr,
+			 (caddr_t)th->iso88025_dhost,
+			 sizeof(etherbroadcastaddr)) == 0)
 			m->m_flags |= M_BCAST;
 		else
 			m->m_flags |= M_MCAST;
-	} 
-	if (m->m_flags & (M_BCAST|M_MCAST))
 		ifp->if_imcasts++;
+	} 
 
-	ether_type = ntohs(l->llc_un.type_snap.ether_type);
+	l = mtod(m, struct llc *);
 
-	switch (ether_type) {
-#ifdef INET
-	case ETHERTYPE_IP:
+	switch (l->llc_dsap) {
+#ifdef IPX
+	case ETHERTYPE_IPX_8022:	/* Thanks a bunch Novell */
+		if (l->llc_ssap != ETHERTYPE_IPX_8022)
+			goto dropanyway;
 		th->iso88025_shost[0] &= ~(TR_RII); 
-		if (ipflow_fastforward(m))
-			return;
-		schednetisr(NETISR_IP);
-		inq = &ipintrq;
+		m_adj(m, 3);
+		schednetisr(NETISR_IPX);
+		inq = &ipxintrq;
 		break;
-
-	case ETHERTYPE_ARP:
-		schednetisr(NETISR_ARP);
-		inq = &arpintrq;
-                break;
 #endif
+	case LLC_SNAP_LSAP: {
+		u_int16_t type;
+		if (l->llc_control != LLC_UI || l->llc_ssap != LLC_SNAP_LSAP)
+			goto dropanyway;
+		if (l->llc_un.type_snap.org_code[0] != 0 ||
+		    l->llc_un.type_snap.org_code[1] != 0 ||
+		    l->llc_un.type_snap.org_code[2] != 0)
+			goto dropanyway;
+		type = ntohs(l->llc_un.type_snap.ether_type);
+		m_adj(m, sizeof(struct llc));
+		switch (type) {
+#ifdef INET
+		case ETHERTYPE_IP:
+			th->iso88025_shost[0] &= ~(TR_RII); 
+			if (ipflow_fastforward(m))
+				return;
+			schednetisr(NETISR_IP);
+			inq = &ipintrq;
+			break;
+
+		case ETHERTYPE_ARP:
+			schednetisr(NETISR_ARP);
+			inq = &arpintrq;
+			break;
+#endif
+#ifdef IPX	/* XXX: this, I think, is bogus. */
+		case ETHERTYPE_IPX:
+			th->iso88025_shost[0] &= ~(TR_RII); 
+			schednetisr(NETISR_IPX);
+			inq = &ipxintrq;
+			break;
+#endif
+#ifdef INET6
+		case ETHERTYPE_IPV6:
+			th->iso88025_shost[0] &= ~(TR_RII); 
+			schednetisr(NETISR_IPV6);
+			inq = &ip6intrq;
+			break;
+#endif
+		default:
+			printf("iso88025_input: unexpected llc_snap ether_type  0x%02x\n", type);
+			m_freem(m);
+			return;
+		}
+		break;
+	}
+	case LLC_ISO_LSAP:
+		switch (l->llc_control) {
+		case LLC_UI:
+			goto dropanyway;
+			break;
+                case LLC_XID:
+                case LLC_XID_P:
+			if(m->m_len < ISO88025_ADDR_LEN)
+				goto dropanyway;
+			l->llc_window = 0;
+			l->llc_fid = 9;  
+			l->llc_class = 1;
+			l->llc_dsap = l->llc_ssap = 0;
+			/* Fall through to */  
+		case LLC_TEST:
+		case LLC_TEST_P:
+		{
+			struct sockaddr sa;
+			struct arpcom *ac = (struct arpcom *)ifp;
+			struct iso88025_sockaddr_data *th2;
+			int i;
+			u_char c = l->llc_dsap;
+
+			if (th->iso88025_shost[0] & TR_RII) { /* XXX */
+				printf("iso88025_input: dropping source routed LLC_TEST\n");
+				m_free(m);
+				return;
+			}
+			l->llc_dsap = l->llc_ssap;
+			l->llc_ssap = c;
+			if (m->m_flags & (M_BCAST | M_MCAST))
+				bcopy((caddr_t)ac->ac_enaddr, 
+			      		(caddr_t)th->iso88025_dhost,
+					ISO88025_ADDR_LEN);
+			sa.sa_family = AF_UNSPEC;
+			sa.sa_len = sizeof(sa);
+			th2 = (struct iso88025_sockaddr_data *)sa.sa_data;
+			for (i = 0; i < ISO88025_ADDR_LEN; i++) {
+				th2->ether_shost[i] = c = th->iso88025_dhost[i];
+				th2->ether_dhost[i] = th->iso88025_dhost[i] =
+					th->iso88025_shost[i];
+				th->iso88025_shost[i] = c;
+			}
+			th2->ac = TR_AC;
+			th2->fc = TR_LLC_FRAME;
+			ifp->if_output(ifp, m, &sa, NULL);
+			return;
+		}
+		default:
+			printf("iso88025_input: unexpected llc control 0x%02x\n", l->llc_control);
+			m_freem(m);
+			return;
+		}
+		break;
 	default:
-	    m_freem(m);
-	    return;
+		printf("iso88025_input: unknown dsap 0x%x\n", l->llc_dsap);
+		ifp->if_noproto++;
+	dropanyway:
+		m_freem(m);
+		return;
 	}
 
 	if (! IF_HANDOFF(inq, m, NULL))
Index: iso88025.h
===================================================================
RCS file: /cvs/src/sys/net/iso88025.h,v
retrieving revision 1.4
diff -u -r1.4 iso88025.h
--- iso88025.h	2000/03/19 21:34:37	1.4
+++ iso88025.h	2001/03/08 02:01:43
@@ -75,6 +75,8 @@
  * Minimum and maximum packet payload lengths.
  */
 #define	ISO88025_MIN_LEN	0 
+#define ISO88025_MAX_LEN_4	4464
+#define	ISO88025_MAX_LEN_16	17960	
 #define	ISO88025_MAX_LEN	17960	
 
 /*
@@ -87,13 +89,18 @@
  * ISO 802.5 physical header
  */
 struct iso88025_header {
-	u_char	ac;				    /* access control field */
-	u_char	fc;				    /* frame control field */
-	u_char	iso88025_dhost[ISO88025_ADDR_LEN];  /* destination address */
-	u_char	iso88025_shost[ISO88025_ADDR_LEN];  /* source address */
-	u_short	rcf;				    /* route control field */
-	u_short	rd[RIF_MAX_RD];			    /* routing designators */
-};
+	u_int8_t	ac;				    /* access control field */
+	u_int8_t	fc;				    /* frame control field */
+	u_int8_t	iso88025_dhost[ISO88025_ADDR_LEN];  /* destination address */
+	u_int8_t	iso88025_shost[ISO88025_ADDR_LEN];  /* source address */
+	u_int16_t	rcf;				    /* route control field */
+	u_int16_t	rd[RIF_MAX_RD];			    /* routing designators */
+} __attribute__ ((__packed__));
+
+struct iso88025_rif {
+	u_int16_t	rcf;				    /* route control field */
+	u_int16_t	rd[RIF_MAX_RD];			    /* routing designators */
+} __attribute__ ((__packed__));
 
 struct iso88025_sockaddr_data {
 	u_char ether_dhost[ISO88025_ADDR_LEN];
Index: if_llc.h
===================================================================
RCS file: /cvs/src/sys/net/if_llc.h,v
retrieving revision 1.7
diff -u -r1.7 if_llc.h
--- if_llc.h	1999/08/28 00:48:18	1.7
+++ if_llc.h	2001/03/09 09:14:03
@@ -46,44 +46,45 @@
  */
 
 struct llc {
-	u_char	llc_dsap;
-	u_char	llc_ssap;
+	u_int8_t	llc_dsap;
+	u_int8_t	llc_ssap;
 	union {
 	    struct {
-		u_char control;
-		u_char format_id;
-		u_char class;
-		u_char window_x2;
-	    } type_u;
-	    struct {
-		u_char num_snd_x2;
-		u_char num_rcv_x2;
-	    } type_i;
-	    struct {
-		u_char control;
-		u_char num_rcv_x2;
-	    } type_s;
+		u_int8_t control;
+		u_int8_t format_id;
+		u_int8_t class;
+		u_int8_t window_x2;
+	    } type_u __attribute__((__packed__));
+	    struct {
+		u_int8_t num_snd_x2;
+		u_int8_t num_rcv_x2;
+	    } type_i __attribute__((__packed__));
+	    struct {
+		u_int8_t control;
+		u_int8_t num_rcv_x2;
+	    } type_s __attribute__((__packed__));
 	    struct {
-	        u_char control;
+	        u_int8_t control;
 		struct frmrinfo {
-			u_char rej_pdu_0;
-			u_char rej_pdu_1;
-			u_char frmr_control;
-			u_char frmr_control_ext;
-			u_char frmr_cause;
-		} frmrinfo;
-	    } type_frmr;
+			u_int8_t rej_pdu_0;
+			u_int8_t rej_pdu_1;
+			u_int8_t frmr_control;
+			u_int8_t frmr_control_ext;
+			u_int8_t frmr_cause;
+		} frmrinfo __attribute__((__packed__));
+	    } type_frmr __attribute__((__packed__));
 	    struct {
-		u_char control;
-		u_char org_code[3];
+		u_int8_t control;
+		u_int8_t org_code[3];
 		u_short ether_type;
-	    } type_snap;
+	    } type_snap __attribute__((__packed__));
 	    struct {
-		u_char control;
-		u_char control_ext;
-	    } type_raw;
-	} llc_un;
-};
+		u_int8_t control;
+		u_int8_t control_ext;
+	    } type_raw __attribute__((__packed__));
+	} llc_un __attribute__((__packed__));
+} __attribute__((__packed__));
+
 #define llc_control            llc_un.type_u.control
 #define	llc_control_ext        llc_un.type_raw.control_ext
 #define llc_fid                llc_un.type_u.format_id
@@ -102,6 +103,8 @@
 #define LLC_ISFRAMELEN 4
 #define LLC_UFRAMELEN  3
 #define LLC_FRMRLEN    7
+#define LLC_SNAPFRAMELEN 8
+
 
 /*
  * Unnumbered LLC format commands

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0103090529280.54019-200000>