예제 #1
0
/*
 * Get rid of old routes.  When draining, this deletes everything, even when
 * the timeout is not expired yet.  When updating, this makes sure that
 * nothing has a timeout longer than the current value of rtq_reallyold.
 */
static int
in6_rtqkill(struct radix_node *rn, void *rock)
{
	struct rtqk_arg *ap = rock;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;

	if (rt->rt_flags & RTPRF_OURS) {
		ap->found++;

		if (ap->draining || rt->rt_rmx.rmx_expire <= time_second) {
			if (rt->rt_refcnt > 0)
				panic("rtqkill route really not free");

			err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
					rt_mask(rt), rt->rt_flags, NULL);
			if (err)
				log(LOG_WARNING, "in6_rtqkill: error %d", err);
			else
				ap->killed++;
		} else {
			if (ap->updating &&
			    (rt->rt_rmx.rmx_expire - time_second >
			     rtq_reallyold)) {
				rt->rt_rmx.rmx_expire =
				    time_second + rtq_reallyold;
			}
			ap->nextstop = lmin(ap->nextstop,
					    rt->rt_rmx.rmx_expire);
		}
	}

	return 0;
}
예제 #2
0
/*
 * Check for alternatives when higher level complains
 * about service problems.  For now, invalidate cached
 * routing information.  If the route was created dynamically
 * (by a redirect), time to try a default gateway again.
 */
void
in6_losing(struct in6pcb *in6p)
{
	struct rtentry *rt;
	struct rt_addrinfo info;

	if (in6p->in6p_af != AF_INET6)
		return;

	if ((rt = rtcache_validate(&in6p->in6p_route)) == NULL)
		return;

	memset(&info, 0, sizeof(info));
	info.rti_info[RTAX_DST] = rtcache_getdst(&in6p->in6p_route);
	info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
	info.rti_info[RTAX_NETMASK] = rt_mask(rt);
	rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
	if (rt->rt_flags & RTF_DYNAMIC) {
		(void)rtrequest(RTM_DELETE, rt_getkey(rt),
		    rt->rt_gateway, rt_mask(rt), rt->rt_flags, NULL);
	}
	/*
	 * A new route can be allocated
	 * the next time output is attempted.
	 */
	rtcache_free(&in6p->in6p_route);
}
예제 #3
0
파일: in_rmx.c 프로젝트: daisu-mi/aod
/*
 * On last reference drop, mark the route as belong to us so that it can be
 * timed out.
 */
static void
in_clsroute(struct radix_node *rn, struct radix_node_head *head)
{
	struct rtentry *rt = (struct rtentry *)rn;

	if(!(rt->rt_flags & RTF_UP))
		return;		/* prophylactic measures */

	if((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
		return;

	if((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS))
	   != RTF_WASCLONED)
		return;

	/*
	 * As requested by David Greenman:
	 * If rtq_reallyold is 0, just delete the route without
	 * waiting for a timeout cycle to kill it.
	 */
	if(rtq_reallyold != 0) {
		rt->rt_flags |= RTPRF_OURS;
		rt->rt_rmx.rmx_expire = time_second + rtq_reallyold;
	} else {
		rtrequest(RTM_DELETE,
			  (struct sockaddr *)rt_key(rt),
			  rt->rt_gateway, rt_mask(rt),
			  rt->rt_flags, 0);
	}
}
예제 #4
0
파일: in_rmx.c 프로젝트: daisu-mi/aod
static int
in_ifadownkill(struct radix_node *rn, void *xap)
{
	struct in_ifadown_arg *ap = xap;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;

	if (rt->rt_ifa == ap->ifa && !(rt->rt_flags & RTF_STATIC)) {
		/*
		 * We need to disable the automatic prune that happens
		 * in this case in rtrequest() because it will blow
		 * away the pointers that rn_walktree() needs in order
		 * continue our descent.  We will end up deleting all
		 * the routes that rtrequest() would have in any case,
		 * so that behavior is not needed there.
		 */
		rt->rt_flags &= ~RTF_PRCLONING;
		err = rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
				rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
		if (err) {
			log(LOG_WARNING, "in_ifadownkill: error %d\n", err);
		}
	}
	return 0;
}
예제 #5
0
/*
 * Install a default route to the passed IP address.
 */
static void
nfs_boot_defrt(struct in_addr *gw_ip)
{
	struct sockaddr dst, gw, mask;
	struct sockaddr_in *sin;
	int error;

	/* Destination: (default) */
	memset((void *)&dst, 0, sizeof(dst));
	dst.sa_len = sizeof(dst);
	dst.sa_family = AF_INET;
	/* Gateway: */
	memset((void *)&gw, 0, sizeof(gw));
	sin = (struct sockaddr_in *)&gw;
	sin->sin_len = sizeof(*sin);
	sin->sin_family = AF_INET;
	sin->sin_addr.s_addr = gw_ip->s_addr;
	/* Mask: (zero length) */
	/* XXX - Just pass a null pointer? */
	memset(&mask, 0, sizeof(mask));

	/* add, dest, gw, mask, flags, 0 */
	error = rtrequest(RTM_ADD, &dst, &gw, &mask,
			  (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
	if (error) {
		printf("nfs_boot: add route, error=%d\n", error);
		error = 0;
	}
}
예제 #6
0
/*
 * Check for alternatives when higher level complains
 * about service problems.  For now, invalidate cached
 * routing information.  If the route was created dynamically
 * (by a redirect), time to try a default gateway again.
 */
void
in_losing(struct inpcb *inp)
{
	register struct rtentry *rt;
	struct rt_addrinfo info;

	if ((rt = inp->inp_route.ro_rt)) {
		inp->inp_route.ro_rt = 0;
		bzero((caddr_t)&info, sizeof(info));
		info.rti_info[RTAX_DST] =
			(struct sockaddr *)&inp->inp_route.ro_dst;
		info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
		info.rti_info[RTAX_NETMASK] = rt_mask(rt);
		rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
		if (rt->rt_flags & RTF_DYNAMIC)
			(void) rtrequest(RTM_DELETE, rt_key(rt),
				rt->rt_gateway, rt_mask(rt), rt->rt_flags,
				(struct rtentry **)0);
		else
		/*
		 * A new route can be allocated
		 * the next time output is attempted.
		 */
			rtfree(rt);
	}
}
예제 #7
0
struct rtentry *
rtalloc1(struct sockaddr *dst, int report, u_int tableid)
{
	struct radix_node_head	*rnh;
	struct rtentry		*rt;
	struct radix_node	*rn;
	struct rtentry		*newrt = 0;
	struct rt_addrinfo	 info;
	int			 s = splsoftnet(), err = 0, msgtype = RTM_MISS;

	rnh = rt_gettable(dst->sa_family, tableid);
	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
	    ((rn->rn_flags & RNF_ROOT) == 0)) {
		newrt = rt = (struct rtentry *)rn;
		if (report && (rt->rt_flags & RTF_CLONING)) {
			err = rtrequest(RTM_RESOLVE, dst, SA(NULL),
			    SA(NULL), 0, &newrt, tableid);
			if (err) {
				newrt = rt;
				rt->rt_refcnt++;
				goto miss;
			}
			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
				msgtype = RTM_RESOLVE;
				goto miss;
			}
			/* Inform listeners of the new route */
			bzero(&info, sizeof(info));
			info.rti_info[RTAX_DST] = rt_key(rt);
			info.rti_info[RTAX_NETMASK] = rt_mask(rt);
			info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
			if (rt->rt_ifp != NULL) {
				info.rti_info[RTAX_IFP] =
				    TAILQ_FIRST(&rt->rt_ifp->if_addrlist)->ifa_addr;
				info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
			}
			rt_missmsg(RTM_ADD, &info, rt->rt_flags,
			    rt->rt_ifp, 0, tableid);
		} else
			rt->rt_refcnt++;
	} else {
		if (dst->sa_family != PF_KEY)
			rtstat.rts_unreach++;
	/*
	 * IP encapsulation does lots of lookups where we don't need nor want
	 * the RTM_MISSes that would be generated.  It causes RTM_MISS storms
	 * sent upward breaking user-level routing queries.
	 */
miss:
		if (report && dst->sa_family != PF_KEY) {
			bzero((caddr_t)&info, sizeof(info));
			info.rti_info[RTAX_DST] = dst;
			rt_missmsg(msgtype, &info, 0, NULL, err, tableid);
		}
	}
	splx(s);
	return (newrt);
}
예제 #8
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int ifart_delete( struct radix_node *rn, struct in_addr *addr )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if (((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr == addr->s_addr)
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              rt->rt_flags, NULL);
	}
	return 0;
}
예제 #9
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int ifprt_delete( struct radix_node *rn, void *ifp )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if(rt->rt_ifp == ifp)
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              rt->rt_flags, NULL);
	}
	return 0;
}
예제 #10
0
//------------------------------------------------------------------------------
// FUNCTION
//
//
// DESCRIPTION
//
//  
// PARAMETERS
//
//  
// RETURN
//
//  
//------------------------------------------------------------------------------
static int staticrt_delete( struct radix_node *rn, void *vifp )
{
	struct rtentry *rt = (struct rtentry *)rn;
	
	if((rt->rt_flags & RTF_STATIC) && !(rt->rt_flags & RTF_LLINFO))
	{
		rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
              0, NULL);
	}
	return 0;
}
예제 #11
0
static int
nfs_boot_delroute(struct rtentry *rt, void *w)
{
	int error;

	if ((void *)rt->rt_ifp != w)
		return 0;

	error = rtrequest(RTM_DELETE, rt_getkey(rt), NULL, rt_mask(rt), 0,
	    NULL);
	if (error != 0)
		printf("%s: del route, error=%d\n", __func__, error);

	return 0;
}
예제 #12
0
struct rtentry *
rtalloc2(struct sockaddr *dst, int report, int howstrict)
{
	struct radix_node_head	*rnh;
	struct rtentry		*rt;
	struct radix_node	*rn;
	struct rtentry		*newrt = 0;
	struct rt_addrinfo	 info;
	int			 s = splnet(), err = 0, msgtype = RTM_MISS;

	rnh = rt_gettable(dst->sa_family, 0);
	if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
	    ((rn->rn_flags & RNF_ROOT) == 0)) {
		newrt = rt = (struct rtentry *)rn;
		if (report && (rt->rt_flags & RTF_CLONING) &&
		    okaytoclone(rt->rt_flags, howstrict)) {
			err = rtrequest(RTM_RESOLVE, dst, SA(0), SA(0), 0,
			    &newrt, 0);
			if (err) {
				newrt = rt;
				rt->rt_refcnt++;
				goto miss;
			}
			if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
				msgtype = RTM_RESOLVE;
				goto miss;
			}
		} else
			rt->rt_refcnt++;
	} else {
		rtstat.rts_unreach++;
miss:
		if (report) {
			bzero((caddr_t)&info, sizeof(info));
			info.rti_info[RTAX_DST] = dst;
			rt_missmsg(msgtype, &info, 0, NULL, err, 0);
		}
	}
	splx(s);
	return (newrt);
}
예제 #13
0
파일: Protocol.cpp 프로젝트: DonCN/haiku
void
IPCP::RemoveRoutes()
{
	// note: netstack creates and deletes destination route automatically
	
	if(fDefaultRoute) {
		struct sockaddr_in netmask;
		memset(&netmask, 0, sizeof(struct sockaddr_in));
		
		netmask.sin_family = AF_INET;
		netmask.sin_addr.s_addr = fLocalRequests.netmask;
		netmask.sin_len = sizeof(struct sockaddr_in);
		
		if(rtrequest(RTM_DELETE, (struct sockaddr*) &netmask,
				(struct sockaddr*) &fGateway, (struct sockaddr*) &netmask,
				RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
			ERROR("IPCP: RemoveRoutes(): could not remove default/subnet route!\n");
		
		fDefaultRoute = NULL;
	}
}
예제 #14
0
파일: in6_rmx.c 프로젝트: MarginC/kame
/*
 * On last reference drop, mark the route as belong to us so that it can be
 * timed out.
 */
static void
in6_clsroute(struct radix_node *rn, struct radix_node_head *head)
{
	struct rtentry *rt = (struct rtentry *)rn;

	if (!(rt->rt_flags & RTF_UP))
		return;		/* prophylactic measures */

	if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
		return;

	if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS))
	   != RTF_WASCLONED)
		return;

	/*
	 * As requested by David Greenman:
	 * If rtq_reallyold is 0, just delete the route without
	 * waiting for a timeout cycle to kill it.
	 */
	if (rtq_reallyold != 0) {
		rt->rt_flags |= RTPRF_OURS;
		rt->rt_rmx.rmx_expire = time_second + rtq_reallyold;
	} else {
#ifdef __FreeBSD__
		rtexpunge(rt);
#else
		struct rtentry *dummy;

		/*
		 * rtrequest() would recursively call rtfree() without the
		 * dummy entry argument, causing duplicated free.
		 */
		rtrequest(RTM_DELETE,
			  (struct sockaddr *)rt_key(rt),
			  rt->rt_gateway, rt_mask(rt),
			  rt->rt_flags, &dummy);
#endif
	}
}
예제 #15
0
static int
aa_dosingleroute(struct ifaddr *ifa,
                 struct at_addr *at_addr, struct at_addr *at_mask, int cmd, int flags)
{
    struct sockaddr_at	addr, mask;

    bzero(&addr, sizeof(addr));
    bzero(&mask, sizeof(mask));
    addr.sat_family = AF_APPLETALK;
    addr.sat_len = sizeof(struct sockaddr_at);
    addr.sat_addr.s_net = at_addr->s_net;
    addr.sat_addr.s_node = at_addr->s_node;
    mask.sat_family = AF_APPLETALK;
    mask.sat_len = sizeof(struct sockaddr_at);
    mask.sat_addr.s_net = at_mask->s_net;
    mask.sat_addr.s_node = at_mask->s_node;
    if (at_mask->s_node)
        flags |= RTF_HOST;
    return(rtrequest(cmd, (struct sockaddr *) &addr,
                     (flags & RTF_HOST)?(ifa->ifa_dstaddr):(ifa->ifa_addr),
                     (struct sockaddr *) &mask, flags, NULL));
}
예제 #16
0
파일: in_rmx.c 프로젝트: epicsdeb/rtems
/*
 * Get rid of old routes.  When draining, this deletes everything, even when
 * the timeout is not expired yet.  When updating, this makes sure that
 * nothing has a timeout longer than the current value of rtq_reallyold.
 */
static int
in_rtqkill(struct radix_node *rn, void *rock)
{
	struct rtqk_arg *ap = rock;
	struct rtentry *rt = (struct rtentry *)rn;
	int err;

	if(rt->rt_flags & RTPRF_OURS) {
		ap->found++;

		if(ap->draining || rt->rt_rmx.rmx_expire <= rtems_bsdnet_seconds_since_boot()) {
			if(rt->rt_refcnt > 0)
				panic("rtqkill route really not free");

			err = rtrequest(RTM_DELETE,
					(struct sockaddr *)rt_key(rt),
					rt->rt_gateway, rt_mask(rt),
					rt->rt_flags, 0);
			if(err) {
				log(LOG_WARNING, "in_rtqkill: error %d\n", err);
			} else {
				ap->killed++;
			}
		} else {
			if(ap->updating
			   && (rt->rt_rmx.rmx_expire - rtems_bsdnet_seconds_since_boot()
			       > rtq_reallyold)) {
				rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot()
					+ rtq_reallyold;
			}
			ap->nextstop = lmin(ap->nextstop,
					    rt->rt_rmx.rmx_expire);
		}
	}

	return 0;
}
예제 #17
0
/*
 * atm_rtrequest: handle ATM rt request (in support of generic code)
 *   inputs: "req" = request code
 *	     "rt" = route entry
 *	     "info" = rt_addrinfo
 */
void
atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
{
	struct sockaddr *gate = rt->rt_gateway;
	struct atm_pseudoioctl api;
#ifdef NATM
	struct sockaddr_in *sin;
	struct natmpcb *npcb = NULL;
	struct atm_pseudohdr *aph;
#endif
	static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
	int error;

	if (rt->rt_flags & RTF_GATEWAY)   /* link level requests only */
		return;

	switch (req) {

	case RTM_RESOLVE: /* resolve: only happens when cloning */
		kprintf("atm_rtrequest: RTM_RESOLVE request detected?\n");
		break;

	case RTM_ADD:

		/*
		 * route added by a command (e.g. ifconfig, route, arp...).
		 *
		 * first check to see if this is not a host route, in which
		 * case we are being called via "ifconfig" to set the address.
		 */

		if ((rt->rt_flags & RTF_HOST) == 0) {
			rt_setgate(rt,rt_key(rt),(struct sockaddr *)&null_sdl,
				   RTL_DONTREPORT);
			gate = rt->rt_gateway;
			SDL(gate)->sdl_type = rt->rt_ifp->if_type;
			SDL(gate)->sdl_index = rt->rt_ifp->if_index;
			break;
		}

		if ((rt->rt_flags & RTF_CLONING) != 0) {
			kprintf("atm_rtrequest: cloning route detected?\n");
			break;
		}
		if (gate->sa_family != AF_LINK ||
		    gate->sa_len < sizeof(null_sdl)) {
			log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
			break;
		}

#ifdef DIAGNOSTIC
		if (rt->rt_ifp->if_ioctl == NULL) panic("atm null ioctl");
#endif

#ifdef NATM
		/*
		 * let native ATM know we are using this VCI/VPI
		 * (i.e. reserve it)
		 */
		sin = (struct sockaddr_in *) rt_key(rt);
		if (sin->sin_family != AF_INET)
			goto failed;
		aph = (struct atm_pseudohdr *) LLADDR(SDL(gate));
		npcb = npcb_add(NULL, rt->rt_ifp, ATM_PH_VCI(aph),
						ATM_PH_VPI(aph));
		if (npcb == NULL)
			goto failed;
		npcb->npcb_flags |= NPCB_IP;
		npcb->ipaddr.s_addr = sin->sin_addr.s_addr;
		/* XXX: move npcb to llinfo when ATM ARP is ready */
		rt->rt_llinfo =  npcb;
		rt->rt_flags |= RTF_LLINFO;
#endif
		/*
		 * let the lower level know this circuit is active
		 */
		bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph));
		api.rxhand = NULL;
		ifnet_serialize_all(rt->rt_ifp);
		error = rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMENA,
					     (caddr_t)&api, NULL);
		ifnet_deserialize_all(rt->rt_ifp);
		if (error) {
			kprintf("atm: couldn't add VC\n");
			goto failed;
		}

		SDL(gate)->sdl_type = rt->rt_ifp->if_type;
		SDL(gate)->sdl_index = rt->rt_ifp->if_index;

		break;

failed:
#ifdef NATM
		if (npcb) {
			npcb_free(npcb, NPCB_DESTROY);
			rt->rt_llinfo = NULL;
			rt->rt_flags &= ~RTF_LLINFO;
		}
#endif
		rtrequest(RTM_DELETE, rt_key(rt), NULL,
		    rt_mask(rt), 0, NULL);
		break;

	case RTM_DELETE:

#ifdef NATM
		/*
		 * tell native ATM we are done with this VC
		 */

		if (rt->rt_flags & RTF_LLINFO) {
			npcb_free(rt->rt_llinfo, NPCB_DESTROY);
			rt->rt_llinfo = NULL;
			rt->rt_flags &= ~RTF_LLINFO;
		}
#endif
		/*
		 * tell the lower layer to disable this circuit
		 */

		bcopy(LLADDR(SDL(gate)), &api.aph, sizeof(api.aph));
		api.rxhand = NULL;
		ifnet_serialize_all(rt->rt_ifp);
		rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMDIS, (caddr_t)&api,
				     NULL);
		ifnet_deserialize_all(rt->rt_ifp);
		break;
	}
}
예제 #18
0
int 
bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
			struct sockaddr_in *myaddr,
			struct sockaddr_in *netmask,
			struct sockaddr_in *gw,
			struct proc *procp)
{
  int error;
  struct sockaddr_in oldgw;
  struct sockaddr_in olddst;
  struct sockaddr_in oldmask;
  struct sockaddr_in *sin;

  /* Remove old default route to 0.0.0.0 */
  
  bzero((caddr_t) &olddst, sizeof(olddst));
  olddst.sin_len=sizeof(olddst);
  olddst.sin_family=AF_INET;
  olddst.sin_addr.s_addr = INADDR_ANY;
  
  bzero((caddr_t) &oldgw, sizeof(oldgw));
  oldgw.sin_len=sizeof(oldgw);
  oldgw.sin_family=AF_INET;
  oldgw.sin_addr.s_addr = INADDR_ANY;
  
  bzero((caddr_t) &oldmask, sizeof(oldmask));
  oldmask.sin_len=sizeof(oldmask);
  oldmask.sin_family=AF_INET;
  oldmask.sin_addr.s_addr = INADDR_ANY;
  
  error = rtrequest(RTM_DELETE, 
		    (struct sockaddr *) &olddst,
		    (struct sockaddr *) &oldgw,
		    (struct sockaddr *) &oldmask, 
		    (RTF_UP | RTF_STATIC), NULL);
  if (error) {
    printf("nfs_boot: del default route, error=%d\n", error);
    return error;
  }

  /*
   * Do enough of ifconfig(8) so that the chosen interface
   * can talk to the servers.  (just set the address)
   */
  bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
  error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set netmask, error=%s\n", strerror(error));
    return error;
  }

  /* Broadcast is with host part of IP address all 1's */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
  error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set broadcast addr, error=%s\n", strerror(error));
    return error;
  }
  
  bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
  error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_adjust_interface: set if addr, error=%s\n", strerror(error));
    return error;
  }

  /* Add new default route */

  error = rtrequest(RTM_ADD, 
		    (struct sockaddr *) &olddst,
		    (struct sockaddr *) gw,
		    (struct sockaddr *) &oldmask,
		    (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
  if (error) {
    printf("bootpc_adjust_interface: add net route, error=%d\n", error);
  }

  return error;
}
예제 #19
0
int 
bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
			struct proc *procp)
{
  struct sockaddr_in *sin;
  int error;
  struct sockaddr_in dst;
  struct sockaddr_in gw;
  struct sockaddr_in mask;

  /*
   * Bring up the interface.
   *
   * Get the old interface flags and or IFF_UP into them; if
   * IFF_UP set blindly, interface selection can be clobbered.
   */
  error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: GIFFLAGS, error=%s\n", strerror(error));
    return error;
  }
  ireq->ifr_flags |= IFF_UP;
  error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: SIFFLAGS, error=%s\n", strerror(error));
    return error;
  }

  /*
   * Do enough of ifconfig(8) so that the chosen interface
   * can talk to the servers.  (just set the address)
   */
  /* addr is 0.0.0.0 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_ANY;
  error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
  /*
   * Ignore a File already exists (EEXIST) error code. This means a
   * route for the address is already present and is returned on
   * a second pass to here.
   */
  if (error && (error != EEXIST)) {
    printf("bootpc_fakeup_interface: set if addr, error=%s\n", strerror(error));
    return error;
  }
  
  /* netmask is 0.0.0.0 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_ANY;
  error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: set if netmask, error=%s\n", strerror(error));
    return error;
  }
  
  /* Broadcast is 255.255.255.255 */
  
  sin = (struct sockaddr_in *)&ireq->ifr_addr;
  bzero((caddr_t)sin, sizeof(*sin));
  sin->sin_len = sizeof(*sin);
  sin->sin_family = AF_INET;
  sin->sin_addr.s_addr = INADDR_BROADCAST;
  error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
  if (error) {
    printf("bootpc_fakeup_interface: set broadcast addr, error=%s\n", strerror(error));
    return error;
  }
  
  /* Add default route to 0.0.0.0 so we can send data */
  
  bzero((caddr_t) &dst, sizeof(dst));
  dst.sin_len=sizeof(dst);
  dst.sin_family=AF_INET;
  dst.sin_addr.s_addr = htonl(0);
  
  bzero((caddr_t) &gw, sizeof(gw));
  gw.sin_len=sizeof(gw);
  gw.sin_family=AF_INET;
  gw.sin_addr.s_addr = htonl(0x0);
  
  bzero((caddr_t) &mask, sizeof(mask));
  mask.sin_len=sizeof(mask);
  mask.sin_family=AF_INET;
  mask.sin_addr.s_addr = htonl(0);
  
  error = rtrequest(RTM_ADD, 
		    (struct sockaddr *) &dst, 
		    (struct sockaddr *) &gw,
		    (struct sockaddr *) &mask, 
		    RTF_UP | RTF_STATIC
		    , NULL);
  if (error && error != EEXIST)
    printf("bootpc_fakeup_interface: add default route, error=%s\n",
           strerror(error));
  
  return error;
}
예제 #20
0
void
atm_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
{
	struct sockaddr *gate = rt->rt_gateway;
	struct atm_pseudoioctl api;
#ifdef NATM
	const struct sockaddr_in *sin;
	struct natmpcb *npcb = NULL;
	const struct atm_pseudohdr *aph;
#endif
	const struct ifnet *ifp = rt->rt_ifp;
	uint8_t namelen = strlen(ifp->if_xname);
	uint8_t addrlen = ifp->if_addrlen;

	if (rt->rt_flags & RTF_GATEWAY)   /* link level requests only */
		return;

	switch (req) {

	case RTM_RESOLVE: /* resolve: only happens when cloning */
		printf("atm_rtrequest: RTM_RESOLVE request detected?\n");
		break;

	case RTM_ADD:

		/*
		 * route added by a command (e.g. ifconfig, route, arp...).
		 *
		 * first check to see if this is not a host route, in which
		 * case we are being called via "ifconfig" to set the address.
		 */

		if ((rt->rt_flags & RTF_HOST) == 0) {
			union {
				struct sockaddr sa;
				struct sockaddr_dl sdl;
				struct sockaddr_storage ss;
			} u;

			sockaddr_dl_init(&u.sdl, sizeof(u.ss),
			    ifp->if_index, ifp->if_type,
			    NULL, namelen, NULL, addrlen);
			rt_setgate(rt, &u.sa);
			gate = rt->rt_gateway;
			break;
		}

		if ((rt->rt_flags & RTF_CLONING) != 0) {
			printf("atm_rtrequest: cloning route detected?\n");
			break;
		}
		if (gate->sa_family != AF_LINK ||
		    gate->sa_len < sockaddr_dl_measure(namelen, addrlen)) {
			log(LOG_DEBUG, "atm_rtrequest: bad gateway value\n");
			break;
		}

#ifdef DIAGNOSTIC
		if (rt->rt_ifp->if_ioctl == NULL) panic("atm null ioctl");
#endif

#ifdef NATM
		/*
		 * let native ATM know we are using this VCI/VPI
		 * (i.e. reserve it)
		 */
		sin = satocsin(rt_getkey(rt));
		if (sin->sin_family != AF_INET)
			goto failed;
		aph = (const struct atm_pseudohdr *)CLLADDR(satosdl(gate));
		npcb = npcb_add(NULL, rt->rt_ifp, ATM_PH_VCI(aph),
						ATM_PH_VPI(aph));
		if (npcb == NULL)
			goto failed;
		npcb->npcb_flags |= NPCB_IP;
		npcb->ipaddr.s_addr = sin->sin_addr.s_addr;
		/* XXX: move npcb to llinfo when ATM ARP is ready */
		rt->rt_llinfo = (void *) npcb;
		rt->rt_flags |= RTF_LLINFO;
#endif
		/*
		 * let the lower level know this circuit is active
		 */
		memcpy(&api.aph, CLLADDR(satocsdl(gate)), sizeof(api.aph));
		api.rxhand = NULL;
		if (rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMENA, &api) != 0) {
			printf("atm: couldn't add VC\n");
			goto failed;
		}

		satosdl(gate)->sdl_type = rt->rt_ifp->if_type;
		satosdl(gate)->sdl_index = rt->rt_ifp->if_index;

		break;

failed:
#ifdef NATM
		if (npcb) {
			npcb_free(npcb, NPCB_DESTROY);
			rt->rt_llinfo = NULL;
			rt->rt_flags &= ~RTF_LLINFO;
		}
#endif
		rtrequest(RTM_DELETE, rt_getkey(rt), NULL,
			rt_mask(rt), 0, NULL);
		break;

	case RTM_DELETE:

#ifdef NATM
		/*
		 * tell native ATM we are done with this VC
		 */

		if (rt->rt_flags & RTF_LLINFO) {
			npcb_free((struct natmpcb *)rt->rt_llinfo,
								NPCB_DESTROY);
			rt->rt_llinfo = NULL;
			rt->rt_flags &= ~RTF_LLINFO;
		}
#endif
		/*
		 * tell the lower layer to disable this circuit
		 */

		memcpy(&api.aph, CLLADDR(satocsdl(gate)), sizeof(api.aph));
		api.rxhand = NULL;
		(void)rt->rt_ifp->if_ioctl(rt->rt_ifp, SIOCATMDIS, &api);

		break;
	}
}
예제 #21
0
파일: in_rmx.c 프로젝트: daisu-mi/aod
/*
 * Do what we need to do when inserting a route.
 */
static struct radix_node *
in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
	    struct radix_node *treenodes)
{
	struct rtentry *rt = (struct rtentry *)treenodes;
	struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
	struct radix_node *ret;

	/*
	 * For IP, all unicast non-host routes are automatically cloning.
	 */
	if(IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
		rt->rt_flags |= RTF_MULTICAST;

	if(!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
		rt->rt_flags |= RTF_PRCLONING;
	}

	/*
	 * A little bit of help for both IP output and input:
	 *   For host routes, we make sure that RTF_BROADCAST
	 *   is set for anything that looks like a broadcast address.
	 *   This way, we can avoid an expensive call to in_broadcast()
	 *   in ip_output() most of the time (because the route passed
	 *   to ip_output() is almost always a host route).
	 *
	 *   We also do the same for local addresses, with the thought
	 *   that this might one day be used to speed up ip_input().
	 *
	 * We also mark routes to multicast addresses as such, because
	 * it's easy to do and might be useful (but this is much more
	 * dubious since it's so easy to inspect the address).  (This
	 * is done above.)
	 */
	if (rt->rt_flags & RTF_HOST) {
		if (in_broadcast(sin->sin_addr, rt->rt_ifp)) {
			rt->rt_flags |= RTF_BROADCAST;
		} else {
#define satosin(sa) ((struct sockaddr_in *)sa)
			if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr
			    == sin->sin_addr.s_addr)
				rt->rt_flags |= RTF_LOCAL;
#undef satosin
		}
	}

	if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) 
	    && rt->rt_ifp)
		rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;

	ret = rn_addroute(v_arg, n_arg, head, treenodes);
	if (ret == NULL && rt->rt_flags & RTF_HOST) {
		struct rtentry *rt2;
		/*
		 * We are trying to add a host route, but can't.
		 * Find out if it is because of an
		 * ARP entry and delete it if so.
		 */
		rt2 = rtalloc1((struct sockaddr *)sin, 0,
				RTF_CLONING | RTF_PRCLONING);
		if (rt2) {
			if (rt2->rt_flags & RTF_LLINFO &&
				rt2->rt_flags & RTF_HOST &&
				rt2->rt_gateway &&
				rt2->rt_gateway->sa_family == AF_LINK) {
				rtrequest(RTM_DELETE,
					  (struct sockaddr *)rt_key(rt2),
					  rt2->rt_gateway,
					  rt_mask(rt2), rt2->rt_flags, 0);
				ret = rn_addroute(v_arg, n_arg, head,
					treenodes);
			}
			RTFREE(rt2);
		}
	}
	return ret;
}
예제 #22
0
파일: in_arp.c 프로젝트: SbIm/xnu-env
/*
 * arp_lookup_route will lookup the route for a given address.
 *
 * The address must be for a host on a local network on this interface.
 * If the returned route is non-NULL, the route is locked and the caller
 * is responsible for unlocking it and releasing its reference.
 */
static errno_t
arp_lookup_route(const struct in_addr *addr, int create, int proxy,
    route_t *route, unsigned int ifscope)
{
	struct sockaddr_inarp sin = {sizeof(sin), AF_INET, 0, {0}, {0}, 0, 0};
	const char *why = NULL;
	errno_t	error = 0;
	route_t rt;

	*route = NULL;

	sin.sin_addr.s_addr = addr->s_addr;
	sin.sin_other = proxy ? SIN_PROXY : 0;

	rt = rtalloc1_scoped((struct sockaddr*)&sin, create, 0, ifscope);
	if (rt == NULL)
		return (ENETUNREACH);

	RT_LOCK(rt);

	if (rt->rt_flags & RTF_GATEWAY) {
		why = "host is not on local network";
		error = ENETUNREACH;
	} else if (!(rt->rt_flags & RTF_LLINFO)) {
		why = "could not allocate llinfo";
		error = ENOMEM;
	} else if (rt->rt_gateway->sa_family != AF_LINK) {
		why = "gateway route is not ours";
		error = EPROTONOSUPPORT;
	}

	if (error != 0) {
		if (create && log_arp_warnings) {
			char tmp[MAX_IPv4_STR_LEN];
			log(LOG_DEBUG, "arplookup link#%d %s failed: %s\n",
			    ifscope, inet_ntop(AF_INET, addr, tmp,
			    sizeof (tmp)), why);
		}

		/*
		 * If there are no references to this route, and it is
		 * a cloned route, and not static, and ARP had created
		 * the route, then purge it from the routing table as
		 * it is probably bogus.
		 */
		if (rt->rt_refcnt == 1 &&
		    (rt->rt_flags & (RTF_WASCLONED | RTF_STATIC)) ==
		    RTF_WASCLONED) {
			/*
			 * Prevent another thread from modiying rt_key,
			 * rt_gateway via rt_setgate() after rt_lock is
			 * dropped by marking the route as defunct.
			 */
			rt->rt_flags |= RTF_CONDEMNED;
			RT_UNLOCK(rt);
			rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
			    rt_mask(rt), rt->rt_flags, 0);
			rtfree(rt);
		} else {
			RT_REMREF_LOCKED(rt);
			RT_UNLOCK(rt);
		}
		return (error);
	}

	/*
	 * Caller releases reference and does RT_UNLOCK(rt).
	 */
	*route = rt;
	return (0);
}
예제 #23
0
/*
 * Mount a remote root fs via. nfs. This depends on the info in the
 * nfs_diskless structure that has been filled in properly by some primary
 * bootstrap.
 * It goes something like this:
 * - do enough of "ifconfig" by calling ifioctl() so that the system
 *   can talk to the server
 * - If nfs_diskless.mygateway is filled in, use that address as
 *   a default gateway.
 * - build the rootfs mount point and call mountnfs() to do the rest.
 *
 * It is assumed to be safe to read, modify, and write the nfsv3_diskless
 * structure, as well as other global NFS client variables here, as
 * nfs_mountroot() will be called once in the boot before any other NFS
 * client activity occurs.
 */
int
nfs_mountroot(struct mount *mp)
{
	struct thread *td = curthread;
	struct nfsv3_diskless *nd = &nfsv3_diskless;
	struct socket *so;
	struct vnode *vp;
	struct ifreq ir;
	int error;
	u_long l;
	char buf[128];
	char *cp;


#if defined(BOOTP_NFSROOT) && defined(BOOTP)
	bootpc_init();		/* use bootp to get nfs_diskless filled in */
#elif defined(NFS_ROOT)
	nfs_setup_diskless();
#endif

	if (nfs_diskless_valid == 0) {
		return (-1);
	}
	if (nfs_diskless_valid == 1)
		nfs_convert_diskless();

	/*
	 * XXX splnet, so networks will receive...
	 */
	splnet();

	/*
	 * Do enough of ifconfig(8) so that the critical net interface can
	 * talk to the server.
	 */
	error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
	    td->td_ucred, td);
	if (error)
		panic("nfs_mountroot: socreate(%04x): %d",
			nd->myif.ifra_addr.sa_family, error);

#if 0 /* XXX Bad idea */
	/*
	 * We might not have been told the right interface, so we pass
	 * over the first ten interfaces of the same kind, until we get
	 * one of them configured.
	 */

	for (i = strlen(nd->myif.ifra_name) - 1;
		nd->myif.ifra_name[i] >= '0' &&
		nd->myif.ifra_name[i] <= '9';
		nd->myif.ifra_name[i] ++) {
		error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
		if(!error)
			break;
	}
#endif

	error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
	if (error)
		panic("nfs_mountroot: SIOCAIFADDR: %d", error);

	if ((cp = getenv("boot.netif.mtu")) != NULL) {
		ir.ifr_mtu = strtol(cp, NULL, 10);
		bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
		freeenv(cp);
		error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
		if (error)
			printf("nfs_mountroot: SIOCSIFMTU: %d", error);
	}
	soclose(so);

	/*
	 * If the gateway field is filled in, set it as the default route.
	 * Note that pxeboot will set a default route of 0 if the route
	 * is not set by the DHCP server.  Check also for a value of 0
	 * to avoid panicking inappropriately in that situation.
	 */
	if (nd->mygateway.sin_len != 0 &&
	    nd->mygateway.sin_addr.s_addr != 0) {
		struct sockaddr_in mask, sin;

		bzero((caddr_t)&mask, sizeof(mask));
		sin = mask;
		sin.sin_family = AF_INET;
		sin.sin_len = sizeof(sin);
                /* XXX MRT use table 0 for this sort of thing */
		CURVNET_SET(TD_TO_VNET(td));
		error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
		    (struct sockaddr *)&nd->mygateway,
		    (struct sockaddr *)&mask,
		    RTF_UP | RTF_GATEWAY, NULL);
		CURVNET_RESTORE();
		if (error)
			panic("nfs_mountroot: RTM_ADD: %d", error);
	}

	/*
	 * Create the rootfs mount point.
	 */
	nd->root_args.fh = nd->root_fh;
	nd->root_args.fhsize = nd->root_fhsize;
	l = ntohl(nd->root_saddr.sin_addr.s_addr);
	snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
		(l >> 24) & 0xff, (l >> 16) & 0xff,
		(l >>  8) & 0xff, (l >>  0) & 0xff, nd->root_hostnam);
	printf("NFS ROOT: %s\n", buf);
	nd->root_args.hostname = buf;
	if ((error = nfs_mountdiskless(buf,
	    &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
		return (error);
	}

	/*
	 * This is not really an nfs issue, but it is much easier to
	 * set hostname here and then let the "/etc/rc.xxx" files
	 * mount the right /var based upon its preset value.
	 */
	mtx_lock(&prison0.pr_mtx);
	strlcpy(prison0.pr_hostname, nd->my_hostnam,
	    sizeof (prison0.pr_hostname));
	mtx_unlock(&prison0.pr_mtx);
	inittodr(ntohl(nd->root_time));
	return (0);
}
예제 #24
0
/*
 * NOTE: in6_ifdetach() does not support loopback if at this moment.
 * We don't need this function in bsdi, because interfaces are never removed
 * from the ifnet list in bsdi.
 */
void
in6_ifdetach(struct ifnet *ifp)
{
	struct in6_ifaddr *ia, *oia;
	struct ifaddr *ifa, *next;
	struct rtentry *rt;
	short rtflags;
	struct in6_multi_mship *imm;

	/* remove ip6_mrouter stuff */
	ip6_mrouter_detach(ifp);

	/* remove neighbor management table */
	nd6_purge(ifp);

	/* XXX this code is duplicated in in6_purgeif() --dyoung */
	/* nuke any of IPv6 addresses we have */
	if_purgeaddrs(ifp, AF_INET6, in6_purgeaddr);

	/* XXX isn't this code is redundant, given the above? --dyoung */
	/* XXX doesn't this code replicate code in in6_purgeaddr() ? --dyoung */
	/* undo everything done by in6_ifattach(), just in case */
	for (ifa = IFADDR_FIRST(ifp); ifa != NULL; ifa = next) {
		next = IFADDR_NEXT(ifa);

		if (ifa->ifa_addr->sa_family != AF_INET6
		 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
			continue;
		}

		ia = (struct in6_ifaddr *)ifa;

		/*
		 * leave from multicast groups we have joined for the interface
		 */
		while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
			LIST_REMOVE(imm, i6mm_chain);
			in6_leavegroup(imm);
		}

		/* remove from the routing table */
		if ((ia->ia_flags & IFA_ROUTE) &&
		    (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
			rtflags = rt->rt_flags;
			rtfree(rt);
			rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
			    (struct sockaddr *)&ia->ia_addr,
			    (struct sockaddr *)&ia->ia_prefixmask,
			    rtflags, NULL);
		}

		/* remove from the linked list */
		ifa_remove(ifp, &ia->ia_ifa);

		/* also remove from the IPv6 address chain(itojun&jinmei) */
		oia = ia;
		if (oia == (ia = in6_ifaddr))
			in6_ifaddr = ia->ia_next;
		else {
			while (ia->ia_next && (ia->ia_next != oia))
				ia = ia->ia_next;
			if (ia->ia_next)
				ia->ia_next = oia->ia_next;
			else {
				nd6log((LOG_ERR,
				    "%s: didn't unlink in6ifaddr from list\n",
				    if_name(ifp)));
			}
		}

		ifafree(&oia->ia_ifa);
	}

	/* cleanup multicast address kludge table, if there is any */
	in6_purgemkludge(ifp);

	/*
	 * remove neighbor management table.  we call it twice just to make
	 * sure we nuke everything.  maybe we need just one call.
	 * XXX: since the first call did not release addresses, some prefixes
	 * might remain.  We should call nd6_purge() again to release the
	 * prefixes after removing all addresses above.
	 * (Or can we just delay calling nd6_purge until at this point?)
	 */
	nd6_purge(ifp);
}
예제 #25
0
파일: in6_rmx.c 프로젝트: MarginC/kame
/*
 * Do what we need to do when inserting a route.
 */
static struct radix_node *
in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
	    struct radix_node *treenodes)
{
	struct rtentry *rt = (struct rtentry *)treenodes;
	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
	struct radix_node *ret;

	/*
	 * For IPv6, all unicast non-host routes are automatically cloning.
	 */
	if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
		rt->rt_flags |= RTF_MULTICAST;

	if (!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
#ifdef RTF_PRCLONING
		rt->rt_flags |= RTF_PRCLONING;
#endif
	}

	/*
	 * A little bit of help for both IPv6 output and input:
	 *   For local addresses, we make sure that RTF_LOCAL is set,
	 *   with the thought that this might one day be used to speed up
	 *   ip_input().
	 *
	 * We also mark routes to multicast addresses as such, because
	 * it's easy to do and might be useful (but this is much more
	 * dubious since it's so easy to inspect the address).  (This
	 * is done above.)
	 *
	 * XXX
	 * should elaborate the code.
	 */
	if (rt->rt_flags & RTF_HOST) {
		if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr)
					->sin6_addr,
				       &sin6->sin6_addr)) {
			rt->rt_flags |= RTF_LOCAL;
		}
	}

	if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp)
		rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);

	ret = rn_addroute(v_arg, n_arg, head, treenodes);
	if (ret == NULL && rt->rt_flags & RTF_HOST) {
		struct rtentry *rt2;
		/*
		 * We are trying to add a host route, but can't.
		 * Find out if it is because of an
		 * ARP entry and delete it if so.
		 */
		rt2 = rtalloc1((struct sockaddr *)sin6, 0,
				RTF_CLONING
#ifdef RTF_PRCLONING
				| RTF_PRCLONING
#endif
				);
		if (rt2) {
			if (rt2->rt_flags & RTF_LLINFO &&
				rt2->rt_flags & RTF_HOST &&
				rt2->rt_gateway &&
				rt2->rt_gateway->sa_family == AF_LINK) {
#ifdef __FreeBSD__
				rtexpunge(rt2);
				RTFREE_LOCKED(rt2);
#else
				rtrequest(RTM_DELETE,
					  (struct sockaddr *)rt_key(rt2),
					  rt2->rt_gateway,
					  rt_mask(rt2), rt2->rt_flags, 0);
#endif
				ret = rn_addroute(v_arg, n_arg, head,
					treenodes);
			} else
#ifdef __FreeBSD__
				RTFREE_LOCKED(rt2);
#else
				RTFREE(rt2);
#endif
		}
	} else if (ret == NULL && rt->rt_flags & RTF_CLONING) {
		struct rtentry *rt2;
		/*
		 * We are trying to add a net route, but can't.
		 * The following case should be allowed, so we'll make a
		 * special check for this:
		 *	Two IPv6 addresses with the same prefix is assigned
		 *	to a single interrface.
		 *	# ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1)
		 *	# ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2)
		 *	In this case, (*1) and (*2) want to add the same
		 *	net route entry, 3ffe:0501:: -> if0.
		 *	This case should not raise an error.
		 */
		rt2 = rtalloc1((struct sockaddr *)sin6, 0,
				RTF_CLONING
#ifdef RTF_PRCLONING
				| RTF_PRCLONING
#endif
			      );
		if (rt2) {
			if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY))
			    == RTF_CLONING && rt2->rt_gateway &&
			    rt2->rt_gateway->sa_family == AF_LINK &&
			    rt2->rt_ifp == rt->rt_ifp) {
				ret = rt2->rt_nodes;
			}
#ifdef __FreeBSD__
			RTFREE_LOCKED(rt2);
#else
			RTFREE(rt2);
#endif
		}
	}
	return ret;
}
예제 #26
0
파일: Protocol.cpp 프로젝트: DonCN/haiku
void
IPCP::UpdateAddresses()
{
	RemoveRoutes();
	
	if(State() != PPP_OPENED_STATE && !Interface().DoesConnectOnDemand())
		return;
	
	struct in_aliasreq inreq;
	struct ifreq ifreqAddress, ifreqDestination;
	memset(&inreq, 0, sizeof(struct in_aliasreq));
	memset(&ifreqAddress, 0, sizeof(struct ifreq));
	memset(&ifreqDestination, 0, sizeof(struct ifreq));
	memset(&fGateway, 0, sizeof(struct sockaddr_in));
	
	// create local address
	inreq.ifra_addr.sin_family = AF_INET;
	if(fLocalRequests.address != INADDR_ANY)
		inreq.ifra_addr.sin_addr.s_addr = fLocalRequests.address;
	else if(fLocalConfiguration.address == INADDR_ANY)
		inreq.ifra_addr.sin_addr.s_addr = 0x010F0F0F; // was: INADDR_BROADCAST
	else
		inreq.ifra_addr.sin_addr.s_addr = fLocalConfiguration.address;
	inreq.ifra_addr.sin_len = sizeof(struct sockaddr_in);
	memcpy(&ifreqAddress.ifr_addr, &inreq.ifra_addr, sizeof(struct sockaddr_in));
	
	// create destination address
	fGateway.sin_family = AF_INET;
	if(fPeerRequests.address != INADDR_ANY)
		fGateway.sin_addr.s_addr = fPeerRequests.address;
	else if(fPeerConfiguration.address == INADDR_ANY)
		fGateway.sin_addr.s_addr = 0x020F0F0F; // was: INADDR_BROADCAST
	else
		fGateway.sin_addr.s_addr = fPeerConfiguration.address;
	fGateway.sin_len = sizeof(struct sockaddr_in);
	memcpy(&inreq.ifra_dstaddr, &fGateway,
		sizeof(struct sockaddr_in));
	memcpy(&ifreqDestination.ifr_dstaddr, &inreq.ifra_dstaddr,
		sizeof(struct sockaddr_in));
	
	// create netmask
	inreq.ifra_mask.sin_family = AF_INET;
	inreq.ifra_mask.sin_addr.s_addr = fLocalRequests.netmask;
	inreq.ifra_mask.sin_len = sizeof(struct sockaddr_in);
	
	// tell stack to use these values
	if(in_control(NULL, SIOCAIFADDR, (caddr_t) &inreq,
			Interface().Ifnet()) != B_OK)
		ERROR("IPCP: UpdateAddress(): SIOCAIFADDR returned error!\n");
	if(in_control(NULL, SIOCSIFADDR, (caddr_t) &ifreqAddress,
			Interface().Ifnet()) != B_OK)
		ERROR("IPCP: UpdateAddress(): SIOCSIFADDR returned error!\n");
	if(in_control(NULL, SIOCSIFDSTADDR, (caddr_t) &ifreqDestination,
			Interface().Ifnet()) != B_OK)
		ERROR("IPCP: UpdateAddress(): SIOCSIFDSTADDR returned error!\n");
	memcpy(&inreq.ifra_addr, &inreq.ifra_mask, sizeof(struct sockaddr_in));
		// SIOCISFNETMASK wants the netmask to be in ifra_addr
	if(in_control(NULL, SIOCSIFNETMASK, (caddr_t) &inreq,
			Interface().Ifnet()) != B_OK)
		ERROR("IPCP: UpdateAddress(): SIOCSIFNETMASK returned error!\n");
	
	// add default/subnet route
	if(Side() == PPP_LOCAL_SIDE) {
		if(rtrequest(RTM_ADD, (struct sockaddr*) &inreq.ifra_mask,
				(struct sockaddr*) &fGateway, (struct sockaddr*) &inreq.ifra_mask,
				RTF_UP | RTF_GATEWAY, &fDefaultRoute) != B_OK)
			ERROR("IPCP: UpdateAddress(): could not add default/subnet route!\n");
		
		--fDefaultRoute->rt_refcnt;
	}
}
예제 #27
0
파일: in_rmx.c 프로젝트: epicsdeb/rtems
/*
 * Do what we need to do when inserting a route.
 */
static struct radix_node *
in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
	    struct radix_node *treenodes)
{
	struct rtentry *rt = (struct rtentry *)treenodes;
	struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
	struct radix_node *ret;

	/*
	 * For IP, all unicast non-host routes are automatically cloning.
	 */
	if(IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
		rt->rt_flags |= RTF_MULTICAST;

	if(!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
		rt->rt_flags |= RTF_PRCLONING;
	}

	/*
	 * A little bit of help for both IP output and input:
	 *   For host routes, we make sure that RTF_BROADCAST
	 *   is set for anything that looks like a broadcast address.
	 *   This way, we can avoid an expensive call to in_broadcast()
	 *   in ip_output() most of the time (because the route passed
	 *   to ip_output() is almost always a host route).
	 *
	 *   We also do the same for local addresses, with the thought
	 *   that this might one day be used to speed up ip_input().
	 *
	 * We also mark routes to multicast addresses as such, because
	 * it's easy to do and might be useful (but this is much more
	 * dubious since it's so easy to inspect the address).  (This
	 * is done above.)
	 */
	if (rt->rt_flags & RTF_HOST) {
		if (in_broadcast(sin->sin_addr, rt->rt_ifp)) {
			rt->rt_flags |= RTF_BROADCAST;
		} else {
#define satosin(sa) ((struct sockaddr_in *)sa)
			if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr
			    == sin->sin_addr.s_addr)
				rt->rt_flags |= RTF_LOCAL;
#undef satosin
		}
	}

	/*
	 * We also specify a send and receive pipe size for every
	 * route added, to help TCP a bit.  TCP doesn't actually
	 * want a true pipe size, which would be prohibitive in memory
	 * costs and is hard to compute anyway; it simply uses these
	 * values to size its buffers.  So, we fill them in with the
	 * same values that TCP would have used anyway, and allow the
	 * installing program or the link layer to override these values
	 * as it sees fit.  This will hopefully allow TCP more
	 * opportunities to save its ssthresh value.
	 */
	if (!rt->rt_rmx.rmx_sendpipe && !(rt->rt_rmx.rmx_locks & RTV_SPIPE))
		rt->rt_rmx.rmx_sendpipe = tcp_sendspace;

	if (!rt->rt_rmx.rmx_recvpipe && !(rt->rt_rmx.rmx_locks & RTV_RPIPE))
		rt->rt_rmx.rmx_recvpipe = tcp_recvspace;

	if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU) 
	    && rt->rt_ifp)
		rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;

	ret = rn_addroute(v_arg, n_arg, head, treenodes);
	if (ret == NULL && rt->rt_flags & RTF_HOST) {
		struct rtentry *rt2;
		/*
		 * We are trying to add a host route, but can't.
		 * Find out if it is because of an
		 * ARP entry and delete it if so.
		 */
		rt2 = rtalloc1((struct sockaddr *)sin, 0,
				RTF_CLONING | RTF_PRCLONING);
		if (rt2) {
			if (rt2->rt_flags & RTF_LLINFO &&
				rt2->rt_flags & RTF_HOST &&
				rt2->rt_gateway &&
				rt2->rt_gateway->sa_family == AF_LINK) {
				rtrequest(RTM_DELETE,
					  (struct sockaddr *)rt_key(rt2),
					  rt2->rt_gateway,
					  rt_mask(rt2), rt2->rt_flags, 0);
				ret = rn_addroute(v_arg, n_arg, head,
					treenodes);
			}
			RTFREE(rt2);
		}
	}
	return ret;
}