Пример #1
0
/*
 * arp_SetProxy - Make a proxy ARP entry for the peer.
 */
int
arp_SetProxy(struct bundle *bundle, struct in_addr addr, int s)
{
  struct arpreq arpreq;
  struct {
    struct sockaddr_dl sdl;
    char space[128];
  }      dls;

  memset(&arpreq, '\0', sizeof arpreq);

  /*
   * Get the hardware address of an interface on the same subnet as our local
   * address.
   */
  if (!arp_EtherAddr(addr, &dls.sdl, 1)) {
    log_Printf(LOG_PHASE_BIT, "Cannot determine ethernet address for "
               "proxy ARP\n");
    return 0;
  }
  arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
  arpreq.arp_ha.sa_family = AF_UNSPEC;
  memcpy(arpreq.arp_ha.sa_data, LLADDR(&dls.sdl), dls.sdl.sdl_alen);
  SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
  ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr;
  arpreq.arp_flags = ATF_PERM | ATF_PUBL;
  if (ID0ioctl(s, SIOCSARP, (caddr_t) & arpreq) < 0) {
    log_Printf(LogERROR, "arp_SetProxy: ioctl(SIOCSARP): %s\n",
               strerror(errno));
    return 0;
  }
  return 1;
}
Пример #2
0
int
iface_Name(struct iface *iface, const char *name)
{
  struct ifreq ifr;
  int s;
  char *newname;

  if ((newname = strdup(name)) == NULL) {
    log_Printf(LogWARN, "iface name: strdup failed: %s\n", strerror(errno));
    return 0;
  }

  if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
    log_Printf(LogERROR, "iface name: socket(): %s\n", strerror(errno));
    free(newname);
    return 0;
  }

  strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
  ifr.ifr_data = newname;
  if (ID0ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
    log_Printf(LogWARN, "iface name: ioctl(SIOCSIFNAME, %s -> %s): %s\n",
               name, newname, strerror(errno));
    free(newname);
    return 0;
  }

  free(iface->name);
  iface->name = newname;

  return 1;
}
Пример #3
0
static int
iface_ChangeFlags(const char *ifname, int flags, int how)
{
  struct ifreq ifrq;
  int s, new_flags;

  s = ID0socket(PF_INET, SOCK_DGRAM, 0);
  if (s < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: socket: %s\n", strerror(errno));
    return 0;
  }

  memset(&ifrq, '\0', sizeof ifrq);
  strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1);
  ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
  if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCGIFFLAGS): %s\n",
       strerror(errno));
    close(s);
    return 0;
  }
#ifdef __FreeBSD__
  new_flags = (ifrq.ifr_flags & 0xffff) | (ifrq.ifr_flagshigh << 16);
#else
  new_flags = ifrq.ifr_flags & 0xffff;
#endif

  if (how == IFACE_ADDFLAGS)
    new_flags |= flags;
  else
    new_flags &= ~flags;
  ifrq.ifr_flags = new_flags & 0xffff;
#ifdef __FreeBSD__
  ifrq.ifr_flagshigh = new_flags >> 16;
#endif

  if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCSIFFLAGS): %s\n",
       strerror(errno));
    close(s);
    return 0;
  }
  close(s);

  return 1;	/* Success */
}
Пример #4
0
static int
iface_ChangeFlags(const char *ifname, int flags, int how)
{
  struct ifreq ifrq;
  int s;

  s = ID0socket(PF_INET, SOCK_DGRAM, 0);
  if (s < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: socket: %s\n", strerror(errno));
    return 0;
  }

  memset(&ifrq, '\0', sizeof ifrq);
  strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1);
  ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
  if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCGIFFLAGS): %s\n",
       strerror(errno));
    close(s);
    return 0;
  }

  if (how == IFACE_ADDFLAGS)
    ifrq.ifr_flags |= flags;
  else
    ifrq.ifr_flags &= ~flags;

  if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
    log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCSIFFLAGS): %s\n",
       strerror(errno));
    close(s);
    return 0;
  }
  close(s);

  return 1;	/* Success */
}
Пример #5
0
/*
 * arp_ClearProxy - Delete the proxy ARP entry for the peer.
 */
int
arp_ClearProxy(struct bundle *bundle, struct in_addr addr, int s)
{
  struct arpreq arpreq;

  memset(&arpreq, '\0', sizeof arpreq);
  SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
  ((struct sockaddr_in *)&arpreq.arp_pa)->sin_addr.s_addr = addr.s_addr;
  if (ID0ioctl(s, SIOCDARP, (caddr_t) & arpreq) < 0) {
    log_Printf(LogERROR, "arp_ClearProxy: ioctl(SIOCDARP): %s\n",
               strerror(errno));
    return 0;
  }
  return 1;
}
Пример #6
0
void
iface_Destroy(struct iface *iface)
{
  struct ifreq ifr;
  int s;

  if (iface != NULL) {
    if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
      log_Printf(LogERROR, "iface_Destroy: socket(): %s\n", strerror(errno));
    } else {
      strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
      if (ID0ioctl(s, SIOCIFDESTROY, (caddr_t)&ifr) < 0)
        log_Printf(LogWARN, "iface_Destroy: ioctl(SIOCIFDESTROY, %s): %s\n",
               iface->name, strerror(errno));
    }
    iface_Free(iface);
  }
}
Пример #7
0
void
tun_configure(struct bundle *bundle)
{
#ifdef __NetBSD__
  struct ifreq ifr;
  int s;

  s = socket(PF_INET, SOCK_DGRAM, 0);

  if (s < 0) {
    log_Printf(LogERROR, "tun_configure: socket(): %s\n", strerror(errno));
    return;
  }

  sprintf(ifr.ifr_name, "tun%d", bundle->unit);
  ifr.ifr_mtu = bundle->iface->mtu;
  if (ioctl(s, SIOCSIFMTU, &ifr) < 0)
      log_Printf(LogERROR, "tun_configure: ioctl(SIOCSIFMTU): %s\n",
             strerror(errno));

  close(s);
#else
  struct tuninfo info;

  memset(&info, '\0', sizeof info);
  info.type = IFT_PPP;
  info.mtu = bundle->iface->mtu;

  info.baudrate = bundle->bandwidth;
#ifdef __OpenBSD__
  info.flags = IFF_UP|IFF_POINTOPOINT|IFF_MULTICAST;
#endif
  if (ID0ioctl(bundle->dev.fd, TUNSIFINFO, &info) < 0)
    log_Printf(LogERROR, "tun_configure: ioctl(TUNSIFINFO): %s\n",
	      strerror(errno));
#endif
}
Пример #8
0
int
iface_Descr(struct cmdargs const *arg)
{
  struct ifreq ifr;
  struct iface *iface;
  size_t sz, len;
  int s, n, ifdescr_maxlen;
  char *descr;

  sz = sizeof(int);
  if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) {
    log_Printf(LogERROR, "iface descr: sysctl failed: %s\n", strerror(errno));
    return 1;
  }

  if (ifdescr_maxlen < 1) {
    log_Printf(LogERROR, "iface descr: sysctl net.ifdescr_maxlen < 1\n");
    return 1;
  }

  sz = sizeof(char) * ifdescr_maxlen;
  if ((descr = malloc(sz)) == NULL) {
    log_Printf(LogERROR, "iface descr: malloc failed: %s\n", strerror(errno));
    return 1;
  }

  *descr = '\0';
  n = arg->argn;
  while (n < arg->argc) {
    if (n > arg->argn && (len = strlcat(descr, " ", sz)) >= sz)
      break;
    if ((len = strlcat(descr, arg->argv[n], sz)) >= sz)
      break;
    ++n;
  }
  if (len >= sz) {
    log_Printf(LogERROR, "iface descr: description exceeds maximum (%d)\n",
               ifdescr_maxlen-1);
    free(descr);
    return 1;
  }

  if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
    log_Printf(LogERROR, "iface descr: socket(): %s\n", strerror(errno));
    free(descr);
    return 1;
  }

  iface = arg->bundle->iface;
  strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
  ifr.ifr_buffer.length = strlen(descr) + 1;
  ifr.ifr_buffer.buffer = descr;
  if (ID0ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) {
    log_Printf(LogWARN, "iface descr: ioctl(SIOCSIFDESCR, %s): %s\n",
               descr, strerror(errno));
    free(descr);
    return 1;
  }

  free(iface->descr);
  iface->descr = descr;

  return 0;
}
Пример #9
0
static int
iface_addr_Add(const char *name, struct iface_addr *addr, int s)
{
  struct ifaliasreq ifra;
#ifndef NOINET6
  struct in6_aliasreq ifra6;
#endif
  struct sockaddr_in *me4, *msk4, *peer4;
  struct sockaddr_storage ssme, sspeer, ssmsk;
  int res;

  ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
  ncpaddr_getsa(&addr->peer, &sspeer);
  res = 0;

  switch (ncprange_family(&addr->ifa)) {
  case AF_INET:
    memset(&ifra, '\0', sizeof ifra);
    strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);

    me4 = (struct sockaddr_in *)&ifra.ifra_addr;
    memcpy(me4, &ssme, sizeof *me4);

    msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
    memcpy(msk4, &ssmsk, sizeof *msk4);

    peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
    if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
      peer4->sin_family = AF_INET;
      peer4->sin_len = sizeof(*peer4);
      peer4->sin_addr.s_addr = INADDR_NONE;
    } else
      memcpy(peer4, &sspeer, sizeof *peer4);

    res = ID0ioctl(s, SIOCAIFADDR, &ifra);
    if (log_IsKept(LogDEBUG)) {
      char buf[100];

      snprintf(buf, sizeof buf, "%s", ncprange_ntoa(&addr->ifa));
      log_Printf(LogWARN, "%s: AIFADDR %s -> %s returns %d\n",
                 ifra.ifra_name, buf, ncpaddr_ntoa(&addr->peer), res);
    }
    break;

#ifndef NOINET6
  case AF_INET6:
    memset(&ifra6, '\0', sizeof ifra6);
    strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);

    memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
    memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
    if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
      ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
    else if (memcmp(&((struct sockaddr_in6 *)&ssmsk)->sin6_addr, &in6mask128,
		    sizeof in6mask128) == 0)
      memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
    ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
    ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;

    res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6);
    break;
#endif
  }

  if (res == -1) {
    char dst[40];
    const char *end =
#ifndef NOINET6
      ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
#endif
      "";

    if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
      log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n",
                 end, ncprange_ntoa(&addr->ifa), strerror(errno));
    else {
      snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
      log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s -> %s): %s\n",
                 end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
    }
  }

  return res != -1;
}