diff options
author | kbyanc <kbyanc@FreeBSD.org> | 2002-05-07 22:14:06 +0000 |
---|---|---|
committer | kbyanc <kbyanc@FreeBSD.org> | 2002-05-07 22:14:06 +0000 |
commit | cc607e6c2d164e9cb79d2fdec151a8c3a151be83 (patch) | |
tree | 1011805115056aee5a327edbdc2edbd88f8dd3e5 /sys | |
parent | 890d39a38cddebc8d4ce58feba2c0be1ee5e44f6 (diff) | |
download | FreeBSD-src-cc607e6c2d164e9cb79d2fdec151a8c3a151be83.zip FreeBSD-src-cc607e6c2d164e9cb79d2fdec151a8c3a151be83.tar.gz |
Move ISO88025 source routing information into sockaddr_dl's sdl_data
field. This returns the sdl_data field to a variable-length field. More
importantly, this prevents a easily-reproduceable data-corruption bug when
the interface name plus the hardware address exceed the sdl_data field's
original 12 byte limit. However, token-ring interfaces may still overflow
the new sdl_data field's 46 byte limit if the interface name exceeds 6
characters (since 6 characters for interface name plus 6 for hardware
address plus 34 for source routing = the size of sdl_data). Further
refinements could overcome this limitation but would break binary
compatibility; this commit only addresses fixing the bug for
commonly-occuring cases without breaking binary compatibility with the
intention that the functionality can be MFC'ed to -stable.
See message ID's (both send to -arch):
20020421013332.F87395-100000@gateway.posi.net
20020430181359.G11009-300000@gateway.posi.net
for a more thorough description of the bug addressed and how to
reproduce it.
Approved by: silence on -arch and -net
Sponsored by: NTT Multimedia Communications Labs
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_dl.h | 4 | ||||
-rw-r--r-- | sys/net/if_iso88025subr.c | 9 | ||||
-rw-r--r-- | sys/net/iso88025.h | 9 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 15 |
4 files changed, 22 insertions, 15 deletions
diff --git a/sys/net/if_dl.h b/sys/net/if_dl.h index 2eb33dc..b9980bb 100644 --- a/sys/net/if_dl.h +++ b/sys/net/if_dl.h @@ -66,10 +66,8 @@ struct sockaddr_dl { u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */ u_char sdl_alen; /* link level address length */ u_char sdl_slen; /* link layer selector length */ - char sdl_data[12]; /* minimum work area, can be larger; + char sdl_data[46]; /* minimum work area, can be larger; contains both if name and ll address */ - u_short sdl_rcf; /* source routing control */ - u_short sdl_route[16]; /* source routing information */ }; #define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index f23f5ee..afb6f4e 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -253,8 +253,8 @@ iso88025_output(ifp, m, dst, rt0) /* Calculate routing info length based on arp table entry */ if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway)) - if (sdl->sdl_rcf != NULL) - rif_len = TR_RCF_RIFLEN(sdl->sdl_rcf); + if (SDL_ISO88025(sdl)->trld_rcf != NULL) + rif_len = TR_RCF_RIFLEN(SDL_ISO88025(sdl)->trld_rcf); /* Generate a generic 802.5 header for the packet */ gen_th.ac = TR_AC; @@ -264,9 +264,10 @@ iso88025_output(ifp, m, dst, rt0) if (rif_len) { gen_th.iso88025_shost[0] |= TR_RII; if (rif_len > 2) { - gen_th.rcf = sdl->sdl_rcf; + gen_th.rcf = SDL_ISO88025(sdl)->trld_rcf; (void)memcpy((caddr_t)gen_th.rd, - (caddr_t)sdl->sdl_route, rif_len - 2); + (caddr_t)SDL_ISO88025(sdl)->trld_route, + rif_len - 2); } } diff --git a/sys/net/iso88025.h b/sys/net/iso88025.h index e30193e..aad8d54 100644 --- a/sys/net/iso88025.h +++ b/sys/net/iso88025.h @@ -109,6 +109,15 @@ struct iso88025_sockaddr_data { u_char fc; }; +struct iso88025_sockaddr_dl_data { + u_short trld_rcf; + u_short *trld_route[RIF_MAX_LEN]; +}; + +#define SDL_ISO88025(s) ((struct iso88025_sockaddr_dl_data *) \ + ((s)->sdl_data + min((s)->sdl_nlen + \ + (s)->sdl_alen + (s)->sdl_slen, 12))) + /* * Structure of a 48-bit iso 802.5 address. * ( We could also add the 16 bit addresses as a union) diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 6a87a5e..6c8b75a 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -571,6 +571,7 @@ in_arpinput(m) struct ether_header *eh; struct arc_header *arh; struct iso88025_header *th = (struct iso88025_header *)0; + struct iso88025_sockaddr_dl_data *trld; register struct llinfo_arp *la = 0; register struct rtentry *rt; struct ifaddr *ifa; @@ -697,7 +698,6 @@ match: } (void)memcpy(LLADDR(sdl), ar_sha(ah), sdl->sdl_alen = ah->ar_hln); - sdl->sdl_rcf = (u_short)0; /* * If we receive an arp from a token-ring station over * a token-ring nic then try to save the source @@ -705,13 +705,14 @@ match: */ if (ifp->if_type == IFT_ISO88025) { th = (struct iso88025_header *)m->m_pkthdr.header; + trld = SDL_ISO88025(sdl); rif_len = TR_RCF_RIFLEN(th->rcf); if ((th->iso88025_shost[0] & TR_RII) && (rif_len > 2)) { - sdl->sdl_rcf = th->rcf; - sdl->sdl_rcf ^= htons(TR_RCF_DIR); - memcpy(sdl->sdl_route, th->rd, rif_len - 2); - sdl->sdl_rcf &= ~htons(TR_RCF_BCST_MASK); + trld->trld_rcf = th->rcf; + trld->trld_rcf ^= htons(TR_RCF_DIR); + memcpy(trld->trld_route, th->rd, rif_len - 2); + trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK); /* * Set up source routing information for * reply packet (XXX) @@ -725,9 +726,7 @@ match: m->m_data -= 8; m->m_len += 8; m->m_pkthdr.len += 8; - th->rcf = sdl->sdl_rcf; - } else { - sdl->sdl_rcf = (u_short)0; + th->rcf = trld->trld_rcf; } if (rt->rt_expire) rt->rt_expire = time_second + arpt_keep; |