--- M:/emaste_photon/fw-bsd/src/sys/netinet/if_ether.c@@/main/RELENG_5/6 2005-03-21 17:05:35.000000000 -0400 +++ M:/emaste_photon/fw-bsd/src/sys/netinet/if_ether.c@@/main/sandvine_bsd_5_2/sandvine_bsd_5_main/8 2005-05-05 10:30:54.000000000 -0400 @@ -82,6 +82,8 @@ SYSCTL_NODE(_net_link_ether, PF_INET, in static int arpt_prune = (5*60*1); /* walk list every 5 minutes */ static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ static int arpt_down = 20; /* once declared down, don't send for 20 sec */ +static int arpt_forged = 0; /* count of arpForgeRoute calls */ +static int arpt_forge_enable = 1; /* enable forge route mode */ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW, &arpt_prune, 0, ""); @@ -89,6 +91,10 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUT &arpt_keep, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW, &arpt_down, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_forged, CTLFLAG_RD, + &arpt_forged, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, arp_forge_enable, CTLFLAG_RW, + &arpt_forge_enable, 0, ""); #define rt_expire rt_rmx.rmx_expire @@ -385,8 +391,14 @@ arpresolve(struct ifnet *ifp, struct rte ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); return (0); } - if (rt) + if (rt) { la = (struct llinfo_arp *)rt->rt_llinfo; + sdl = SDL(rt->rt_gateway); + if (sdl && sdl->sdl_family == AF_LINK && rt->rt_expire == 0) { + bcopy(LLADDR(sdl), desten, sdl->sdl_alen); + return 0; + } + } if (la == 0) { la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0); if (la) @@ -464,6 +476,45 @@ arpresolve(struct ifnet *ifp, struct rte return (EWOULDBLOCK); } +extern int rttrash; +void +arpForgeRoute(struct ifnet *ifp, + struct route *rt, + struct in_addr *ip, + struct ether_header *eh) +{ + if (arpt_forge_enable) { + struct sockaddr_dl *dl = 0; + struct sockaddr_in *sin; + + /* If there's already a route, free it first */ + if (rt->ro_rt) + RTFREE(rt->ro_rt); + rt->ro_rt=0; + bzero(&rt->ro_dst, sizeof(struct sockaddr)); + + R_Malloc(dl, struct sockaddr_dl *, sizeof(struct sockaddr_dl)); + if (!dl) + return; + + arpt_forged++; + sin=(struct sockaddr_in*)&rt->ro_dst; + sin->sin_family = AF_INET; + sin->sin_len = sizeof(struct sockaddr_in); + sin->sin_addr.s_addr = ip->s_addr; + + bzero(dl, sizeof(*dl)); + dl->sdl_len = sizeof(struct sockaddr_dl); + dl->sdl_family = AF_LINK; + dl->sdl_alen = ETHER_ADDR_LEN; + dl->sdl_index = ifp->if_index; + dl->sdl_type = ifp->if_type; + memcpy(LLADDR(dl), eh->ether_shost,ETHER_ADDR_LEN); + + rt->ro_rt=rtforge((struct sockaddr*)dl, ifp); + } +} + /* * Common length and type checks are done here, * then the protocol-specific routine is called. --- M:/emaste_photon/fw-bsd/src/sys/netinet/tcp_input.c@@/main/RELENG_5/21 2005-07-05 19:25:42.000000000 -0400 +++ M:/emaste_photon/fw-bsd/src/sys/netinet/tcp_input.c@@/main/sandvine_bsd_5_2/sandvine_bsd_5_main/10 2006-05-29 14:04:09.000000000 -0400 @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ #ifdef TCPDEBUG #include #endif /* TCPDEBUG */ +#include #ifdef FAST_IPSEC #include @@ -439,6 +441,7 @@ tcp_input(m, off0) int headlocked = 0; #ifdef IPFIREWALL_FORWARD struct m_tag *fwd_tag; + struct sockaddr_in *next_hop = 0; #endif int rstreason; /* For badport_bandlim accounting purposes */ @@ -458,7 +461,23 @@ tcp_input(m, off0) struct tcphdr tcp_savetcp; short ostate = 0; #endif + struct ether_header *eh = 0; /* From ether_input if + using ipfw fwd & coming + from ethernet interface + */ + struct ether_header saved_eh; + struct rtentry *forged_route = 0; + int prev_line_number = 0; + + + { + struct m_tag *mtag = m_tag_find(m, PACKET_TAG_ETHERFORWARD, NULL); + if (mtag != 0) { + eh = (struct ether_header *)(mtag +1); + } + + } #ifdef INET6 isipv6 = (mtod(m, struct ip *)->ip_v == 6) ? 1 : 0; #endif @@ -503,6 +522,11 @@ tcp_input(m, off0) off0 = sizeof(struct ip); } if (m->m_len < sizeof (struct tcpiphdr)) { + if (eh) { + saved_eh = *eh; + eh = &saved_eh; + } + if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) { tcpstat.tcps_rcvshort++; return; @@ -566,6 +590,11 @@ tcp_input(m, off0) #endif } else { if (m->m_len < sizeof(struct ip) + off) { + if (eh && eh != &saved_eh) { + saved_eh = *eh; + eh = &saved_eh; + } + if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) { tcpstat.tcps_rcvshort++; @@ -625,7 +654,6 @@ findpcb: fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); if (fwd_tag != NULL && isipv6 == 0) { /* IPv6 support is not yet */ - struct sockaddr_in *next_hop; next_hop = (struct sockaddr_in *)(fwd_tag+1); /* @@ -793,6 +821,7 @@ findpcb: #endif if (so->so_options & SO_ACCEPTCONN) { struct in_conninfo inc; + bzero(&inc, sizeof(inc)); #ifdef INET6 inc.inc_isipv6 = isipv6; @@ -964,6 +993,23 @@ findpcb: tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen, &tcp_savetcp, 0); #endif +#ifdef IPFIREWALL_FORWARD + /* If we've created it, forge the route so we can + * be sure to go back to the same spot if we're + * using multipath routing. We forge this as + * a HOST route, with the LLA already known */ + if (next_hop && eh) { + arpForgeRoute(m->m_pkthdr.rcvif, + &inc.inc_froute, + &ip->ip_src, + eh); + forged_route = inc.inc_froute.ro_rt; + } else { + memset(&inc.inc_froute,0,sizeof(inc.inc_froute)); + } +#else + memset(&inc.inc_froute,0,sizeof(inc.inc_froute)); +#endif tcp_dooptions(tp, &to, optp, optlen, 1, th); if (!syncache_add(&inc, &to, th, &so, m)) goto drop; @@ -1699,6 +1745,7 @@ trimthenstep6: tcpstat.tcps_rcvduppack++; tcpstat.tcps_rcvdupbyte += tlen; tcpstat.tcps_pawsdrop++; + prev_line_number = __LINE__; if (tlen) goto dropafterack; goto drop; @@ -1713,7 +1760,10 @@ trimthenstep6: */ if ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) == (TF_REQ_CC|TF_RCVD_CC) && ((to.to_flags & TOF_CC) == 0 || tp->cc_recv != to.to_cc)) - goto dropafterack; + { + prev_line_number = __LINE__; + goto dropafterack; + } /* * In the SYN-RECEIVED state, validate that the packet belongs to @@ -1822,7 +1872,10 @@ trimthenstep6: tp->t_flags |= TF_ACKNOW; tcpstat.tcps_rcvwinprobe++; } else - goto dropafterack; + { + prev_line_number = __LINE__; + goto dropafterack; + } } else tcpstat.tcps_rcvbyteafterwin += todrop; m_adj(m, -todrop); @@ -2131,6 +2184,7 @@ trimthenstep6: tp->t_dupacks = 0; if (SEQ_GT(th->th_ack, tp->snd_max)) { tcpstat.tcps_rcvacktoomuch++; + prev_line_number = __LINE__; goto dropafterack; } /* @@ -2338,6 +2392,7 @@ process_ACK: KASSERT(tp->t_state != TCPS_TIME_WAIT, ("timewait")); callout_reset(tp->tt_2msl, 2 * tcp_msl, tcp_timer_2msl, tp); + prev_line_number = __LINE__; goto dropafterack; } } @@ -2610,6 +2665,11 @@ dropafterack: #endif KASSERT(headlocked, ("headlocked should be 1")); INP_INFO_WUNLOCK(&tcbinfo); + if (tp->snd_nxt - tp->snd_una < 0) { + log(LOG_CRIT, + "dropafterack: tp->snd_nxt - tp->snd_una < 0, jumped from %d\n", + prev_line_number); + } tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); INP_UNLOCK(inp); @@ -2669,6 +2729,9 @@ dropwithreset: return; drop: + if (forged_route) + rtfree(forged_route); + /* * Drop space held by incoming segment and return. */ @@ -2859,6 +2922,9 @@ tcp_xmit_timer(tp, rtt) INP_LOCK_ASSERT(tp->t_inpcb); + if (rtt < 0) { + return; + } tcpstat.tcps_rttupdated++; tp->t_rttupdated++; if (tp->t_srtt != 0) { @@ -2981,6 +3047,15 @@ tcp_mss(tp, offer) #endif bzero(&tao, sizeof(tao)); + so = inp->inp_socket; + + /* + * Looking at the offer and finding the mtu is not necessary, if + * the mss is being overridden + */ + if (tp->t_flags & TF_MSSOVERRIDE) + goto mssoverride; + /* initialize */ #ifdef INET6 if (isipv6) { @@ -2991,8 +3066,8 @@ tcp_mss(tp, offer) { maxmtu = tcp_maxmtu(&inp->inp_inc); tp->t_maxopd = tp->t_maxseg = tcp_mssdflt; + } - so = inp->inp_socket; /* * no route to sender, stay with default mss and return @@ -3050,8 +3125,8 @@ tcp_mss(tp, offer) /* * if there's a discovered mtu int tcp hostcache, use it - * else, use the link mtu. - */ + * else, use the link mtu. + */ if (metrics.rmx_mtu) mss = min(metrics.rmx_mtu, maxmtu) - min_protoh; else { @@ -3073,6 +3148,15 @@ tcp_mss(tp, offer) mss = min(mss, offer); /* + * If the TCP_MSSOVERRIDE option was specified, + * tp->t_maxopd would contain the forced MSS, so ignore mss and use same + * steps to chop tp->t_maxopd down to a 'sensible' tp->t_maxseg. + */ +mssoverride: + if (tp->t_flags & TF_MSSOVERRIDE) + mss = tp->t_maxopd; + + /* * maxopd stores the maximum length of data AND options * in a segment; maxseg is the amount of data in a normal * segment. We need to store this value (maxopd) apart @@ -3370,6 +3454,14 @@ tcp_timewait(tw, to, th, m, tlen) */ if ((thflags & TH_SYN) && SEQ_GT(th->th_seq, tw->rcv_nxt)) { (void) tcp_twclose(tw, 0); +#if 0 + if (rt == NULL && !(tp->t_flags & TF_MSSOVERRIDE)) + + if (tp->t_flags & TF_MSSOVERRIDE) + return tp->t_maxopd; + else + return rt->rt_ifp->if_mtu - min_protoh; +#endif return (1); } --- M:/emaste_photon/fw-bsd/src/sys/netinet/if_ether.h@@/main/RELENG_5/2 2005-03-21 17:05:35.000000000 -0400 +++ M:/emaste_photon/fw-bsd/src/sys/netinet/if_ether.h@@/main/sandvine_bsd_5_main/2 2005-05-06 12:53:53.000000000 -0400 @@ -113,6 +113,11 @@ int arpresolve(struct ifnet *ifp, struct struct mbuf *m, struct sockaddr *dst, u_char *desten); void arp_ifinit(struct ifnet *, struct ifaddr *); void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *); +struct route; +void arpForgeRoute(struct ifnet *ifp, + struct route *rt, + struct in_addr *ip, + struct ether_header *eh); #endif #endif --- M:/emaste_photon/fw-bsd/src/sys/netinet/tcp_syncache.c@@/main/RELENG_5/5 2006-02-16 18:05:03.000000000 -0500 +++ M:/emaste_photon/fw-bsd/src/sys/netinet/tcp_syncache.c@@/main/sandvine_bsd_5_main/8 2006-05-29 14:04:01.000000000 -0400 @@ -100,12 +100,14 @@ #include #include +static int syncache_delete_flag; static int tcp_syncookies = 1; SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_RW, &tcp_syncookies, 0, "Use TCP SYN cookies if the syncache overflows"); static void syncache_drop(struct syncache *, struct syncache_head *); +static void syncache_delete(struct syncache *, struct syncache_head *); static void syncache_free(struct syncache *); static void syncache_insert(struct syncache *, struct syncache_head *); struct syncache *syncache_lookup(struct in_conninfo *, struct syncache_head **); @@ -146,6 +148,7 @@ struct tcp_syncache { struct callout tt_timerq[SYNCACHE_MAXREXMTS + 1]; }; static struct tcp_syncache tcp_syncache; +static TAILQ_HEAD(syncache_delete_list, syncache) sc_delete_list; SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0, "TCP SYN cache"); @@ -187,7 +190,7 @@ static MALLOC_DEFINE(M_SYNCACHE, "syncac #define ENDPTS6_EQ(a, b) (memcmp(a, b, sizeof(*a)) == 0) -#define SYNCACHE_TIMEOUT(sc, slot) do { \ +#define SYNCACHE_TIMEOUT(sc, slot) do { \ sc->sc_rxtslot = (slot); \ sc->sc_rxttime = ticks + TCPTV_RTOBASE * tcp_backoff[(slot)]; \ TAILQ_INSERT_TAIL(&tcp_syncache.timerq[(slot)], sc, sc_timerq); \ @@ -202,6 +205,14 @@ syncache_free(struct syncache *sc) { if (sc->sc_ipopts) (void) m_free(sc->sc_ipopts); + if (sc->sc_froute.ro_rt) { + /* If we have an arpForgeRoute'd route, delete it */ + RTFREE(sc->sc_froute.ro_rt); + } + sc->sc_tp = NULL; +#if defined(DIAGNOSTIC) + memset(sc, 0xee, sizeof(struct syncache)); +#endif uma_zfree(tcp_syncache.zone, sc); } @@ -258,6 +269,8 @@ syncache_init(void) NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uma_zone_set_max(tcp_syncache.zone, tcp_syncache.cache_limit); tcp_syncache.cache_limit -= 1; + TAILQ_INIT(&sc_delete_list); + } static void @@ -314,6 +327,18 @@ syncache_drop(sc, sch) struct syncache *sc; struct syncache_head *sch; { + if ((sc->sc_flags & SCF_DELETE) == 0) { + sc->sc_flags |= SCF_DELETE; + syncache_delete_flag = 1; + TAILQ_INSERT_TAIL(&sc_delete_list, sc, sc_delete); + } +} + +static void +syncache_delete(sc, sch) + struct syncache *sc; + struct syncache_head *sch; +{ INP_INFO_WLOCK_ASSERT(&tcbinfo); if (sch == NULL) { @@ -329,6 +354,8 @@ syncache_drop(sc, sch) } } + TAILQ_REMOVE(&sc_delete_list, sc, sc_delete); + TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash); sch->sch_length--; tcp_syncache.cache_count--; @@ -353,6 +380,7 @@ syncache_timer(xslot) struct inpcb *inp; INP_INFO_WLOCK(&tcbinfo); + if (callout_pending(&tcp_syncache.tt_timerq[slot]) || !callout_active(&tcp_syncache.tt_timerq[slot])) { /* XXX can this happen? */ @@ -361,6 +389,14 @@ syncache_timer(xslot) } callout_deactivate(&tcp_syncache.tt_timerq[slot]); + sc = TAILQ_FIRST(&sc_delete_list); + while (sc != NULL) { + nsc = TAILQ_NEXT(sc, sc_delete); + syncache_delete(sc, NULL); + sc = nsc; + } + TAILQ_INIT(&sc_delete_list); + nsc = TAILQ_FIRST(&tcp_syncache.timerq[slot]); while (nsc != NULL) { if (ticks < nsc->sc_rxttime) @@ -393,6 +429,16 @@ syncache_timer(xslot) if (nsc != NULL) callout_reset(&tcp_syncache.tt_timerq[slot], nsc->sc_rxttime - ticks, syncache_timer, (void *)(slot)); + + sc = TAILQ_FIRST(&sc_delete_list); + while (sc != NULL) { + nsc = TAILQ_NEXT(sc, sc_delete); + syncache_delete(sc, NULL); + sc = nsc; + } + TAILQ_INIT(&sc_delete_list); + syncache_delete_flag = 0; + INP_INFO_WUNLOCK(&tcbinfo); } @@ -866,6 +912,14 @@ syncache_add(inc, to, th, sop, m) (void) m_free(sc->sc_ipopts); sc->sc_ipopts = ipopts; } + if (sc->sc_froute.ro_rt) { + /* + * If we already have an arpForgeRoute'd + * route, delete it and use the new one + */ + RTFREE(sc->sc_froute.ro_rt); + sc->sc_froute = inc->inc_froute; + } /* * Update timestamp if present. */ @@ -934,6 +988,8 @@ syncache_add(inc, to, th, sop, m) { sc->sc_inc.inc_faddr = inc->inc_faddr; sc->sc_inc.inc_laddr = inc->inc_laddr; + sc->sc_inc.inc_froute = inc->inc_froute; + } sc->sc_irs = th->th_seq; sc->sc_flags = 0; @@ -1454,6 +1510,7 @@ syncookie_lookup(inc, th, so) sc = uma_zalloc(tcp_syncache.zone, M_NOWAIT | M_ZERO); if (sc == NULL) return (NULL); + bzero(sc, sizeof(*sc)); /* * Fill in the syncache values. * XXX duplicate code from syncache_add --- M:/emaste_photon/fw-bsd/src/sys/netinet/udp_usrreq.c@@/main/RELENG_5/RELENG_5_4/1 2005-05-06 02:51:10.000000000 -0400 +++ M:/emaste_photon/fw-bsd/src/sys/netinet/udp_usrreq.c@@/main/sandvine_bsd_5_2/sandvine_bsd_5_main/10 2006-05-02 23:25:35.000000000 -0400 @@ -30,9 +30,11 @@ * $FreeBSD$ */ +#include "opt_ipfw.h" /* for ipfw_fwd */ #include "opt_ipsec.h" #include "opt_inet6.h" #include "opt_mac.h" +#include "opt_prime.h" #include #include @@ -81,6 +83,10 @@ #ifdef IPSEC #include #endif /*IPSEC*/ +#ifdef PRIME +#include +#endif +#include #include @@ -138,7 +144,7 @@ udp_init() &udbinfo.porthashmask); udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); - uma_zone_set_max(udbinfo.ipi_zone, maxsockets); + uma_zone_set_max(udbinfo.ipi_zone, maxudpcb); } void @@ -154,9 +160,32 @@ udp_input(m, off) int len; struct ip save_ip; struct sockaddr_in udp_in; +#ifdef IPFIREWALL_FORWARD + struct sockaddr_in *next_hop = NULL; + struct m_tag *fwd_tag; +#endif + struct ether_header *eh = 0; /* From ether_input if + using ipfw fwd & coming + from ethernet interface + */ + struct ether_header saved_eh; udpstat.udps_ipackets++; +#ifdef IPFIREWALL_FORWARD + /* Grab info from MT_TAG mbufs prepended to the chain. */ + fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); + if (fwd_tag != NULL) + next_hop = (struct sockaddr_in*)(fwd_tag+1); + { + struct m_tag *mtag = m_tag_find(m, PACKET_TAG_ETHERFORWARD, NULL); + if (mtag != 0) { + eh = (struct ether_header *)(mtag +1); + } + + } +#endif + /* * Strip IP options, if any; should skip this, * make available to user, and use on returned packets, @@ -173,6 +202,10 @@ udp_input(m, off) */ ip = mtod(m, struct ip *); if (m->m_len < iphlen + sizeof(struct udphdr)) { + if (eh) { + saved_eh = *eh; + eh = &saved_eh; + } if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { udpstat.udps_hdrops++; return; @@ -356,6 +389,46 @@ udp_input(m, off) /* * Locate pcb for datagram. */ + +#ifdef IPFIREWALL_FORWARD + /* + * WARNING!!! INET6 not supported by UDP IPFW forwarding. + * Extra code needed similar to tcp_input + */ + if (next_hop != NULL) { + /* + * Transparently forwarded. Pretend to be the destination. + * already got one like this? + */ + inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport, + ip->ip_dst, uh->uh_dport, 0, m->m_pkthdr.rcvif); + + if (!inp) { + /* No, then it's new.*/ + if (!next_hop->sin_port) { + inp = in_pcblookup_hash(&udbinfo, ip->ip_src, + uh->uh_sport, next_hop->sin_addr, + uh->uh_dport, 1, m->m_pkthdr.rcvif); + } else { + inp = in_pcblookup_hash(&udbinfo, ip->ip_src, + uh->uh_sport, next_hop->sin_addr, + ntohs(next_hop->sin_port), 1, + m->m_pkthdr.rcvif); + + /* If we've created it, forge the route so we can + * be sure to go back to the same spot if we're + * using multipath routing. We forge this as + * a HOST route, with the LLA already known + */ + if (inp && eh) { + arpForgeRoute( m->m_pkthdr.rcvif, &inp->inp_froute, + &ip->ip_src, eh); + } + } + } + } else +#endif + inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif); if (inp == NULL) { @@ -452,7 +525,21 @@ udp_append(last, ip, n, off, udp_in) last->inp_flags = savedflags; } else #endif - ip_savecontrol(last, &opts, ip, n); + { + ip_savecontrol(last, &opts, ip, n); + if (last->inp_flags & INP_RECVDSTPORT) { + struct udphdr *uh; + struct mbuf **mp = &opts; + while (*mp) { + mp = &(*mp)->m_next; + } + uh = (struct udphdr *)((caddr_t)ip + + (off - sizeof(struct udphdr))); + *mp = sbcreatecontrol((caddr_t) &uh->uh_dport, + sizeof(u_int16_t), IP_RECVDSTPORT, + IPPROTO_IP); + } + } } #ifdef INET6 if (last->inp_vflag & INP_IPV6) { @@ -700,6 +787,7 @@ udp_output(inp, m, addr, control, td) int ipflags; u_short fport, lport; int unlock_udbinfo; + struct route *ro = NULL; /* * udp_output() may need to temporarily bind or connect the current @@ -878,7 +966,9 @@ udp_output(inp, m, addr, control, td) if (unlock_udbinfo) INP_INFO_WUNLOCK(&udbinfo); - error = ip_output(m, inp->inp_options, NULL, ipflags, + if (inp->inp_froute.ro_rt) + ro = &inp->inp_froute; + error = ip_output(m, inp->inp_options, ro, ipflags, inp->inp_moptions, inp); INP_UNLOCK(inp); return (error); @@ -988,6 +1078,9 @@ udp_connect(struct socket *so, struct so struct inpcb *inp; int s, error; struct sockaddr_in *sin; +#ifdef PRIME + struct sockaddr tmpAddr; +#endif /* PRIME */ INP_INFO_WLOCK(&udbinfo); inp = sotoinpcb(so); @@ -1006,9 +1099,26 @@ udp_connect(struct socket *so, struct so if (td && jailed(td->td_ucred)) prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr); error = in_pcbconnect(inp, nam, td->td_ucred); +#ifdef PRIME + memcpy( &tmpAddr, nam, sizeof(tmpAddr) ); + ((struct sockaddr_in *)(&tmpAddr))->sin_port = 0; + if ((ifa_ifwithaddr(&tmpAddr) == 0) && + error == 0 && + inp->inp_flags & INP_ALIENSRC && + inp->inp_socket->so_options & SO_PRIME) { + inp->inp_ip_p = IPPROTO_UDP; + error = prime_start(inp); + splx(s); + soisconnecting(so); + goto done; + } +#endif /* PRIME */ splx(s); if (error == 0) soisconnected(so); +#ifdef PRIME +done: +#endif /* PRIME */ INP_UNLOCK(inp); INP_INFO_WUNLOCK(&udbinfo); return error; @@ -1112,10 +1222,43 @@ udp_peeraddr(struct socket *so, struct s return (in_setpeeraddr(so, nam, &udbinfo)); } +#ifdef PRIME +#include +static int +udp_prime_poll(struct socket *so, int events, struct ucred *cred, + struct thread *td) +{ + int s=splnet(); + int revents=sopoll(so, events, cred, td); + + /* If poll says it's writable but it has a primecb it really isn't */ + if (revents & (POLLOUT | POLLWRNORM)) { + struct inpcb *inp; + inp = sotoinpcb(so); + if (inp && inp->inp_primecb) { + revents &= ~(POLLOUT | POLLWRNORM); + if (revents == 0) { + selrecord(td, &so->so_snd.sb_sel); + so->so_snd.sb_flags |= SB_SEL; + } + } + } + + splx(s); + return revents; +} +#endif /* PRIME */ + struct pr_usrreqs udp_usrreqs = { udp_abort, pru_accept_notsupp, udp_attach, udp_bind, udp_connect, pru_connect2_notsupp, in_control, udp_detach, udp_disconnect, pru_listen_notsupp, udp_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp, udp_send, pru_sense_null, udp_shutdown, - udp_sockaddr, sosend, soreceive, sopoll, in_pcbsosetlabel + udp_sockaddr, sosend, soreceive, +#ifdef PRIME + udp_prime_poll, +#else /* PRIME */ + sopoll, +#endif /* PRIME */ + in_pcbsosetlabel }; --- M:/emaste_photon/fw-bsd/src/sys/net/route.c@@/main/RELENG_5/2 2005-01-31 23:26:23.000000000 -0500 +++ M:/emaste_photon/fw-bsd/src/sys/net/route.c@@/main/sandvine_bsd_5_2/sandvine_bsd_5_main/6 2005-05-02 15:31:44.000000000 -0400 @@ -52,7 +52,7 @@ static struct rtstat rtstat; struct radix_node_head *rt_tables[AF_MAX+1]; -static int rttrash; /* routes not in table but not freed */ +int rttrash; /* routes not in table but not freed */ static void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *); @@ -222,6 +222,25 @@ rtalloc1(struct sockaddr *dst, int repor return (newrt); } + +/* + * Forge a route entry to the given sockaddr + */ +struct rtentry *rtforge(struct sockaddr *dst, struct ifnet *ifp) +{ + struct rtentry *rt = uma_zalloc(rtzone, M_NOWAIT | M_ZERO); + if (rt) { + ++rttrash; + RT_LOCK_INIT(rt); + rt->rt_rmx.rmx_expire = 0; + rt->rt_refcnt = 1; + rt->rt_gateway = (struct sockaddr *)dst; + rt->rt_ifp = ifp; + rt->rt_flags = RTF_UP | RTF_HOST | RTF_NOKEY; + } + return rt; +} + /* * Remove a reference count from an rtentry. * If the count gets low enough, take it out of the routing table @@ -229,14 +248,15 @@ rtalloc1(struct sockaddr *dst, int repor void rtfree(struct rtentry *rt) { - struct radix_node_head *rnh; + /* + * find the tree for that address family + */ + register struct radix_node_head *rnh = 0; - /* XXX the NULL checks are probably useless */ - if (rt == NULL) - panic("rtfree: NULL rt"); - rnh = rt_tables[rt_key(rt)->sa_family]; - if (rnh == NULL) - panic("rtfree: NULL rnh"); + if (rt == 0) + panic("rtfree"); + if (rt_key(rt)) + rnh = rt_tables[rt_key(rt)->sa_family]; RT_LOCK_ASSERT(rt); @@ -257,7 +277,7 @@ rtfree(struct rtentry *rt) * typically calls rtexpunge which clears the RTF_UP flag * on the entry so that the code below reclaims the storage. */ - if (rt->rt_refcnt == 0 && rnh->rnh_close) + if (rt->rt_refcnt == 0 && rnh && rnh->rnh_close) rnh->rnh_close((struct radix_node *)rt, rnh); /* @@ -265,8 +285,8 @@ rtfree(struct rtentry *rt) * then we can free the resources associated * with the route. */ - if ((rt->rt_flags & RTF_UP) == 0) { - if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) + if ((rt->rt_flags & RTF_UP) == 0 || !rnh) { + if (rnh && rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT)) panic ("rtfree 2"); /* * the rtentry must have been removed from the routing table @@ -292,7 +312,11 @@ rtfree(struct rtentry *rt) * This also frees the gateway, as they are always malloc'd * together. */ - Free(rt_key(rt)); + if (rt_key(rt)) + Free(rt_key(rt)); + if (rt->rt_flags & RTF_NOKEY) + Free(rt->rt_gateway); + /* * and the rtentry itself of course --- M:/emaste_photon/fw-bsd/src/sys/net/route.h@@/main/RELENG_5/1 2005-01-31 23:26:23.000000000 -0500 +++ M:/emaste_photon/fw-bsd/src/sys/net/route.h@@/main/sandvine_bsd_5_main/3 2005-08-26 16:03:42.000000000 -0400 @@ -168,6 +168,7 @@ struct ortentry { #define RTF_BROADCAST 0x400000 /* route represents a bcast address */ #define RTF_MULTICAST 0x800000 /* route represents a mcast address */ /* 0x1000000 and up unassigned */ +#define RTF_NOKEY 0x80000000 /* Has gateway but no rt_key */ /* * Routing statistics. @@ -219,6 +220,7 @@ struct rt_msghdr { #define RTM_NEWMADDR 0xf /* mcast group membership being added to if */ #define RTM_DELMADDR 0x10 /* mcast group membership being deleted */ #define RTM_IFANNOUNCE 0x11 /* iface arrival/departure */ +#define RTM_IFVLAN 0x20 /* SV: vlan configuration change */ /* * Bitmask values for rtm_inits and rmx_locks. @@ -317,10 +319,12 @@ struct rt_addrinfo { extern struct radix_node_head *rt_tables[AF_MAX+1]; struct ifmultiaddr; +struct vlanreq; int rt_getifa(struct rt_addrinfo *); -void rt_ifannouncemsg(struct ifnet *, int); +void rt_ifannouncemsg(struct ifnet *, int, int); void rt_ifmsg(struct ifnet *); +void rt_ifvlanmsg(struct ifnet *, struct vlanreq *); void rt_missmsg(int, struct rt_addrinfo *, int, int); void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *); void rt_newmaddrmsg(int, struct ifmultiaddr *); @@ -341,6 +345,7 @@ int rt_setgate(struct rtentry *, struct void rtalloc_ign(struct route *ro, u_long ignflags); void rtalloc(struct route *ro); /* XXX deprecated, use rtalloc_ign(ro, 0) */ struct rtentry *rtalloc1(struct sockaddr *, int, u_long); +struct rtentry *rtforge(struct sockaddr*, struct ifnet *); int rtexpunge(struct rtentry *); void rtfree(struct rtentry *); int rtinit(struct ifaddr *, int, int);