Remove the last two global variables that are used to store packet state while
it travels through the IP stack. This wasn't much of a problem because IP source routing is disabled by default but when enabled together with SMP and preemption it would have very likely cross-corrupted the IP options in transit. The IP source route options of a packet are now stored in a mtag instead of the global variable.
This commit is contained in:
parent
f2a9e36629
commit
e098266191
@ -711,7 +711,7 @@ match:
|
|||||||
* add on any record-route or timestamp options.
|
* add on any record-route or timestamp options.
|
||||||
*/
|
*/
|
||||||
cp = (u_char *) (ip + 1);
|
cp = (u_char *) (ip + 1);
|
||||||
if ((opts = ip_srcroute()) == 0 &&
|
if ((opts = ip_srcroute(m)) == 0 &&
|
||||||
(opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
|
(opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
|
||||||
opts->m_len = sizeof(struct in_addr);
|
opts->m_len = sizeof(struct in_addr);
|
||||||
mtod(opts, struct in_addr *)->s_addr = 0;
|
mtod(opts, struct in_addr *)->s_addr = 0;
|
||||||
|
@ -213,28 +213,22 @@ int fw_enable = 1;
|
|||||||
int fw_one_pass = 1;
|
int fw_one_pass = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX this is ugly -- the following two global variables are
|
* XXX this is ugly. IP options source routing magic.
|
||||||
* used to store packet state while it travels through the stack.
|
|
||||||
* Note that the code even makes assumptions on the size and
|
|
||||||
* alignment of fields inside struct ip_srcrt so e.g. adding some
|
|
||||||
* fields will break the code. This needs to be fixed.
|
|
||||||
*
|
|
||||||
* We need to save the IP options in case a protocol wants to respond
|
|
||||||
* to an incoming packet over the same route if the packet got here
|
|
||||||
* using IP source routing. This allows connection establishment and
|
|
||||||
* maintenance when the remote end is on a network that is not known
|
|
||||||
* to us.
|
|
||||||
* XXX: Broken on SMP and possibly preemption!
|
|
||||||
*/
|
*/
|
||||||
static int ip_nhops = 0;
|
struct ipoptrt {
|
||||||
static struct ip_srcrt {
|
|
||||||
struct in_addr dst; /* final destination */
|
struct in_addr dst; /* final destination */
|
||||||
char nop; /* one NOP to align */
|
char nop; /* one NOP to align */
|
||||||
char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
|
char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
|
||||||
struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
|
struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
|
||||||
} ip_srcrt;
|
};
|
||||||
|
|
||||||
static void save_rte(u_char *, struct in_addr);
|
struct ipopt_tag {
|
||||||
|
struct m_tag tag;
|
||||||
|
int ip_nhops;
|
||||||
|
struct ipoptrt ip_srcrt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void save_rte(struct mbuf *, u_char *, struct in_addr);
|
||||||
static int ip_dooptions(struct mbuf *m, int);
|
static int ip_dooptions(struct mbuf *m, int);
|
||||||
static void ip_forward(struct mbuf *m, int srcrt);
|
static void ip_forward(struct mbuf *m, int srcrt);
|
||||||
static void ip_freef(struct ipqhead *, struct ipq *);
|
static void ip_freef(struct ipqhead *, struct ipq *);
|
||||||
@ -1244,7 +1238,7 @@ ip_dooptions(struct mbuf *m, int pass)
|
|||||||
*/
|
*/
|
||||||
if (!ip_acceptsourceroute)
|
if (!ip_acceptsourceroute)
|
||||||
goto nosourcerouting;
|
goto nosourcerouting;
|
||||||
save_rte(cp, ip->ip_src);
|
save_rte(m, cp, ip->ip_src);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef IPSTEALTH
|
#ifdef IPSTEALTH
|
||||||
@ -1454,22 +1448,30 @@ ip_rtaddr(dst)
|
|||||||
* to be picked up later by ip_srcroute if the receiver is interested.
|
* to be picked up later by ip_srcroute if the receiver is interested.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
save_rte(option, dst)
|
save_rte(m, option, dst)
|
||||||
|
struct mbuf *m;
|
||||||
u_char *option;
|
u_char *option;
|
||||||
struct in_addr dst;
|
struct in_addr dst;
|
||||||
{
|
{
|
||||||
unsigned olen;
|
unsigned olen;
|
||||||
|
struct ipopt_tag *opts;
|
||||||
|
|
||||||
|
opts = (struct ipopt_tag *)m_tag_get(PACKET_TAG_IPOPTIONS,
|
||||||
|
sizeof(struct ipopt_tag), M_NOWAIT);
|
||||||
|
if (opts == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
olen = option[IPOPT_OLEN];
|
olen = option[IPOPT_OLEN];
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ipprintfs)
|
if (ipprintfs)
|
||||||
printf("save_rte: olen %d\n", olen);
|
printf("save_rte: olen %d\n", olen);
|
||||||
#endif
|
#endif
|
||||||
if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
|
if (olen > sizeof(opts->ip_srcrt) - (1 + sizeof(dst)))
|
||||||
return;
|
return;
|
||||||
bcopy(option, ip_srcrt.srcopt, olen);
|
bcopy(option, opts->ip_srcrt.srcopt, olen);
|
||||||
ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
|
opts->ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
|
||||||
ip_srcrt.dst = dst;
|
opts->ip_srcrt.dst = dst;
|
||||||
|
m_tag_prepend(m, (struct m_tag *)opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1478,31 +1480,37 @@ save_rte(option, dst)
|
|||||||
* The first hop is placed before the options, will be removed later.
|
* The first hop is placed before the options, will be removed later.
|
||||||
*/
|
*/
|
||||||
struct mbuf *
|
struct mbuf *
|
||||||
ip_srcroute()
|
ip_srcroute(m0)
|
||||||
|
struct mbuf *m0;
|
||||||
{
|
{
|
||||||
register struct in_addr *p, *q;
|
register struct in_addr *p, *q;
|
||||||
register struct mbuf *m;
|
register struct mbuf *m;
|
||||||
|
struct ipopt_tag *opts;
|
||||||
|
|
||||||
if (ip_nhops == 0)
|
opts = (struct ipopt_tag *)m_tag_find(m0, PACKET_TAG_IPOPTIONS, NULL);
|
||||||
|
if (opts == NULL)
|
||||||
|
return ((struct mbuf *)0);
|
||||||
|
|
||||||
|
if (opts->ip_nhops == 0)
|
||||||
return ((struct mbuf *)0);
|
return ((struct mbuf *)0);
|
||||||
m = m_get(M_DONTWAIT, MT_HEADER);
|
m = m_get(M_DONTWAIT, MT_HEADER);
|
||||||
if (m == NULL)
|
if (m == NULL)
|
||||||
return ((struct mbuf *)0);
|
return ((struct mbuf *)0);
|
||||||
|
|
||||||
#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
|
#define OPTSIZ (sizeof(opts->ip_srcrt.nop) + sizeof(opts->ip_srcrt.srcopt))
|
||||||
|
|
||||||
/* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
|
/* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
|
||||||
m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
|
m->m_len = opts->ip_nhops * sizeof(struct in_addr) +
|
||||||
OPTSIZ;
|
sizeof(struct in_addr) + OPTSIZ;
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ipprintfs)
|
if (ipprintfs)
|
||||||
printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
|
printf("ip_srcroute: nhops %d mlen %d", opts->ip_nhops, m->m_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First save first hop for return route
|
* First save first hop for return route
|
||||||
*/
|
*/
|
||||||
p = &ip_srcrt.route[ip_nhops - 1];
|
p = &(opts->ip_srcrt.route[opts->ip_nhops - 1]);
|
||||||
*(mtod(m, struct in_addr *)) = *p--;
|
*(mtod(m, struct in_addr *)) = *p--;
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ipprintfs)
|
if (ipprintfs)
|
||||||
@ -1512,10 +1520,10 @@ ip_srcroute()
|
|||||||
/*
|
/*
|
||||||
* Copy option fields and padding (nop) to mbuf.
|
* Copy option fields and padding (nop) to mbuf.
|
||||||
*/
|
*/
|
||||||
ip_srcrt.nop = IPOPT_NOP;
|
opts->ip_srcrt.nop = IPOPT_NOP;
|
||||||
ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
|
opts->ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
|
||||||
(void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr),
|
(void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr),
|
||||||
&ip_srcrt.nop, OPTSIZ);
|
&(opts->ip_srcrt.nop), OPTSIZ);
|
||||||
q = (struct in_addr *)(mtod(m, caddr_t) +
|
q = (struct in_addr *)(mtod(m, caddr_t) +
|
||||||
sizeof(struct in_addr) + OPTSIZ);
|
sizeof(struct in_addr) + OPTSIZ);
|
||||||
#undef OPTSIZ
|
#undef OPTSIZ
|
||||||
@ -1523,7 +1531,7 @@ ip_srcroute()
|
|||||||
* Record return path as an IP source route,
|
* Record return path as an IP source route,
|
||||||
* reversing the path (pointers are now aligned).
|
* reversing the path (pointers are now aligned).
|
||||||
*/
|
*/
|
||||||
while (p >= ip_srcrt.route) {
|
while (p >= opts->ip_srcrt.route) {
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ipprintfs)
|
if (ipprintfs)
|
||||||
printf(" %lx", (u_long)ntohl(q->s_addr));
|
printf(" %lx", (u_long)ntohl(q->s_addr));
|
||||||
@ -1533,11 +1541,12 @@ ip_srcroute()
|
|||||||
/*
|
/*
|
||||||
* Last hop goes to final destination.
|
* Last hop goes to final destination.
|
||||||
*/
|
*/
|
||||||
*q = ip_srcrt.dst;
|
*q = opts->ip_srcrt.dst;
|
||||||
#ifdef DIAGNOSTIC
|
#ifdef DIAGNOSTIC
|
||||||
if (ipprintfs)
|
if (ipprintfs)
|
||||||
printf(" %lx\n", (u_long)ntohl(q->s_addr));
|
printf(" %lx\n", (u_long)ntohl(q->s_addr));
|
||||||
#endif
|
#endif
|
||||||
|
m_tag_delete(m0, (struct m_tag *)opts);
|
||||||
return (m);
|
return (m);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1913,7 +1922,7 @@ ip_savecontrol(inp, mp, ip, m)
|
|||||||
}
|
}
|
||||||
/* ip_srcroute doesn't do what we want here, need to fix */
|
/* ip_srcroute doesn't do what we want here, need to fix */
|
||||||
if (inp->inp_flags & INP_RECVRETOPTS) {
|
if (inp->inp_flags & INP_RECVRETOPTS) {
|
||||||
*mp = sbcreatecontrol((caddr_t) ip_srcroute(),
|
*mp = sbcreatecontrol((caddr_t) ip_srcroute(m),
|
||||||
sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
|
sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
|
||||||
if (*mp)
|
if (*mp)
|
||||||
mp = &(*mp)->m_next;
|
mp = &(*mp)->m_next;
|
||||||
|
@ -176,7 +176,7 @@ void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
|
|||||||
struct mbuf *);
|
struct mbuf *);
|
||||||
void ip_slowtimo(void);
|
void ip_slowtimo(void);
|
||||||
struct mbuf *
|
struct mbuf *
|
||||||
ip_srcroute(void);
|
ip_srcroute(struct mbuf *);
|
||||||
void ip_stripoptions(struct mbuf *, struct mbuf *);
|
void ip_stripoptions(struct mbuf *, struct mbuf *);
|
||||||
u_int16_t ip_randomid(void);
|
u_int16_t ip_randomid(void);
|
||||||
int rip_ctloutput(struct socket *, struct sockopt *);
|
int rip_ctloutput(struct socket *, struct sockopt *);
|
||||||
|
@ -649,7 +649,7 @@ syncache_socket(sc, lso, m)
|
|||||||
struct in_addr laddr;
|
struct in_addr laddr;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
|
||||||
inp->inp_options = ip_srcroute();
|
inp->inp_options = ip_srcroute(m);
|
||||||
if (inp->inp_options == NULL) {
|
if (inp->inp_options == NULL) {
|
||||||
inp->inp_options = sc->sc_ipopts;
|
inp->inp_options = sc->sc_ipopts;
|
||||||
sc->sc_ipopts = NULL;
|
sc->sc_ipopts = NULL;
|
||||||
@ -847,7 +847,7 @@ syncache_add(inc, to, th, sop, m)
|
|||||||
#ifdef INET6
|
#ifdef INET6
|
||||||
if (!inc->inc_isipv6)
|
if (!inc->inc_isipv6)
|
||||||
#endif
|
#endif
|
||||||
ipopts = ip_srcroute();
|
ipopts = ip_srcroute(m);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See if we already have an entry for this connection.
|
* See if we already have an entry for this connection.
|
||||||
|
@ -642,6 +642,7 @@ struct mbuf *m_uiotombuf(struct uio *, int, int);
|
|||||||
#define PACKET_TAG_PF_TAG 24 /* PF tagged */
|
#define PACKET_TAG_PF_TAG 24 /* PF tagged */
|
||||||
#define PACKET_TAG_RTSOCKFAM 25 /* rtsock sa family */
|
#define PACKET_TAG_RTSOCKFAM 25 /* rtsock sa family */
|
||||||
#define PACKET_TAG_PF_TRANSLATE_LOCALHOST 26 /* PF translate localhost */
|
#define PACKET_TAG_PF_TRANSLATE_LOCALHOST 26 /* PF translate localhost */
|
||||||
|
#define PACKET_TAG_IPOPTIONS 27 /* Saved IP options */
|
||||||
|
|
||||||
/* Packet tag routines. */
|
/* Packet tag routines. */
|
||||||
struct m_tag *m_tag_alloc(u_int32_t, int, int, int);
|
struct m_tag *m_tag_alloc(u_int32_t, int, int, int);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user