Example #1
0
void
route_Change(struct bundle *bundle, struct sticky_route *r,
             const struct ncpaddr *me, const struct ncpaddr *peer)
{
  struct ncpaddr dst;

  for (; r; r = r->next) {
    ncprange_getaddr(&r->dst, &dst);
    if (ncpaddr_family(me) == AF_INET) {
      if ((r->type & ROUTE_DSTMYADDR) && !ncpaddr_equal(&dst, me)) {
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        ncprange_sethost(&r->dst, me);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_DSTHISADDR) && !ncpaddr_equal(&dst, peer)) {
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        ncprange_sethost(&r->dst, peer);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_DSTDNS0) && !ncpaddr_equal(&dst, peer)) {
        if (bundle->ncp.ipcp.ns.dns[0].s_addr == INADDR_NONE)
          continue;
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_DSTDNS1) && !ncpaddr_equal(&dst, peer)) {
        if (bundle->ncp.ipcp.ns.dns[1].s_addr == INADDR_NONE)
          continue;
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_GWHISADDR) && !ncpaddr_equal(&r->gw, peer))
        ncpaddr_copy(&r->gw, peer);
#ifndef NOINET6
    } else if (ncpaddr_family(me) == AF_INET6) {
      if ((r->type & ROUTE_DSTMYADDR6) && !ncpaddr_equal(&dst, me)) {
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        ncprange_sethost(&r->dst, me);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_DSTHISADDR6) && !ncpaddr_equal(&dst, peer)) {
        rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
        ncprange_sethost(&r->dst, peer);
        if (r->type & ROUTE_GWHISADDR)
          ncpaddr_copy(&r->gw, peer);
      } else if ((r->type & ROUTE_GWHISADDR6) && !ncpaddr_equal(&r->gw, peer))
        ncpaddr_copy(&r->gw, peer);
#endif
    }
    rt_Set(bundle, RTM_ADD, &r->dst, &r->gw, 1, 0);
  }
}
Example #2
0
/*
 *  Delete routes associated with our interface
 */
void
route_IfDelete(struct bundle *bundle, int all)
{
  struct rt_msghdr *rtm;
  struct sockaddr *sa[RTAX_MAX];
  struct ncprange range;
  int pass;
  size_t needed;
  char *sp, *cp, *ep;
  int mib[6];

  log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->iface->index);

  mib[0] = CTL_NET;
  mib[1] = PF_ROUTE;
  mib[2] = 0;
  mib[3] = 0;
  mib[4] = NET_RT_DUMP;
  mib[5] = 0;
  if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
    log_Printf(LogERROR, "route_IfDelete: sysctl: estimate: %s\n",
              strerror(errno));
    return;
  }

  sp = malloc(needed);
  if (sp == NULL)
    return;

  if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) {
    log_Printf(LogERROR, "route_IfDelete: sysctl: getroute: %s\n",
              strerror(errno));
    free(sp);
    return;
  }
  ep = sp + needed;

  for (pass = 0; pass < 2; pass++) {
    /*
     * We do 2 passes.  The first deletes all cloned routes.  The second
     * deletes all non-cloned routes.  This is done to avoid
     * potential errors from trying to delete route X after route Y where
     * route X was cloned from route Y (and is no longer there 'cos it
     * may have gone with route Y).
     */
    if (RTF_WASCLONED == 0 && pass == 0)
      /* So we can't tell ! */
      continue;
    for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
      rtm = (struct rt_msghdr *)cp;
      route_ParseHdr(rtm, sa);
      if (rtm->rtm_index == bundle->iface->index &&
          sa[RTAX_DST] && sa[RTAX_GATEWAY] &&
          (sa[RTAX_DST]->sa_family == AF_INET
#ifndef NOINET6
           || sa[RTAX_DST]->sa_family == AF_INET6
#endif
           ) &&
          (all || (rtm->rtm_flags & RTF_GATEWAY))) {
        if (log_IsKept(LogDEBUG)) {
          char gwstr[41];
          struct ncpaddr gw;
          ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]);
          ncpaddr_setsa(&gw, sa[RTAX_GATEWAY]);
          snprintf(gwstr, sizeof gwstr, "%s", ncpaddr_ntoa(&gw));
          log_Printf(LogDEBUG, "Found %s %s\n", ncprange_ntoa(&range), gwstr);
        }
        if (sa[RTAX_GATEWAY]->sa_family == AF_INET ||
#ifndef NOINET6
            sa[RTAX_GATEWAY]->sa_family == AF_INET6 ||
#endif
            sa[RTAX_GATEWAY]->sa_family == AF_LINK) {
          if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
              (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
            ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]);
            rt_Set(bundle, RTM_DELETE, &range, NULL, 0, 0);
          } else
            log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass);
        } else
          log_Printf(LogDEBUG,
                    "route_IfDelete: Can't remove routes for family %d\n",
                    sa[RTAX_GATEWAY]->sa_family);
      }
    }
  }
  free(sp);
}
Example #3
0
static int
ipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_char *myifid, u_char *hisifid)
{
  struct bundle *bundle = ipv6cp->fsm.bundle;
  struct in6_addr myaddr, hisaddr;
  struct ncprange myrange, range;
  struct ncpaddr addr;
  struct sockaddr_storage ssdst, ssgw, ssmask;
  struct sockaddr *sadst, *sagw, *samask;

  sadst = (struct sockaddr *)&ssdst;
  sagw = (struct sockaddr *)&ssgw;
  samask = (struct sockaddr *)&ssmask;

  memset(&myaddr, '\0', sizeof myaddr);
  memset(&hisaddr, '\0', sizeof hisaddr);

  myaddr.s6_addr[0] = 0xfe;
  myaddr.s6_addr[1] = 0x80;
  memcpy(&myaddr.s6_addr[8], myifid, IPV6CP_IFIDLEN);
#if 0
  myaddr.s6_addr[8] |= 0x02;	/* set 'universal' bit */
#endif

  hisaddr.s6_addr[0] = 0xfe;
  hisaddr.s6_addr[1] = 0x80;
  memcpy(&hisaddr.s6_addr[8], hisifid, IPV6CP_IFIDLEN);
#if 0
  hisaddr.s6_addr[8] |= 0x02;	/* set 'universal' bit */
#endif

  ncpaddr_setip6(&ipv6cp->myaddr, &myaddr);
  ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr);
  ncprange_set(&myrange, &ipv6cp->myaddr, 64);

  if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr,
                 IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM))
    return 0;

  if (!Enabled(bundle, OPT_IFACEALIAS))
    iface_Clear(bundle->iface, &bundle->ncp, AF_INET6,
                IFACE_CLEAR_ALIASES|IFACE_SYSTEM);

  ncpaddr_setip6(&addr, &in6addr_linklocal_mcast);
  ncprange_set(&range, &addr, 32);
  rt_Set(bundle, RTM_ADD, &range, &ipv6cp->myaddr, 1, 0);

  if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) {
    ncprange_getsa(&myrange, &ssgw, &ssmask);
    if (ncpaddr_isset(&ipv6cp->hisaddr))
      ncpaddr_getsa(&ipv6cp->hisaddr, &ssdst);
    else
      sadst = NULL;
    rt_Update(bundle, sadst, sagw, samask, NULL, NULL);
  }

  if (Enabled(bundle, OPT_SROUTES))
    route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr);

#ifndef NORADIUS
  if (bundle->radius.valid)
    route_Change(bundle, bundle->radius.ipv6routes, &ipv6cp->myaddr,
                 &ipv6cp->hisaddr);
#endif

  return 1;	/* Ok */
}