diff options
Diffstat (limited to 'sys/net/encap.c')
-rw-r--r-- | sys/net/encap.c | 118 |
1 files changed, 115 insertions, 3 deletions
diff --git a/sys/net/encap.c b/sys/net/encap.c index ea0d210c4d4..911ca641397 100644 --- a/sys/net/encap.c +++ b/sys/net/encap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: encap.c,v 1.9 1997/07/14 08:46:39 provos Exp $ */ +/* $OpenBSD: encap.c,v 1.10 1997/07/15 23:11:08 provos Exp $ */ /* * The author of this code is John Ioannidis, ji@tla.org, @@ -164,12 +164,13 @@ va_dcl { #define SENDERR(e) do { error = e; goto flush;} while (0) struct sockaddr_encap encapdst, encapgw, encapnetmask; + struct in_addr alts, altm; int len, emlen, error = 0; + struct flow *flow, *flow2; struct encap_msghdr *emp; struct tdb *tdbp, *tdbp2; caddr_t buffer = 0; struct socket *so; - struct flow *flow; u_int32_t spi; va_list ap; @@ -454,10 +455,42 @@ va_dcl if (flow != (struct flow *) NULL) SENDERR(EEXIST); + /* Check for 0.0.0.0/255.255.255.255 if the flow is local */ + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + { + alts.s_addr = INADDR_ANY; + altm.s_addr = INADDR_BROADCAST; + flow2 = find_flow(alts, altm, emp->em_ena_idst, + emp->em_ena_idmask, emp->em_ena_protocol, + emp->em_ena_sport, emp->em_ena_dport, tdbp); + if (flow2 != (struct flow *) NULL) + SENDERR(EEXIST); + } + flow = get_flow(); if (flow == (struct flow *) NULL) SENDERR(ENOBUFS); + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + { + flow2 = get_flow(); + if (flow2 == (struct flow *) NULL) + { + FREE(flow, M_TDB); + SENDERR(ENOBUFS); + } + + flow2->flow_src.s_addr = INADDR_ANY; + flow2->flow_dst.s_addr = emp->em_ena_idst.s_addr; + flow2->flow_srcmask.s_addr = INADDR_BROADCAST; + flow2->flow_dstmask.s_addr = emp->em_ena_idmask.s_addr; + flow2->flow_proto = emp->em_ena_protocol; + flow2->flow_sport = emp->em_ena_sport; + flow2->flow_dport = emp->em_ena_dport; + + put_flow(flow2, tdbp); + } + flow->flow_src.s_addr = emp->em_ena_isrc.s_addr; flow->flow_dst.s_addr = emp->em_ena_idst.s_addr; flow->flow_srcmask.s_addr = emp->em_ena_ismask.s_addr; @@ -501,6 +534,14 @@ va_dcl encapnetmask.sen_dport = 0xffff; } + /* If this is set, delete any old route for this flow */ + if (emp->em_ena_flags & ENABLE_FLAG_REPLACE) + rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0); + /* Add the entry in the routing table */ error = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst, (struct sockaddr *) &encapgw, @@ -511,9 +552,47 @@ va_dcl if (error) { delete_flow(flow, tdbp); + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + delete_flow(flow2, tdbp); SENDERR(error); } + /* If this is a "local" packet flow */ + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + { + encapdst.sen_ip_src.s_addr = INADDR_ANY; + encapnetmask.sen_ip_src.s_addr = INADDR_BROADCAST; + + if (emp->em_ena_flags & ENABLE_FLAG_REPLACE) + rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0); + + error = rtrequest(RTM_ADD, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0); + + if (error) + { + encapdst.sen_ip_src.s_addr = emp->em_ena_isrc.s_addr; + encapnetmask.sen_ip_src.s_addr = emp->em_ena_ismask.s_addr; + + rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0); + + delete_flow(flow, tdbp); + delete_flow(flow2, tdbp); + SENDERR(error); + } + } + error = 0; break; @@ -533,6 +612,18 @@ va_dcl if (flow == (struct flow *) NULL) SENDERR(ENOENT); + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + { + alts.s_addr = INADDR_ANY; + altm.s_addr = INADDR_BROADCAST; + + flow2 = find_flow(alts, altm, emp->em_ena_idst, + emp->em_ena_idmask, emp->em_ena_protocol, + emp->em_ena_sport, emp->em_ena_dport, tdbp); + if (flow2 == (struct flow *) NULL) + SENDERR(ENOENT); + } + /* Setup the encap fields */ encapdst.sen_len = SENT_IP4_LEN; encapdst.sen_family = AF_ENCAP; @@ -566,7 +657,7 @@ va_dcl encapnetmask.sen_dport = 0xffff; } - /* Add the entry in the routing table */ + /* Delete the entry */ error = rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, (struct sockaddr *) &encapgw, (struct sockaddr *) &encapnetmask, @@ -575,6 +666,27 @@ va_dcl delete_flow(flow, tdbp); + if (error) + SENDERR(error); + + if (emp->em_ena_flags & ENABLE_FLAG_LOCAL) + { + + encapdst.sen_ip_src.s_addr = INADDR_ANY; + encapnetmask.sen_ip_src.s_addr = INADDR_BROADCAST; + + error = rtrequest(RTM_DELETE, (struct sockaddr *) &encapdst, + (struct sockaddr *) &encapgw, + (struct sockaddr *) &encapnetmask, + RTF_UP | RTF_GATEWAY | RTF_STATIC, + (struct rtentry **) 0); + + delete_flow(flow2, tdbp); + + if (error) + SENDERR(error); + } + break; case EMT_NOTIFY: |