diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/if_atm.c | 2 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 297 | ||||
-rw-r--r-- | sys/netinet/in_gif.c | 8 | ||||
-rw-r--r-- | sys/netinet/in_mcast.c | 3 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 3 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 2 | ||||
-rw-r--r-- | sys/netinet/in_rmx.c | 154 | ||||
-rw-r--r-- | sys/netinet/in_var.h | 16 | ||||
-rw-r--r-- | sys/netinet/ip_fastfwd.c | 2 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 4 | ||||
-rw-r--r-- | sys/netinet/ip_fw2.c | 54 | ||||
-rw-r--r-- | sys/netinet/ip_icmp.c | 17 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.c | 4 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.h | 2 | ||||
-rw-r--r-- | sys/netinet/ip_options.c | 5 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 8 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 2 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_os_bsd.h | 2 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 1 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 8 | ||||
-rw-r--r-- | sys/netinet/tcp_syncache.c | 4 |
23 files changed, 430 insertions, 180 deletions
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c index d19dea8..065f0c4 100644 --- a/sys/netinet/if_atm.c +++ b/sys/netinet/if_atm.c @@ -327,7 +327,7 @@ atmresolve(struct rtentry *rt, struct mbuf *m, struct sockaddr *dst, } if (rt == NULL) { - rt = RTALLOC1(dst, 0); + rt = RTALLOC1(dst, 0); /* link level on table 0 XXX MRT */ if (rt == NULL) goto bad; /* failed */ RT_REMREF(rt); /* don't keep LL references */ diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index b1133c9..6939dbb 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -116,7 +116,7 @@ static void arprequest(struct ifnet *, static void arpintr(struct mbuf *); static void arptimer(void *); static struct rtentry - *arplookup(u_long, int, int); + *arplookup(u_long, int, int, int); #ifdef INET static void in_arpinput(struct mbuf *); #endif @@ -138,7 +138,8 @@ arptimer(void *arg) */ RT_UNLOCK(rt); - rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL); + in_rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL, + rt->rt_fibnum); } /* @@ -362,6 +363,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, struct rtentry *rt = NULL; struct sockaddr_dl *sdl; int error; + int fibnum = 0; if (m) { if (m->m_flags & M_BCAST) { @@ -375,10 +377,14 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); return (0); } + fibnum = M_GETFIB(m); } if (rt0 != NULL) { - error = rt_check(&rt, &rt0, dst); + /* Look for a cached arp (ll) entry. */ + if (m == NULL) + fibnum = rt0->rt_fibnum; + error = in_rt_check(&rt, &rt0, dst, fibnum); if (error) { m_freem(m); return error; @@ -389,10 +395,14 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, } if (la == NULL) { /* - * We enter this block in case if rt0 was NULL, - * or if rt found by rt_check() didn't have llinfo. + * We enter this block if rt0 was NULL, + * or if rt found by in_rt_check() didn't have llinfo. + * we should get a cloned route, which since it should + * come from the local interface should have a ll entry. + * if may be incoplete but that's ok. + * XXXMRT if we haven't found a fibnum is that OK? */ - rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0); + rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0, fibnum); if (rt == NULL) { log(LOG_DEBUG, "arpresolve: can't allocate route for %s\n", @@ -582,6 +592,9 @@ in_arpinput(struct mbuf *m) int op, rif_len; int req_len; int bridged = 0; + u_int fibnum; + u_int goodfib = 0; + int firstpass = 1; #ifdef DEV_CARP int carp_match = 0; #endif @@ -674,133 +687,181 @@ match: } if (ifp->if_flags & IFF_STATICARP) goto reply; - rt = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0); - if (rt != NULL) { - sin.sin_addr.s_addr = isaddr.s_addr; - EVENTHANDLER_INVOKE(route_arp_update_event, rt, - ar_sha(ah), (struct sockaddr *)&sin); + /* + * We look for any FIBs that has this address to find + * the interface etc. + * For sanity checks that are FIB independent we abort the loop. + */ + for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { + rt = arplookup(isaddr.s_addr, + itaddr.s_addr == myaddr.s_addr, 0, fibnum); + if (rt == NULL) + continue; + + sdl = SDL(rt->rt_gateway); + /* Only call this once */ + if (firstpass) { + sin.sin_addr.s_addr = isaddr.s_addr; + EVENTHANDLER_INVOKE(route_arp_update_event, rt, + ar_sha(ah), (struct sockaddr *)&sin); + } la = (struct llinfo_arp *)rt->rt_llinfo; if (la == NULL) { RT_UNLOCK(rt); - goto reply; + continue; } - } else - goto reply; - /* The following is not an error when doing bridging. */ - if (!bridged && rt->rt_ifp != ifp + if (firstpass) { + /* The following is not an error when doing bridging. */ + if (!bridged && rt->rt_ifp != ifp #ifdef DEV_CARP - && (ifp->if_type != IFT_CARP || !carp_match) + && (ifp->if_type != IFT_CARP || !carp_match) #endif - ) { - if (log_arp_wrong_iface) - log(LOG_ERR, "arp: %s is on %s but got reply from %*D on %s\n", - inet_ntoa(isaddr), - rt->rt_ifp->if_xname, - ifp->if_addrlen, (u_char *)ar_sha(ah), ":", - ifp->if_xname); - RT_UNLOCK(rt); - goto reply; - } - sdl = SDL(rt->rt_gateway); - if (sdl->sdl_alen && - bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) { - if (rt->rt_expire) { - if (log_arp_movements) - log(LOG_INFO, "arp: %s moved from %*D to %*D on %s\n", - inet_ntoa(isaddr), - ifp->if_addrlen, (u_char *)LLADDR(sdl), ":", - ifp->if_addrlen, (u_char *)ar_sha(ah), ":", - ifp->if_xname); - } else { - RT_UNLOCK(rt); - if (log_arp_permanent_modify) - log(LOG_ERR, "arp: %*D attempts to modify " - "permanent entry for %s on %s\n", - ifp->if_addrlen, (u_char *)ar_sha(ah), ":", - inet_ntoa(isaddr), ifp->if_xname); - goto reply; - } - } - /* - * sanity check for the address length. - * XXX this does not work for protocols with variable address - * length. -is - */ - if (sdl->sdl_alen && - sdl->sdl_alen != ah->ar_hln) { - log(LOG_WARNING, - "arp from %*D: new addr len %d, was %d", - ifp->if_addrlen, (u_char *) ar_sha(ah), ":", - ah->ar_hln, sdl->sdl_alen); - } - if (ifp->if_addrlen != ah->ar_hln) { - log(LOG_WARNING, - "arp from %*D: addr len: new %d, i/f %d (ignored)", - ifp->if_addrlen, (u_char *) ar_sha(ah), ":", - ah->ar_hln, ifp->if_addrlen); - RT_UNLOCK(rt); - goto reply; - } - (void)memcpy(LLADDR(sdl), ar_sha(ah), - sdl->sdl_alen = ah->ar_hln); - /* - * If we receive an arp from a token-ring station over - * a token-ring nic then try to save the source - * routing info. - */ - if (ifp->if_type == IFT_ISO88025) { - struct iso88025_header *th = NULL; - struct iso88025_sockaddr_dl_data *trld; - - 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)) { - 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); + ) { + if (log_arp_wrong_iface) + log(LOG_ERR, "arp: %s is on %s " + "but got reply from %*D " + "on %s\n", + inet_ntoa(isaddr), + rt->rt_ifp->if_xname, + ifp->if_addrlen, + (u_char *)ar_sha(ah), ":", + ifp->if_xname); + RT_UNLOCK(rt); + break; + } + if (sdl->sdl_alen && + bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) { + if (rt->rt_expire) { + if (log_arp_movements) + log(LOG_INFO, + "arp: %s moved from %*D to %*D " + "on %s\n", + inet_ntoa(isaddr), + ifp->if_addrlen, + (u_char *)LLADDR(sdl), ":", + ifp->if_addrlen, + (u_char *)ar_sha(ah), ":", + ifp->if_xname); + } else { + RT_UNLOCK(rt); + if (log_arp_permanent_modify) + log(LOG_ERR, + "arp: %*D attempts to " + "modify permanent entry " + "for %s on %s\n", + ifp->if_addrlen, + (u_char *)ar_sha(ah), ":", + inet_ntoa(isaddr), + ifp->if_xname); + break; + } + } /* - * Set up source routing information for - * reply packet (XXX) + * sanity check for the address length. + * XXX this does not work for protocols + * with variable address length. -is */ - m->m_data -= rif_len; - m->m_len += rif_len; - m->m_pkthdr.len += rif_len; - } else { - th->iso88025_shost[0] &= ~TR_RII; - trld->trld_rcf = 0; + if (sdl->sdl_alen && + sdl->sdl_alen != ah->ar_hln) { + log(LOG_WARNING, + "arp from %*D: new addr len %d, was %d", + ifp->if_addrlen, (u_char *) ar_sha(ah), + ":", ah->ar_hln, sdl->sdl_alen); + } + if (ifp->if_addrlen != ah->ar_hln) { + log(LOG_WARNING, + "arp from %*D: addr len: " + "new %d, i/f %d (ignored)", + ifp->if_addrlen, (u_char *) ar_sha(ah), + ":", ah->ar_hln, ifp->if_addrlen); + RT_UNLOCK(rt); + break; + } + firstpass = 0; + goodfib = fibnum; } - m->m_data -= 8; - m->m_len += 8; - m->m_pkthdr.len += 8; - th->rcf = trld->trld_rcf; - } - if (rt->rt_expire) { - rt->rt_expire = time_uptime + arpt_keep; - callout_reset(&la->la_timer, hz * arpt_keep, arptimer, rt); - } - la->la_asked = 0; - la->la_preempt = arp_maxtries; - hold = la->la_hold; - la->la_hold = NULL; - RT_UNLOCK(rt); - if (hold != NULL) - (*ifp->if_output)(ifp, hold, rt_key(rt), rt); + /* Copy in the information received. */ + (void)memcpy(LLADDR(sdl), ar_sha(ah), + sdl->sdl_alen = ah->ar_hln); + /* + * If we receive an arp from a token-ring station over + * a token-ring nic then try to save the source routing info. + * XXXMRT Only minimal Token Ring support for MRT. + * Only do this on the first pass as if modifies the mbuf. + */ + if (ifp->if_type == IFT_ISO88025) { + struct iso88025_header *th = NULL; + struct iso88025_sockaddr_dl_data *trld; + + /* force the fib loop to end after this pass */ + fibnum = rt_numfibs - 1; + + 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)) { + 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) + */ + m->m_data -= rif_len; + m->m_len += rif_len; + m->m_pkthdr.len += rif_len; + } else { + th->iso88025_shost[0] &= ~TR_RII; + trld->trld_rcf = 0; + } + m->m_data -= 8; + m->m_len += 8; + m->m_pkthdr.len += 8; + th->rcf = trld->trld_rcf; + } + + if (rt->rt_expire) { + rt->rt_expire = time_uptime + arpt_keep; + callout_reset(&la->la_timer, hz * arpt_keep, + arptimer, rt); + } + la->la_asked = 0; + la->la_preempt = arp_maxtries; + hold = la->la_hold; + la->la_hold = NULL; + RT_UNLOCK(rt); + if (hold != NULL) + (*ifp->if_output)(ifp, hold, rt_key(rt), rt); + } /* end of FIB loop */ reply: + + /* + * Decide if we have to respond to something. + */ if (op != ARPOP_REQUEST) goto drop; if (itaddr.s_addr == myaddr.s_addr) { - /* I am the target */ + /* Shortcut.. the receiving interface is the target. */ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln); (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln); } else { - rt = arplookup(itaddr.s_addr, 0, SIN_PROXY); + /* It's not asking for our address. But it still may + * be something we should answer. + * + * XXX MRT + * We assume that link level info is independent of + * the table used and so we use whichever we can and don't + * have a better option. + */ + /* Have we been asked to proxy for the target. */ + rt = arplookup(itaddr.s_addr, 0, SIN_PROXY, goodfib); if (rt == NULL) { + /* Nope, only intersted now if proxying everything. */ struct sockaddr_in sin; if (!arp_proxyall) @@ -811,7 +872,8 @@ reply: sin.sin_len = sizeof sin; sin.sin_addr = itaddr; - rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); + /* XXX MRT use table 0 for arp reply */ + rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); if (!rt) goto drop; /* @@ -835,7 +897,8 @@ reply: */ sin.sin_addr = isaddr; - rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); + /* XXX MRT use table 0 for arp checks */ + rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0); if (!rt) goto drop; if (rt->rt_ifp != ifp) { @@ -905,7 +968,7 @@ drop: * Lookup or enter a new address in arptab. */ static struct rtentry * -arplookup(u_long addr, int create, int proxy) +arplookup(u_long addr, int create, int proxy, int fibnum) { struct rtentry *rt; struct sockaddr_inarp sin; @@ -917,7 +980,7 @@ arplookup(u_long addr, int create, int proxy) sin.sin_addr.s_addr = addr; if (proxy) sin.sin_other = SIN_PROXY; - rt = rtalloc1((struct sockaddr *)&sin, create, 0UL); + rt = in_rtalloc1((struct sockaddr *)&sin, create, 0UL, fibnum); if (rt == 0) return (0); diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index 69a34f8..55b4ec7 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -191,6 +191,8 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m) } bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); + M_SETFIB(m, sc->gif_fibnum); + if (dst->sin_family != sin_dst->sin_family || dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) { /* cache route doesn't match */ @@ -208,7 +210,7 @@ in_gif_output(struct ifnet *ifp, int family, struct mbuf *m) } if (sc->gif_ro.ro_rt == NULL) { - rtalloc_ign(&sc->gif_ro, 0); + in_rtalloc_ign(&sc->gif_ro, 0, sc->gif_fibnum); if (sc->gif_ro.ro_rt == NULL) { m_freem(m); return ENETUNREACH; @@ -368,7 +370,9 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp) sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); sin.sin_addr = ip->ip_src; - rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL); + /* XXX MRT check for the interface we would use on output */ + rt = in_rtalloc1((struct sockaddr *)&sin, 0, + 0UL, sc->gif_fibnum); if (!rt || rt->rt_ifp != ifp) { #if 0 log(LOG_WARNING, "%s: packet from 0x%x dropped " diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c index be2208a..9f37f33 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -1025,7 +1025,8 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt) ro.ro_rt = NULL; *(struct sockaddr_in *)&ro.ro_dst = gsa->sin; - rtalloc_ign(&ro, RTF_CLONING); + in_rtalloc_ign(&ro, RTF_CLONING, + inp->inp_inc.inc_fibnum); if (ro.ro_rt != NULL) { ifp = ro.ro_rt->rt_ifp; KASSERT(ifp != NULL, ("%s: null ifp", diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 9b0b6a5..a9702c5 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -186,6 +186,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) bzero(inp, inp_zero_size); inp->inp_pcbinfo = pcbinfo; inp->inp_socket = so; + inp->inp_inc.inc_fibnum = so->so_fibnum; #ifdef MAC error = mac_inpcb_init(inp, M_NOWAIT); if (error != 0) @@ -605,7 +606,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, * Find out route to destination */ if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0) - ia = ip_rtaddr(faddr); + ia = ip_rtaddr(faddr, inp->inp_inc.inc_fibnum); /* * If we found a route, use the address corresponding to * the outgoing interface. diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index afb4dd2..6e5c92e 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -101,7 +101,7 @@ struct in_endpoints { struct in_conninfo { u_int8_t inc_flags; u_int8_t inc_len; - u_int16_t inc_pad; /* XXX alignment for in_endpoints */ + u_int16_t inc_fibnum; /* XXX was pad, 16 bits is plenty */ /* protocol dependent part */ struct in_endpoints inc_ie; }; diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 8a5f978..aabf57e 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -110,7 +110,8 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head, * Find out if it is because of an * ARP entry and delete it if so. */ - rt2 = rtalloc1((struct sockaddr *)sin, 0, RTF_CLONING); + rt2 = in_rtalloc1((struct sockaddr *)sin, 0, + RTF_CLONING, rt->rt_fibnum); if (rt2) { if (rt2->rt_flags & RTF_LLINFO && rt2->rt_flags & RTF_HOST && @@ -225,10 +226,10 @@ in_rtqkill(struct radix_node *rn, void *rock) if (rt->rt_refcnt > 0) panic("rtqkill route really not free"); - err = rtrequest(RTM_DELETE, + err = in_rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), - rt->rt_flags, 0); + rt->rt_flags, 0, rt->rt_fibnum); if (err) { log(LOG_WARNING, "in_rtqkill: error %d\n", err); } else { @@ -253,12 +254,31 @@ in_rtqkill(struct radix_node *rn, void *rock) static int rtq_timeout = RTQ_TIMEOUT; static struct callout rtq_timer; +static void in_rtqtimo_one(void *rock); + static void in_rtqtimo(void *rock) { + int fibnum; + void *newrock; + struct timeval atv; + + KASSERT((rock == (void *)rt_tables[0][AF_INET]), + ("in_rtqtimo: unexpected arg")); + for (fibnum = 0; fibnum < rt_numfibs; fibnum++) { + if ((newrock = rt_tables[fibnum][AF_INET]) != NULL) + in_rtqtimo_one(newrock); + } + atv.tv_usec = 0; + atv.tv_sec = rtq_timeout; + callout_reset(&rtq_timer, tvtohz(&atv), in_rtqtimo, rock); +} + +static void +in_rtqtimo_one(void *rock) +{ struct radix_node_head *rnh = rock; struct rtqk_arg arg; - struct timeval atv; static time_t last_adjusted_timeout = 0; arg.found = arg.killed = 0; @@ -297,27 +317,29 @@ in_rtqtimo(void *rock) RADIX_NODE_HEAD_UNLOCK(rnh); } - atv.tv_usec = 0; - atv.tv_sec = arg.nextstop - time_uptime; - callout_reset(&rtq_timer, tvtohz(&atv), in_rtqtimo, rock); } void in_rtqdrain(void) { - struct radix_node_head *rnh = rt_tables[AF_INET]; + struct radix_node_head *rnh; struct rtqk_arg arg; + int fibnum; - arg.found = arg.killed = 0; - arg.rnh = rnh; - arg.nextstop = 0; - arg.draining = 1; - arg.updating = 0; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_rtqkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); + for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { + rnh = rt_tables[fibnum][AF_INET]; + arg.found = arg.killed = 0; + arg.rnh = rnh; + arg.nextstop = 0; + arg.draining = 1; + arg.updating = 0; + RADIX_NODE_HEAD_LOCK(rnh); + rnh->rnh_walktree(rnh, in_rtqkill, &arg); + RADIX_NODE_HEAD_UNLOCK(rnh); + } } +static int _in_rt_was_here; /* * Initialize our routing tree. */ @@ -326,18 +348,29 @@ in_inithead(void **head, int off) { struct radix_node_head *rnh; - if (!rn_inithead(head, off)) + /* XXX MRT + * This can be called from vfs_export.c too in which case 'off' + * will be 0. We know the correct value so just use that and + * return directly if it was 0. + * This is a hack that replaces an even worse hack on a bad hack + * on a bad design. After RELENG_7 this should be fixed but that + * will change the ABI, so for now do it this way. + */ + if (!rn_inithead(head, 32)) return 0; - if (head != (void **)&rt_tables[AF_INET]) /* BOGUS! */ - return 1; /* only do this for the real routing table */ + if (off == 0) /* XXX MRT see above */ + return 1; /* only do the rest for a real routing table */ rnh = *head; rnh->rnh_addaddr = in_addroute; rnh->rnh_matchaddr = in_matroute; rnh->rnh_close = in_clsroute; - callout_init(&rtq_timer, CALLOUT_MPSAFE); - in_rtqtimo(rnh); /* kick off timeout first time */ + if (_in_rt_was_here == 0 ) { + callout_init(&rtq_timer, CALLOUT_MPSAFE); + in_rtqtimo(rnh); /* kick off timeout first time */ + _in_rt_was_here = 1; + } return 1; } @@ -384,16 +417,81 @@ in_ifadown(struct ifaddr *ifa, int delete) { struct in_ifadown_arg arg; struct radix_node_head *rnh; + int fibnum; if (ifa->ifa_addr->sa_family != AF_INET) return 1; - rnh = rt_tables[AF_INET]; - arg.ifa = ifa; - arg.del = delete; - RADIX_NODE_HEAD_LOCK(rnh); - rnh->rnh_walktree(rnh, in_ifadownkill, &arg); - RADIX_NODE_HEAD_UNLOCK(rnh); - ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ + for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { + rnh = rt_tables[fibnum][AF_INET]; + arg.ifa = ifa; + arg.del = delete; + RADIX_NODE_HEAD_LOCK(rnh); + rnh->rnh_walktree(rnh, in_ifadownkill, &arg); + RADIX_NODE_HEAD_UNLOCK(rnh); + ifa->ifa_flags &= ~IFA_ROUTE; /* XXXlocking? */ + } return 0; } + +/* + * inet versions of rt functions. These have fib extensions and + * for now will just reference the _fib variants. + * eventually this order will be reversed, + */ +void +in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum) +{ + rtalloc_ign_fib(ro, ignflags, fibnum); +} + +int +in_rtrequest( int req, + struct sockaddr *dst, + struct sockaddr *gateway, + struct sockaddr *netmask, + int flags, + struct rtentry **ret_nrt, + u_int fibnum) +{ + return (rtrequest_fib(req, dst, gateway, netmask, + flags, ret_nrt, fibnum)); +} + +struct rtentry * +in_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum) +{ + return (rtalloc1_fib(dst, report, ignflags, fibnum)); +} + +int +in_rt_check(struct rtentry **lrt, struct rtentry **lrt0, + struct sockaddr *dst, u_int fibnum) +{ + return (rt_check_fib(lrt, lrt0, dst, fibnum)); +} + +void +in_rtredirect(struct sockaddr *dst, + struct sockaddr *gateway, + struct sockaddr *netmask, + int flags, + struct sockaddr *src, + u_int fibnum) +{ + rtredirect_fib(dst, gateway, netmask, flags, src, fibnum); +} + +void +in_rtalloc(struct route *ro, u_int fibnum) +{ + rtalloc_ign_fib(ro, 0UL, fibnum); +} + +#if 0 +int in_rt_getifa(struct rt_addrinfo *, u_int fibnum); +int in_rtioctl(u_long, caddr_t, u_int); +int in_rtrequest1(int, struct rt_addrinfo *, struct rtentry **, u_int); +#endif + + diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 47a160a..d7f1e28 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -287,6 +287,7 @@ do { \ IN_NEXT_MULTI((step), (inm)); \ } while(0) +struct rtentry; struct route; struct ip_moptions; @@ -305,6 +306,21 @@ int in_ifadown(struct ifaddr *ifa, int); void in_ifscrub(struct ifnet *, struct in_ifaddr *); struct mbuf *ip_fastforward(struct mbuf *); +/* XXX */ +void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum); +void in_rtalloc(struct route *ro, u_int fibnum); +struct rtentry *in_rtalloc1(struct sockaddr *, int, u_long, u_int); +void in_rtredirect(struct sockaddr *, struct sockaddr *, + struct sockaddr *, int, struct sockaddr *, u_int); +int in_rtrequest(int, struct sockaddr *, + struct sockaddr *, struct sockaddr *, int, struct rtentry **, u_int); +int in_rt_check(struct rtentry **, struct rtentry **, struct sockaddr *, u_int); + +#if 0 +int in_rt_getifa(struct rt_addrinfo *, u_int fibnum); +int in_rtioctl(u_long, caddr_t, u_int); +int in_rtrequest1(int, struct rt_addrinfo *, struct rtentry **, u_int); +#endif #endif /* _KERNEL */ /* INET6 stuff */ diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 97b823f..bb8c74a 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -123,7 +123,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr.s_addr = dest.s_addr; - rtalloc_ign(ro, RTF_CLONING); + in_rtalloc_ign(ro, RTF_CLONING, M_GETFIB(m)); /* * Route there and interface still up? diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index b41c037..5dcdbb3 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -161,6 +161,9 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_TAG, /* arg1=tag number */ O_TAGGED, /* arg1=tag number */ + O_SETFIB, /* arg1=FIB number */ + O_FIB, /* arg1=FIB desired fib number */ + O_LAST_OPCODE /* not an opcode! */ }; @@ -465,6 +468,7 @@ struct ipfw_flow_id { u_int32_t src_ip; u_int16_t dst_port; u_int16_t src_port; + u_int8_t fib; u_int8_t proto; u_int8_t flags; /* protocol-specific flags */ uint8_t addr_type; /* 4 = ipv4, 6 = ipv6, 1=ether ? */ diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 39baa71..2346df6 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -492,7 +492,7 @@ iface_match(struct ifnet *ifp, ipfw_insn_if *cmd) * multicast, or broadcast. */ static int -verify_path(struct in_addr src, struct ifnet *ifp) +verify_path(struct in_addr src, struct ifnet *ifp, u_int fib) { struct route ro; struct sockaddr_in *dst; @@ -503,7 +503,7 @@ verify_path(struct in_addr src, struct ifnet *ifp) dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = src; - rtalloc_ign(&ro, RTF_CLONING); + in_rtalloc_ign(&ro, RTF_CLONING, fib); if (ro.ro_rt == NULL) return 0; @@ -593,6 +593,7 @@ verify_path6(struct in6_addr *src, struct ifnet *ifp) dst->sin6_family = AF_INET6; dst->sin6_len = sizeof(*dst); dst->sin6_addr = *src; + /* XXX MRT 0 for ipv6 at this time */ rtalloc_ign((struct route *)&ro, RTF_CLONING); if (ro.ro_rt == NULL) @@ -828,6 +829,10 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, snprintf(SNPARGS(action2, 0), "Tee %d", cmd->arg1); break; + case O_SETFIB: + snprintf(SNPARGS(action2, 0), "SetFib %d", + cmd->arg1); + break; case O_SKIPTO: snprintf(SNPARGS(action2, 0), "SkipTo %d", cmd->arg1); @@ -1500,6 +1505,7 @@ install_state(struct ip_fw *rule, ipfw_insn_limit *cmd, id.dst_ip = id.src_ip = id.dst_port = id.src_port = 0; id.proto = args->f_id.proto; id.addr_type = args->f_id.addr_type; + id.fib = M_GETFIB(args->m); if (IS_IP6_FLOW_ID (&(args->f_id))) { if (limit_mask & DYN_SRC_ADDR) @@ -1601,6 +1607,7 @@ send_pkt(struct mbuf *replyto, struct ipfw_flow_id *id, u_int32_t seq, return (NULL); m->m_pkthdr.rcvif = (struct ifnet *)0; + M_SETFIB(m, id->fib); #ifdef MAC if (replyto != NULL) mac_netinet_firewall_reply(replyto, m); @@ -2200,6 +2207,7 @@ ipfw_chk(struct ip_fw_args *args) return (IP_FW_PASS); /* accept */ pktlen = m->m_pkthdr.len; + args->f_id.fib = M_GETFIB(m); /* note mbuf not altered) */ proto = args->f_id.proto = 0; /* mark f_id invalid */ /* XXX 0 is a valid proto: IP/IPv6 Hop-by-Hop Option */ @@ -2911,7 +2919,8 @@ check_body: verify_path6(&(args->f_id.src_ip6), m->m_pkthdr.rcvif) : #endif - verify_path(src_ip, m->m_pkthdr.rcvif))); + verify_path(src_ip, m->m_pkthdr.rcvif, + args->f_id.fib))); break; case O_VERSRCREACH: @@ -2922,7 +2931,7 @@ check_body: verify_path6(&(args->f_id.src_ip6), NULL) : #endif - verify_path(src_ip, NULL))); + verify_path(src_ip, NULL, args->f_id.fib))); break; case O_ANTISPOOF: @@ -2941,7 +2950,8 @@ check_body: m->m_pkthdr.rcvif) : #endif verify_path(src_ip, - m->m_pkthdr.rcvif); + m->m_pkthdr.rcvif, + args->f_id.fib); else match = 1; break; @@ -3043,6 +3053,11 @@ check_body: break; } + case O_FIB: /* try match the specified fib */ + if (args->f_id.fib == cmd->arg1) + match = 1; + break; + case O_TAGGED: { uint32_t tag = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; @@ -3203,7 +3218,6 @@ check_body: IP_FW_DIVERT : IP_FW_TEE; goto done; } - case O_COUNT: case O_SKIPTO: f->pcnt++; /* update stats */ @@ -3283,6 +3297,14 @@ check_body: IP_FW_NETGRAPH : IP_FW_NGTEE; goto done; + case O_SETFIB: + f->pcnt++; /* update stats */ + f->bcnt += pktlen; + f->timestamp = time_uptime; + M_SETFIB(m, cmd->arg1); + args->f_id.fib = cmd->arg1; + goto next_rule; + case O_NAT: { struct cfg_nat *t; int nat_id; @@ -3793,6 +3815,26 @@ check_ipfw_struct(struct ip_fw *rule, int size) goto bad_size; break; + case O_FIB: + if (cmdlen != F_INSN_SIZE(ipfw_insn)) + goto bad_size; + if (cmd->arg1 >= rt_numfibs) { + printf("ipfw: invalid fib number %d\n", + cmd->arg1); + return EINVAL; + } + break; + + case O_SETFIB: + if (cmdlen != F_INSN_SIZE(ipfw_insn)) + goto bad_size; + if (cmd->arg1 >= rt_numfibs) { + printf("ipfw: invalid fib number %d\n", + cmd->arg1); + return EINVAL; + } + goto check_action; + case O_UID: case O_GID: case O_JAIL: diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 4f664bf..bed9536 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -227,6 +227,10 @@ stdreply: icmpelen = max(8, min(icmp_quotelen, oip->ip_len - oiphlen)); m_align(m, ICMP_MINLEN + icmplen); m->m_len = ICMP_MINLEN + icmplen; + /* XXX MRT make the outgoing packet use the same FIB + * that was associated with the incoming packet + */ + M_SETFIB(m, M_GETFIB(n)); icp = mtod(m, struct icmp *); icmpstat.icps_outhist[type]++; icp->icmp_type = type; @@ -295,6 +299,7 @@ icmp_input(struct mbuf *m, int off) int icmplen = ip->ip_len; int i, code; void (*ctlfunc)(int, struct sockaddr *, void *); + int fibnum; /* * Locate icmp structure in mbuf, and check @@ -576,10 +581,12 @@ reflect: } #endif icmpsrc.sin_addr = icp->icmp_ip.ip_dst; - rtredirect((struct sockaddr *)&icmpsrc, - (struct sockaddr *)&icmpdst, - (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, - (struct sockaddr *)&icmpgw); + for ( fibnum = 0; fibnum < rt_numfibs; fibnum++) { + in_rtredirect((struct sockaddr *)&icmpsrc, + (struct sockaddr *)&icmpdst, + (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST, + (struct sockaddr *)&icmpgw, fibnum); + } pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc); #ifdef IPSEC key_sa_routechange((struct sockaddr *)&icmpsrc); @@ -693,7 +700,7 @@ icmp_reflect(struct mbuf *m) * When we don't have a route back to the packet source, stop here * and drop the packet. */ - ia = ip_rtaddr(ip->ip_dst); + ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m)); if (ia == NULL) { m_freem(m); icmpstat.icps_noroute++; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 1eb9e4a..93ba871 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1198,7 +1198,7 @@ ipproto_unregister(u_char ipproto) * return internet address info of interface to be used to get there. */ struct in_ifaddr * -ip_rtaddr(struct in_addr dst) +ip_rtaddr(struct in_addr dst, u_int fibnum) { struct route sro; struct sockaddr_in *sin; @@ -1209,7 +1209,7 @@ ip_rtaddr(struct in_addr dst) sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = dst; - rtalloc_ign(&sro, RTF_CLONING); + in_rtalloc_ign(&sro, RTF_CLONING, fibnum); if (sro.ro_rt == NULL) return (NULL); @@ -1269,7 +1269,7 @@ ip_forward(struct mbuf *m, int srcrt) } #endif - ia = ip_rtaddr(ip->ip_dst); + ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m)); if (!srcrt && ia == NULL) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); return; @@ -1334,7 +1334,7 @@ ip_forward(struct mbuf *m, int srcrt) sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; - rtalloc_ign(&ro, RTF_CLONING); + in_rtalloc_ign(&ro, RTF_CLONING, M_GETFIB(m)); rt = ro.ro_rt; @@ -1363,7 +1363,7 @@ ip_forward(struct mbuf *m, int srcrt) * the ICMP_UNREACH_NEEDFRAG "Next-Hop MTU" field described in RFC1191. */ bzero(&ro, sizeof(ro)); - rtalloc_ign(&ro, RTF_CLONING); + rtalloc_ign_fib(&ro, RTF_CLONING, M_GETFIB(m)); error = ip_output(m, NULL, &ro, IP_FORWARDING, NULL, NULL); diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 6e0e124..d60e8bd 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -303,7 +303,7 @@ static int X_ip_mrouter_done(void); static int X_ip_mrouter_get(struct socket *so, struct sockopt *m); static int X_ip_mrouter_set(struct socket *so, struct sockopt *m); static int X_legal_vif_num(int vif); -static int X_mrt_ioctl(int cmd, caddr_t data); +static int X_mrt_ioctl(int cmd, caddr_t data, int fibnum); static int get_sg_cnt(struct sioc_sg_req *); static int get_vif_cnt(struct sioc_vif_req *); @@ -552,7 +552,7 @@ X_ip_mrouter_get(struct socket *so, struct sockopt *sopt) * Handle ioctl commands to obtain information from the cache */ static int -X_mrt_ioctl(int cmd, caddr_t data) +X_mrt_ioctl(int cmd, caddr_t data, int fibnum) { int error = 0; diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h index c756d84..4043e44 100644 --- a/sys/netinet/ip_mroute.h +++ b/sys/netinet/ip_mroute.h @@ -359,7 +359,7 @@ struct sockopt; extern int (*ip_mrouter_set)(struct socket *, struct sockopt *); extern int (*ip_mrouter_get)(struct socket *, struct sockopt *); extern int (*ip_mrouter_done)(void); -extern int (*mrt_ioctl)(int, caddr_t); +extern int (*mrt_ioctl)(int, caddr_t, int); #endif /* _KERNEL */ diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index 72b6edd..0019f7a 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -233,7 +233,8 @@ dropit: if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == NULL) ia = (INA)ifa_ifwithnet((SA)&ipaddr); } else - ia = ip_rtaddr(ipaddr.sin_addr); +/* XXX MRT 0 for routing */ + ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m)); if (ia == NULL) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; @@ -276,7 +277,7 @@ dropit: * same). */ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == NULL && - (ia = ip_rtaddr(ipaddr.sin_addr)) == NULL) { + (ia = ip_rtaddr(ipaddr.sin_addr, M_GETFIB(m))) == NULL) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 37995ef..231510a 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -230,10 +230,12 @@ again: */ if (ro->ro_rt == NULL) #ifdef RADIX_MPATH - rtalloc_mpath(ro, - ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr)); + rtalloc_mpath_fib(ro, + ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr), + inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m)); #else - rtalloc_ign(ro, 0); + in_rtalloc_ign(ro, 0, + inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m)); #endif if (ro->ro_rt == NULL) { ipstat.ips_noroute++; diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index eef4e1f..436a4a0 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -209,7 +209,7 @@ int ipproto_unregister(u_char); struct mbuf * ip_reass(struct mbuf *); struct in_ifaddr * - ip_rtaddr(struct in_addr); + ip_rtaddr(struct in_addr, u_int fibnum); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); void ip_slowtimo(void); diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 23ab1fe..2e9366f 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -95,7 +95,7 @@ int (*ip_mrouter_get)(struct socket *, struct sockopt *); int (*ip_mrouter_done)(void); int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *, struct ip_moptions *); -int (*mrt_ioctl)(int, caddr_t); +int (*mrt_ioctl)(int, caddr_t, int); int (*legal_vif_num)(int); u_long (*ip_mcast_src)(int); diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index b165943..01c0fcb 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -399,7 +399,7 @@ typedef struct callout sctp_os_timer_t; typedef struct route sctp_route_t; typedef struct rtentry sctp_rtentry_t; -#define SCTP_RTALLOC(ro, vrf_id) rtalloc_ign((struct route *)ro, 0UL) +#define SCTP_RTALLOC(ro, vrf_id) in_rtalloc_ign((struct route *)ro, 0UL, vrf_id) /* Future zero copy wakeup/send function */ #define SCTP_ZERO_COPY_EVENT(inp, so) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index a344ae5..47763c1 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -453,6 +453,7 @@ findpcb: /* * If the INPCB does not exist then all data in the incoming * segment is discarded and an appropriate RST is sent back. + * XXX MRT Send RST using which routing table? */ if (inp == NULL) { /* diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index aaac6d6..36422197 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -471,6 +471,10 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, bcopy((caddr_t)th, (caddr_t)nth, sizeof(struct tcphdr)); flags = TH_ACK; } else { + /* + * reuse the mbuf. + * XXX MRT We inherrit the FIB, which is lucky. + */ m_freem(m->m_next); m->m_next = NULL; m->m_data = (caddr_t)ipgen; @@ -1199,6 +1203,8 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip) bzero(&inc, sizeof(inc)); inc.inc_flags = 0; /* IPv4 */ inc.inc_faddr = faddr; + inc.inc_fibnum = + inp->inp_inc.inc_fibnum; mtu = ntohs(icp->icmp_nextmtu); /* @@ -1595,7 +1601,7 @@ tcp_maxmtu(struct in_conninfo *inc, int *flags) dst->sin_family = AF_INET; dst->sin_len = sizeof(*dst); dst->sin_addr = inc->inc_faddr; - rtalloc_ign(&sro, RTF_CLONING); + in_rtalloc_ign(&sro, RTF_CLONING, inc->inc_fibnum); } if (sro.ro_rt != NULL) { ifp = sro.ro_rt->rt_ifp; diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index d5694f3..e19f095 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -671,6 +671,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) #endif inp = sotoinpcb(so); + inp->inp_inc.inc_fibnum = sc->sc_inc.inc_fibnum; + so->so_fibnum = sc->sc_inc.inc_fibnum; INP_WLOCK(inp); /* Insert new socket into PCB hash list. */ @@ -941,6 +943,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, else tcpstat.tcps_sc_completed++; +/* how do we find the inp for the new socket? */ if (sc != &scs) syncache_free(sc); return (1); @@ -1127,6 +1130,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, sc->sc_label = maclabel; #endif sc->sc_ipopts = ipopts; + sc->sc_inc.inc_fibnum = inp->inp_inc.inc_fibnum; bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo)); #ifdef INET6 if (!inc->inc_isipv6) |