Subject: making our tcp/ip a strong-end system
To: None <tech-net@netbsd.org>
From: Luke Mewburn <lukem@netbsd.org>
List: tech-net
Date: 11/10/1998 23:16:10
in PR kern/991, darren reed outlines how to modify netbsd (1.0a) to
enforce the `strong end system' model in tcp/ip. this is where a
packet destined for this machine is not accepted on an interface other
than the one that is configured for that address.
i've taken the ideas in darren's pr (and subsequent followups to it)
and merged them into -current (19981010). before i go and totally
screw the pooch, i was interested in feedback from the tcp gurus
to see if my mods were the appropriate solution.
the patch below adds support for a new sysctl, net.inet.ip.strongendsystem,
which if set to non-zero enforces the semantics described above. you
can hardcode this on by defining IPSTRONGENDSYSTEM to non-zero.
comments/thoughts on this suggested patch? problems people see with
this implementation (especially when you've got a multihomed box
that's routing)?
luke.
Index: if_arp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/if_arp.c,v
retrieving revision 1.53
diff -c -r1.53 if_arp.c
*** if_arp.c 1998/10/01 11:04:24 1.53
--- if_arp.c 1998/11/10 12:10:30
***************
*** 512,517 ****
--- 512,518 ----
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
int op;
+ int oipses;
ah = mtod(m, struct arphdr *);
op = ntohs(ah->ar_op);
***************
*** 539,552 ****
* or any address on the interface to use
* as a dummy address in the rest of this function
*/
! INADDR_TO_IA(itaddr, ia);
! while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif)
! NEXT_IA_WITH_SAME_ADDR(ia);
!
if (ia == NULL) {
! INADDR_TO_IA(isaddr, ia);
! while ((ia != NULL) && ia->ia_ifp != m->m_pkthdr.rcvif)
! NEXT_IA_WITH_SAME_ADDR(ia);
if (ia == NULL) {
IFP_TO_IA(ifp, ia);
--- 540,554 ----
* or any address on the interface to use
* as a dummy address in the rest of this function
*/
! oipses = ip_strongendsystem;
! ip_strongendsystem = 1;
! INADDR_TO_IA(itaddr, ia, m);
! ip_strongendsystem = oipses;
if (ia == NULL) {
! oipses = ip_strongendsystem;
! ip_strongendsystem = 1;
! INADDR_TO_IA(isaddr, ia, m);
! ip_strongendsystem = oipses;
if (ia == NULL) {
IFP_TO_IA(ifp, ia);
Index: in.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.h,v
retrieving revision 1.39
diff -c -r1.39 in.h
*** in.h 1998/09/14 21:15:56 1.39
--- in.h 1998/11/10 12:10:30
***************
*** 297,303 ****
#define IPCTL_ANONPORTMAX 11 /* maximum ephemeral port */
#define IPCTL_MTUDISCTIMEOUT 12 /* allow path MTU discovery */
#define IPCTL_MAXFLOWS 13 /* maximum ip flows allowed */
! #define IPCTL_MAXID 14
#define IPCTL_NAMES { \
{ 0, 0 }, \
--- 297,304 ----
#define IPCTL_ANONPORTMAX 11 /* maximum ephemeral port */
#define IPCTL_MTUDISCTIMEOUT 12 /* allow path MTU discovery */
#define IPCTL_MAXFLOWS 13 /* maximum ip flows allowed */
! #define IPCTL_STRONGENDSYSTEM 14 /* forbid packets on wrong interface */
! #define IPCTL_MAXID 15
#define IPCTL_NAMES { \
{ 0, 0 }, \
***************
*** 314,319 ****
--- 315,321 ----
{ "anonportmax", CTLTYPE_INT }, \
{ "mtudisctimeout", CTLTYPE_INT }, \
{ "maxflows", CTLTYPE_INT }, \
+ { "strongendsystem", CTLTYPE_INT }, \
}
#endif /* !_XOPEN_SOURCE */
Index: in_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/in_var.h,v
retrieving revision 1.31
diff -c -r1.31 in_var.h
*** in_var.h 1998/09/30 21:52:25 1.31
--- in_var.h 1998/11/10 12:10:30
***************
*** 138,174 ****
extern struct in_ifaddrhead in_ifaddr; /* List head (in ip_input) */
extern struct ifqueue ipintrq; /* ip packet input queue */
void in_socktrim __P((struct sockaddr_in *));
/*
* Macro for finding whether an internet address (in_addr) belongs to one
! * of our interfaces (in_ifaddr). NULL if the address isn't ours.
*/
! #define INADDR_TO_IA(addr, ia) \
/* struct in_addr addr; */ \
/* struct in_ifaddr *ia; */ \
{ \
for (ia = IN_IFADDR_HASH((addr).s_addr).lh_first; \
! ia != NULL && !in_hosteq(ia->ia_addr.sin_addr, (addr)); \
! ia = ia->ia_hash.le_next) \
! continue; \
! }
!
! /*
! * Macro for finding the next in_ifaddr structure with the same internet
! * address as ia. Call only with a valid ia pointer.
! * Will set ia to NULL if none found.
! */
!
! #define NEXT_IA_WITH_SAME_ADDR(ia) \
! /* struct in_ifaddr *ia; */ \
! { \
! struct in_addr addr; \
! addr = ia->ia_addr.sin_addr; \
! do { \
! ia = ia->ia_hash.le_next; \
! } while ((ia != NULL) && !in_hosteq(ia->ia_addr.sin_addr, addr)); \
}
/*
--- 138,169 ----
extern struct in_ifaddrhead in_ifaddr; /* List head (in ip_input) */
extern struct ifqueue ipintrq; /* ip packet input queue */
+
+ extern int ipforwarding; /* ip forwarding */
+ extern int ip_strongendsystem; /* strong ended system */
+
void in_socktrim __P((struct sockaddr_in *));
/*
* Macro for finding whether an internet address (in_addr) belongs to one
! * of our interfaces (in_ifaddr). If necessary, ensure that the packet (mb)
! * came in on the correct interface. NULL if the address isn't ours.
*/
! #define INADDR_TO_IA(addr, ia, mb) \
/* struct in_addr addr; */ \
/* struct in_ifaddr *ia; */ \
+ /* struct mbuf *mb; */ \
{ \
for (ia = IN_IFADDR_HASH((addr).s_addr).lh_first; \
! ia != NULL; \
! ia = ia->ia_hash.le_next) {\
! if (!in_hosteq(ia->ia_addr.sin_addr, (addr))) \
! continue; \
! if (mb == NULL || \
! !ip_strongendsystem || ia->ia_ifp == mb->m_pkthdr.rcvif) \
! break; \
! } \
}
/*
***************
*** 180,187 ****
/* struct ifnet *ifp; */ \
{ \
register struct in_ifaddr *ia; \
\
! INADDR_TO_IA(addr, ia); \
(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
}
--- 175,183 ----
/* struct ifnet *ifp; */ \
{ \
register struct in_ifaddr *ia; \
+ register struct mbuf *mb = NULL; \
\
! INADDR_TO_IA(addr, ia, mb); \
(ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
}
Index: ip_icmp.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.30
diff -c -r1.30 ip_icmp.c
*** ip_icmp.c 1998/09/30 21:52:25 1.30
--- ip_icmp.c 1998/11/10 12:10:31
***************
*** 492,498 ****
* or anonymous), use the address which corresponds
* to the incoming interface.
*/
! INADDR_TO_IA(t, ia);
if (ia == NULL && (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) {
for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
--- 492,498 ----
* or anonymous), use the address which corresponds
* to the incoming interface.
*/
! INADDR_TO_IA(t, ia, m);
if (ia == NULL && (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST)) {
for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
Index: ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.73
diff -c -r1.73 ip_input.c
*** ip_input.c 1998/10/08 01:41:46 1.73
--- ip_input.c 1998/11/10 12:10:31
***************
*** 128,133 ****
--- 128,136 ----
#ifndef IPMTUDISCTIMEOUT
#define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */
#endif
+ #ifndef IPSTRONGENDSYSTEM
+ #define IPSTRONGENDSYSTEM 0 /* allow packets on wrong interface */
+ #endif
/*
* Note: DIRECTED_BROADCAST is handled this way so that previous
***************
*** 148,153 ****
--- 151,157 ----
int ip_allowsrcrt = IPALLOWSRCRT;
int ip_mtudisc = IPMTUDISC;
u_int ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
+ int ip_strongendsystem = IPSTRONGENDSYSTEM;
#ifdef DIAGNOSTIC
int ipprintfs = 0;
#endif
***************
*** 359,370 ****
/*
* Check our list of addresses, to see if the packet is for us.
*/
! INADDR_TO_IA(ip->ip_dst, ia);
! if (ia != NULL) goto ours;
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
! if (ifa->ifa_addr->sa_family != AF_INET) continue;
ia = ifatoia(ifa);
if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
--- 363,376 ----
/*
* Check our list of addresses, to see if the packet is for us.
*/
! INADDR_TO_IA(ip->ip_dst, ia, m);
! if (ia != NULL)
! goto ours;
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
! if (ifa->ifa_addr->sa_family != AF_INET)
! continue;
ia = ifatoia(ifa);
if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
***************
*** 1424,1429 ****
--- 1430,1438 ----
return (error);
}
#endif
+ case IPCTL_STRONGENDSYSTEM:
+ return (sysctl_int(oldp, oldlenp, newp, newlen,
+ &ip_strongendsystem));
default:
return (EOPNOTSUPP);
}
Index: ip_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_var.h,v
retrieving revision 1.36
diff -c -r1.36 ip_var.h
*** ip_var.h 1998/10/08 01:41:46 1.36
--- ip_var.h 1998/11/10 12:10:32
***************
*** 181,198 ****
extern struct ipstat ipstat; /* ip statistics */
extern LIST_HEAD(ipqhead, ipq) ipq; /* ip reass. queue */
extern u_int16_t ip_id; /* ip packet ctr, for ids */
! extern int ip_defttl; /* default IP ttl */
! extern int ipforwarding; /* ip forwarding */
! extern int ip_mtudisc; /* mtu discovery */
! extern u_int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */
! extern int anonportmin; /* minimum ephemeral port */
! extern int anonportmax; /* maximum ephemeral port */
extern struct rttimer_queue *ip_mtudisc_timeout_q;
#ifdef GATEWAY
! extern int ip_maxflows;
#endif
extern struct pool ipqent_pool;
! struct inpcb;
int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
int ip_dooptions __P((struct mbuf *));
--- 181,197 ----
extern struct ipstat ipstat; /* ip statistics */
extern LIST_HEAD(ipqhead, ipq) ipq; /* ip reass. queue */
extern u_int16_t ip_id; /* ip packet ctr, for ids */
! extern int ip_defttl; /* default IP ttl */
! extern int ip_mtudisc; /* mtu discovery */
! extern u_int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */
! extern int anonportmin; /* minimum ephemeral port */
! extern int anonportmax; /* maximum ephemeral port */
extern struct rttimer_queue *ip_mtudisc_timeout_q;
#ifdef GATEWAY
! extern int ip_maxflows;
#endif
extern struct pool ipqent_pool;
! struct inpcb;
int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
int ip_dooptions __P((struct mbuf *));