/**
 * @return
 * the MAC address of the main IP address
 */
unsigned char * getMainIpMacAddress(void) {
	if (!macSet) {
		struct ifreq ifr;
		unsigned char * macInIfr;

		struct interface *mainInterface = if_ifwithaddr(&olsr_cnf->main_addr);
		if (!mainInterface) {
			pudError(true, "Could not get the main interface");
			return NULL;
		}
		macInIfr = getHardwareAddress(mainInterface->int_name, olsr_cnf->ip_version, &ifr);
		if (!macInIfr) {
			pudError(true, "Could not get the MAC address of the main interface");
			return NULL;
		}
		memcpy(&mac[0], &macInIfr[0], PUD_NODEIDTYPE_MAC_BYTES);
		macSet = true;
	}

	return &mac[0];
}
Example #2
0
File: Bmf.c Project: Dany3R9/Proj
/* -------------------------------------------------------------------------
 * Function   : BmfEncapsulationPacketReceived
 * Description: Handle a received BMF-encapsulation packet
 * Input      : intf - the network interface on which the packet was received
 *              forwardedBy - the IP node that forwarded the packet to me
 *              forwardedTo - the destination IP address of the encapsulation
 *                packet, in case the packet was received promiscuously.
 *                Pass NULL if the packet is received normally (unicast or
 *                broadcast).
 *              encapsulationUdpData - the encapsulating IP UDP data, containting
 *                the BMF encapsulation header, followed by the encapsulated
 *                IP packet
 * Output     : none
 * Return     : none
 * Data Used  : BmfInterfaces
 * ------------------------------------------------------------------------- */
static void BmfEncapsulationPacketReceived(
  struct TBmfInterface* intf,
  union olsr_ip_addr* forwardedBy,
  union olsr_ip_addr* forwardedTo,
  unsigned char* encapsulationUdpData)
{
  int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */
  unsigned char* ipPacket; /* The encapsulated IP packet */
  u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */
  struct ip* ipHeader; /* IP header inside the encapsulated IP packet */
  union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */
  union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */
  struct TEncapHeader* encapsulationHdr;
  struct TBmfInterface* walker;
#ifndef NODEBUG
  struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf;
#endif
  /* Are we talking to ourselves? */
  if (if_ifwithaddr(forwardedBy) != NULL)
  {
    return;
  }

  /* Discard encapsulated packets received on a non-OLSR interface */
  if (intf->olsrIntf == NULL)
  {
    return;
  }

  /* Retrieve details about the encapsulated IP packet */
  ipPacket = GetIpPacket(encapsulationUdpData);
  ipPacketLen = GetIpTotalLength(ipPacket);
  ipHeader = GetIpHeader(encapsulationUdpData);

  mcSrc.v4 = ipHeader->ip_src;
  mcDst.v4 = ipHeader->ip_dst;

  /* Increase counter */
  intf->nBmfPacketsRx++;

  /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */
  OLSR_PRINTF(
    8,
    "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n",
    PLUGIN_NAME_SHORT,
    (long)ipPacketLen,
    intf->ifName,
    olsr_ip_to_string(&mcSrcBuf, &mcSrc),
    olsr_ip_to_string(&mcDstBuf, &mcDst),
    olsr_ip_to_string(&forwardedByBuf, forwardedBy),
    forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me");

  /* Get encapsulation header */
  encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData;

  /* Verify correct format of BMF encapsulation header */
  if (encapsulationHdr->type != BMF_ENCAP_TYPE ||
      encapsulationHdr->len != BMF_ENCAP_LEN ||
      ntohs(encapsulationHdr->reserved != 0))
  {
    OLSR_PRINTF(
      8,
      "%s: --> discarding: format of BMF encapsulation header not recognized\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  /* Check if this packet was seen recently */
  if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32)))
  {
    /* Increase counter */
    intf->nBmfPacketsRxDup++;

    OLSR_PRINTF(
      8,
      "%s: --> discarding: packet is duplicate\n",
      PLUGIN_NAME_SHORT);
    return;
  }

  if (EtherTunTapFd >= 0)
  {
    /* Unpack the encapsulated IP packet and deliver it locally, by sending
     * a copy into the local IP stack via the EtherTunTap interface */

    union olsr_ip_addr broadAddr;
    int nBytesToWrite, nBytesWritten;
    unsigned char* bufferToWrite;

    /* If the encapsulated IP packet is a local broadcast packet,
     * update its destination address to match the subnet of the EtherTunTap
     * interface */
    broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast);
    CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr);

    bufferToWrite = ipPacket;
    nBytesToWrite = ipPacketLen;

    /* Write the packet into the EtherTunTap interface for local delivery */
    nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
    if (nBytesWritten != nBytesToWrite)
    {
      BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName);
    }
    else
    {
      OLSR_PRINTF(
        8,
        "%s: --> unpacked and delivered locally on \"%s\"\n",
        PLUGIN_NAME_SHORT,
        EtherTunTapIfName);
    }
  } /* if (EtherTunTapFd >= 0) */

  /* Check if I am MPR for the forwarder */
  iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL);

  /* Check with each network interface what needs to be done on it */
  for (walker = BmfInterfaces; walker != NULL; walker = walker->next)
  {
    /* What to do with the packet on a non-OLSR interface? Unpack
     * encapsulated packet, and forward it.
     *
     * What to do with the packet on an OLSR interface? Forward it only
     * if the forwarding node has selected us as MPR (iAmMpr).
     *
     * Note that the packet is always coming in on an OLSR interface, because
     * it is an encapsulated BMF packet. */

    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
    if (walker->olsrIntf == NULL)
    {
      ForwardPacket (walker, ipPacket, ipPacketLen, "unpacked and forwarded to non-OLSR interface");
    } /* if (walker->olsrIntf == NULL) */

    /* To an OLSR interface: forward the packet, but only if this node is
     * selected as MPR by the forwarding node */
    else if (iAmMpr)
    {
      EncapsulateAndForwardPacket (
        walker,
        encapsulationUdpData,
        &mcSrc,
        forwardedBy,
        forwardedTo);
    }  /* else if (iAmMpr) */

    else /* walker->olsrIntf != NULL && !iAmMpr */
    {
#ifndef NODEBUG
      struct ipaddr_str buf;
#endif
      /* 'walker' is an OLSR interface, but I am not selected as MPR. In that
       * case, don't forward. */
      OLSR_PRINTF(
        8,
        "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n",
        PLUGIN_NAME_SHORT,
        walker->ifName,
        olsr_ip_to_string(&buf, forwardedBy));
    } /* else */
  } /* for */
} /* BmfEncapsulationPacketReceived */
Example #3
0
void ifinit(void)
{
    struct interface ifs, *ifp;
    int s;
    char buf[BUFSIZ], *cp, *cplim;
    struct ifconf ifc;
    struct ifreq ifreq, *ifr;
    struct sockaddr_in *sin;
    u_long i;

    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        syslog(LOG_ERR, "socket: %m");
        close(s);
        return;
    }
    ifc.ifc_len = sizeof (buf);
    ifc.ifc_buf = buf;
    if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
        syslog(LOG_ERR, "ioctl (get interface configuration)");
        close(s);
        return;
    }
    ifr = ifc.ifc_req;
    lookforinterfaces = 0;
    cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
    for (cp = buf; cp < cplim;
            cp += sizeof (ifr->ifr_name) + sizeof(ifr->ifr_ifru)) {
        ifr = (struct ifreq *)cp;
        bzero((char *)&ifs, sizeof(ifs));
        ifs.int_addr = ifr->ifr_addr;
        ifreq = *ifr;
        if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get interface flags)",
                   ifr->ifr_name);
            continue;
        }
        ifs.int_flags =
            ifreq.ifr_flags | IFF_INTERFACE;
        if ((ifs.int_flags & IFF_UP) == 0 ||
                ifr->ifr_addr.sa_family == AF_UNSPEC) {
            lookforinterfaces = 1;
            continue;
        }
        /* argh, this'll have to change sometime */
        if (ifs.int_addr.sa_family != AF_INET)
            continue;
        if (ifs.int_flags & IFF_POINTOPOINT) {
            if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
                       ifr->ifr_name);
                continue;
            }
            if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
                lookforinterfaces = 1;
                continue;
            }
            ifs.int_dstaddr = ifreq.ifr_dstaddr;
        }
        /*
         * already known to us?
         * This allows multiple point-to-point links
         * to share a source address (possibly with one
         * other link), but assumes that there will not be
         * multiple links with the same destination address.
         */
        if (ifs.int_flags & IFF_POINTOPOINT) {
            if (if_ifwithdstaddr(&ifs.int_dstaddr))
                continue;
        } else if (if_ifwithaddr(&ifs.int_addr))
            continue;
        if (ifs.int_flags & IFF_LOOPBACK) {
            ifs.int_flags |= IFF_PASSIVE;
            foundloopback = 1;
            loopaddr = ifs.int_addr;
            for (ifp = ifnet; ifp; ifp = ifp->int_next)
                if (ifp->int_flags & IFF_POINTOPOINT)
                    add_ptopt_localrt(ifp);
        }
        if (ifs.int_flags & IFF_BROADCAST) {
            if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
                       ifr->ifr_name);
                continue;
            }
            ifs.int_broadaddr = ifreq.ifr_broadaddr;
        }
#ifdef SIOCGIFMETRIC
        if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get metric)",
                   ifr->ifr_name);
            ifs.int_metric = 0;
        } else
            ifs.int_metric = ifreq.ifr_metric;
#else
        ifs.int_metric = 0;
#endif
        /*
         * Use a minimum metric of one;
         * treat the interface metric (default 0)
         * as an increment to the hop count of one.
         */
        ifs.int_metric++;
        if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
            syslog(LOG_ERR, "%s: ioctl (get netmask)",
                   ifr->ifr_name);
            continue;
        }
        sin = (struct sockaddr_in *)&ifreq.ifr_addr;
        ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
        sin = (struct sockaddr_in *)&ifs.int_addr;
        i = ntohl(sin->sin_addr.s_addr);
        if (IN_CLASSA(i))
            ifs.int_netmask = IN_CLASSA_NET;
        else if (IN_CLASSB(i))
            ifs.int_netmask = IN_CLASSB_NET;
        else
            ifs.int_netmask = IN_CLASSC_NET;
        ifs.int_net = i & ifs.int_netmask;
        ifs.int_subnet = i & ifs.int_subnetmask;
        if (ifs.int_subnetmask != ifs.int_netmask)
            ifs.int_flags |= IFF_SUBNET;
        ifp = (struct interface *)malloc(sizeof (struct interface));
        if (ifp == 0) {
            printf("routed: out of memory\n");
            break;
        }
        *ifp = ifs;
        /*
         * Count the # of directly connected networks
         * and point to point links which aren't looped
         * back to ourself.  This is used below to
         * decide if we should be a routing ``supplier''.
         */
        if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
                ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
                 if_ifwithaddr(&ifs.int_dstaddr) == 0))
            externalinterfaces++;
        /*
         * If we have a point-to-point link, we want to act
         * as a supplier even if it's our only interface,
         * as that's the only way our peer on the other end
         * can tell that the link is up.
         */
        if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
            supplier = 1;
        ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
        if (ifp->int_name == 0) {
            fprintf(stderr, "routed: ifinit: out of memory\n");
            syslog(LOG_ERR, "routed: ifinit: out of memory\n");
            close(s);
            return;
        }
        strcpy(ifp->int_name, ifr->ifr_name);
        *ifnext = ifp;
        ifnext = &ifp->int_next;
        traceinit(ifp);
        addrouteforif(ifp);
    }
    if (externalinterfaces > 1 && supplier < 0)
        supplier = 1;
    close(s);
}
Example #4
0
/**
 *Processes an list of neighbors from an incoming HELLO message.
 *@param neighbor the neighbor who sent the message.
 *@param message the HELLO message
 *@return nada
 */
static void
process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message)
{
  struct hello_neighbor *message_neighbors;

  for (message_neighbors = message->neighbors; message_neighbors != NULL; message_neighbors = message_neighbors->next) {
    union olsr_ip_addr *neigh_addr;
    struct neighbor_2_entry *two_hop_neighbor;

    /*
     *check all interfaces
     *so that we don't add ourselves to the
     *2 hop list
     *IMPORTANT!
     */
    if (if_ifwithaddr(&message_neighbors->address) != NULL)
      continue;

    /* Get the main address */
    neigh_addr = mid_lookup_main_addr(&message_neighbors->address);

    if (neigh_addr != NULL) {
      message_neighbors->address = *neigh_addr;
    }

    if (((message_neighbors->status == SYM_NEIGH) || (message_neighbors->status == MPR_NEIGH))) {
      struct neighbor_2_list_entry *two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor, &message_neighbors->address);

      if (two_hop_neighbor_yet != NULL) {
        /* Updating the holding time for this neighbor */
        olsr_set_timer(&two_hop_neighbor_yet->nbr2_list_timer, message->vtime, OLSR_NBR2_LIST_JITTER, OLSR_TIMER_ONESHOT,
                       &olsr_expire_nbr2_list, two_hop_neighbor_yet, 0);
        two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;

        /*
         * For link quality OLSR, reset the path link quality here.
         * The path link quality will be calculated in the second pass, below.
         * Keep the saved_path_link_quality for reference.
         */

        if (olsr_cnf->lq_level > 0) {
          /*
           * loop through the one-hop neighbors that see this
           * 'two_hop_neighbor'
           */

          struct neighbor_list_entry *walker;

          for (walker = two_hop_neighbor->neighbor_2_nblist.next; walker != &two_hop_neighbor->neighbor_2_nblist;
               walker = walker->next) {
            /*
             * have we found the one-hop neighbor that sent the
             * HELLO message that we're current processing?
             */

            if (walker->neighbor == neighbor) {
              walker->path_linkcost = LINK_COST_BROKEN;
            }
          }
        }
      } else {
        two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&message_neighbors->address);
        if (two_hop_neighbor == NULL) {
          changes_neighborhood = true;
          changes_topology = true;

          two_hop_neighbor = olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO");

          two_hop_neighbor->neighbor_2_nblist.next = &two_hop_neighbor->neighbor_2_nblist;

          two_hop_neighbor->neighbor_2_nblist.prev = &two_hop_neighbor->neighbor_2_nblist;

          two_hop_neighbor->neighbor_2_pointer = 0;

          two_hop_neighbor->neighbor_2_addr = message_neighbors->address;

          olsr_insert_two_hop_neighbor_table(two_hop_neighbor);

          linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
        } else {
          /*
             linking to this two_hop_neighbor entry
           */
          changes_neighborhood = true;
          changes_topology = true;

          linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime);
        }
      }
    }
  }

  /* Separate, second pass for link quality OLSR */
  /* Separate, second and third pass for link quality OLSR */

  if (olsr_cnf->lq_level > 0) {
    olsr_linkcost first_hop_pathcost;
    struct link_entry *lnk = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);

    if (!lnk)
      return;

    /* calculate first hop path quality */
    first_hop_pathcost = lnk->linkcost;
    /*
     *  Second pass for link quality OLSR: calculate the best 2-hop
     * path costs to all the 2-hop neighbors indicated in the
     * HELLO message. Since the same 2-hop neighbor may be listed
     * more than once in the same HELLO message (each at a possibly
     * different quality) we want to select only the best one, not just
     * the last one listed in the HELLO message.
     */

    for (message_neighbors = message->neighbors; message_neighbors != NULL; message_neighbors = message_neighbors->next) {
      if (if_ifwithaddr(&message_neighbors->address) != NULL)
        continue;

      if (((message_neighbors->status == SYM_NEIGH) || (message_neighbors->status == MPR_NEIGH))) {
        struct neighbor_list_entry *walker;
        struct neighbor_2_entry *two_hop_neighbor;
        struct neighbor_2_list_entry *two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor,
                                                                                      &message_neighbors->address);

        if (!two_hop_neighbor_yet)
          continue;

        two_hop_neighbor = two_hop_neighbor_yet->neighbor_2;

        /*
         *  loop through the one-hop neighbors that see this
         * 'two_hop_neighbor'
         */

        for (walker = two_hop_neighbor->neighbor_2_nblist.next; walker != &two_hop_neighbor->neighbor_2_nblist;
             walker = walker->next) {
          /*
           * have we found the one-hop neighbor that sent the
           * HELLO message that we're current processing?
           */

          if (walker->neighbor == neighbor) {
            olsr_linkcost new_second_hop_linkcost, new_path_linkcost;

            // the link cost between the 1-hop neighbour and the
            // 2-hop neighbour

            new_second_hop_linkcost = message_neighbors->cost;

            // the total cost for the route
            // "us --- 1-hop --- 2-hop"

            new_path_linkcost = first_hop_pathcost + new_second_hop_linkcost;

            // Only copy the link quality if it is better than what we have
            // for this 2-hop neighbor
            if (new_path_linkcost < walker->path_linkcost) {
              walker->second_hop_linkcost = new_second_hop_linkcost;
              walker->path_linkcost = new_path_linkcost;

              walker->saved_path_linkcost = new_path_linkcost;

              changes_neighborhood = true;
              changes_topology = true;
            }
          }
        }
      }
    }
  }
}
Example #5
0
/* -------------------------------------------------------------------------
 * Function   : CreateBmfNetworkInterfaces
 * Description: Create a list of TBmfInterface objects, one for each network
 *              interface on which BMF runs
 * Input      : skipThisIntf - network interface to skip, if seen
 * Output     : none
 * Return     : fail (-1) or success (0)
 * Data Used  : none
 * ------------------------------------------------------------------------- */
int
CreateBmfNetworkInterfaces(struct interface *skipThisIntf)
{
  int skfd;
  struct ifconf ifc;
  int numreqs = 30;
  struct ifreq *ifr;
  int n;
  int nOpenedSockets = 0;

  /* Clear input descriptor set */
  FD_ZERO(&InputSet);

  skfd = socket(PF_INET, SOCK_DGRAM, 0);
  if (skfd < 0) {
    BmfPError("no inet socket available to retrieve interface list");
    return -1;
  }

  /* Retrieve the network interface configuration list */
  ifc.ifc_buf = NULL;
  for (;;) {
    ifc.ifc_len = sizeof(struct ifreq) * numreqs;
    ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);

    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
      BmfPError("ioctl(SIOCGIFCONF) error");

      close(skfd);
      free(ifc.ifc_buf);
      return -1;
    }
    if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
      /* Assume it overflowed; double the space and try again */
      numreqs *= 2;
      assert(numreqs < 1024);
      continue;                 /* for (;;) */
    }
    break;                      /* for (;;) */
  }                             /* for (;;) */

  close(skfd);

  /* For each item in the interface configuration list... */
  ifr = ifc.ifc_req;
  for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
    struct interface *olsrIntf;
    union olsr_ip_addr ipAddr;

    /* Skip the BMF network interface itself */
    //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
    //{
    //  continue; /* for (n = ...) */
    //}

    /* ...find the OLSR interface structure, if any */
    ipAddr.v4 = ((struct sockaddr_in *)ARM_NOWARN_ALIGN(&ifr->ifr_addr))->sin_addr;
    olsrIntf = if_ifwithaddr(&ipAddr);

    if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
      continue;                 /* for (n = ...) */
    }

    if (olsrIntf == NULL && !IsNonOlsrBmfIf(ifr->ifr_name)) {
      /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
       * interface in the BMF plugin parameter list */
      continue;                 /* for (n = ...) */
    }

    if (!IsNonOlsrBmfIf(ifr->ifr_name)) {
      //If the interface is not specified in the configuration file then go ahead
      continue;                 /* for (n = ...) */
    }
    //TODO: asser if->ifr_name is not talking OLSR
    //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
    nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);

  }                             /* for (n = ...) */

  free(ifc.ifc_buf);

  if (BmfInterfaces == NULL) {
    //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
  } else {
    //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
  }
  return 0;
}                               /* CreateBmfNetworkInterfaces */
Example #6
0
/*
 * Find the network interfaces which have configured themselves.
 * If the interface is present but not yet up (for example an
 * ARPANET IMP), set the lookforinterfaces flag so we'll
 * come back later and look again.
 */
void
ifinit(void)
{
	struct interface ifs, *ifp;
	size_t needed;
	int mib[6], no_ipxaddr = 0, flags = 0;
	char *buf, *cplim, *cp;
	struct if_msghdr *ifm;
	struct ifa_msghdr *ifam;
	struct sockaddr_dl *sdl = NULL;

        mib[0] = CTL_NET;
        mib[1] = PF_ROUTE;
        mib[2] = 0;
        mib[3] = AF_IPX;
        mib[4] = NET_RT_IFLIST;
        mib[5] = 0;
        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
                quit("route-sysctl-estimate");
	if ((buf = malloc(needed)) == NULL)
		quit("malloc");
        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
		lookforinterfaces = 0;
	cplim = buf + needed;
	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)cp;
		if (ifm->ifm_type == RTM_IFINFO) {
			bzero(&ifs, sizeof(ifs));
			ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE;
			if ((flags & IFF_UP) == 0 || no_ipxaddr)
				lookforinterfaces = 1;
			sdl = (struct sockaddr_dl *) (ifm + 1);
			sdl->sdl_data[sdl->sdl_nlen] = 0;
			no_ipxaddr = 1;
			continue;
		}
		if (ifm->ifm_type != RTM_NEWADDR)
			quit("ifinit: out of sync");
		if ((flags & IFF_UP) == 0)
			continue;
		ifam = (struct ifa_msghdr *)ifm;
		info.rti_addrs = ifam->ifam_addrs;
		rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
		if (ifaaddr == 0) {
			syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
			continue;
		}
		ifs.int_addr = *ifaaddr;
		if (ifs.int_addr.sa_family != AF_IPX)
			continue;
		no_ipxaddr = 0;
		if (ifs.int_flags & IFF_POINTOPOINT) {
			if (brdaddr == 0) {
				syslog(LOG_ERR, "%s: (get dstaddr)",
					sdl->sdl_data);
				continue;
			}
			if (brdaddr->sa_family == AF_UNSPEC) {
				lookforinterfaces = 1;
				continue;
			}
			ifs.int_dstaddr = *brdaddr;
		}
		if (ifs.int_flags & IFF_BROADCAST) {
			if (brdaddr == 0) {
				syslog(LOG_ERR, "%s: (get broadaddr)",
					sdl->sdl_data);
				continue;
			}
			ifs.int_dstaddr = *brdaddr;
		}
		if (ifs.int_flags & IFF_LOOPBACK) {
			ifs.int_dstaddr = ifs.int_addr;
		}
		/* 
		 * already known to us? 
		 * what makes a POINTOPOINT if unique is its dst addr,
		 * NOT its source address 
		 */
		if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
			if_ifwithdstaddr(&ifs.int_dstaddr)) ||
			( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
			if_ifwithaddr(&ifs.int_addr)))
			continue;
		ifp = (struct interface *)
			malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
		if (ifp == NULL) {
			syslog(LOG_ERR, "IPXrouted: out of memory\n");
			lookforinterfaces = 1;
			break;
		}
		*ifp = ifs;
		/*
		 * Count the # of directly connected networks
		 * and point to point links which aren't looped
		 * back to ourself.  This is used below to
		 * decide if we should be a routing ``supplier''.
		 */
		if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
		    if_ifwithaddr(&ifs.int_dstaddr) == 0)
			externalinterfaces++;
		/*
		 * If we have a point-to-point link, we want to act
		 * as a supplier even if it's our only interface,
		 * as that's the only way our peer on the other end
		 * can tell that the link is up.
		 */
		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
			supplier = 1;
		ifp->int_name = (char *)(ifp + 1);
		strcpy(ifp->int_name, sdl->sdl_data);

		ifp->int_metric = ifam->ifam_metric;
		ifp->int_next = ifnet;
		ifnet = ifp;
		traceinit(ifp);
		addrouteforif(ifp);
	}
	if (externalinterfaces > 1 && supplier < 0)
		supplier = 1;
	free(buf);
}
Example #7
0
/* 
 * Reads kernel interface list and makes a copy for the local use.
 */
int
initialize_interface(void)
{
	size_t needed;
	int newif = FALSE, mib[6], flags = 0;
	char *buf, *cplim, *cp;
	struct interface *ifs, *ifp;
	struct preflist *plp = NULL;
	struct sockaddr_dl *sdl;
	register struct if_msghdr *ifm;
	register struct ifa_msghdr *ifam;
	int externalinterfaces = 0;

	/* I'm afraid of stack overflow. */
	/* So work areas are malloc-ed.  */
	ifs = (struct interface *)malloc(sizeof(struct interface));
	if (ifs == NULL) {
		syslog(LOG_ERR, "work area malloc: %m");
		return -1;
	}
	mib[0] = CTL_NET;
	mib[1] = PF_ROUTE;
	mib[2] = 0;
	mib[3] = AF_INET6;
	mib[4] = NET_RT_IFLIST;
	mib[5] = 0;

	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
		free(ifs);
		syslog(LOG_ERR, "sysctl IFLIST 1 : %m");
		return -1;
	}
	if ((buf = malloc(needed)) == NULL) {
		free(ifs);
		syslog(LOG_ERR, "sysctl IFLIST malloc : %m");
		return -1;
	}
	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
		free(buf);
		free(ifs);
		syslog(LOG_ERR, "sysctl IFLIST 2 : %m");
		return -1;
	}
	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
		for (plp = ifp->if_ip6addr; plp; plp = plp->pl_next)
			plp->pl_flag = PL_DELADDR;
		for (plp = ifp->if_sladdr; plp; plp = plp->pl_next)
			plp->pl_flag = PL_DELADDR;
		for (plp = ifp->if_lladdr; plp; plp = plp->pl_next)
			plp->pl_flag = PL_DELADDR;
	}
	/* so, ifp is NULL now */

	cplim = buf + needed;
	for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
		ifm = (struct if_msghdr *)cp;
		if (ifm->ifm_type == RTM_IFINFO) {
			newif = FALSE;
			ifp = (struct interface *)NULL;
			if (ifm->ifm_addrs != RTA_IFP)
				continue;	/* sanity check */
			sdl = (struct sockaddr_dl *)(ifm + 1);
			if ((ifp = get_if_by_name(sdl)) == NULL) {
			/* Hack! */
			/* IFF_RUNNING means 'has at least one linklocal'
			 * <CAN_SEND> */
			/* IFF_JOINED  means 'joined multicast group'
			 * <CAN_RECEIVE> */
				flags = ifm->ifm_flags & ~(IFF_RUNNING | IFF_JOINED);
				if ((flags & IFF_UP) == 0) {
					ifp = NULL;
					continue;
				}
				bzero(ifs, sizeof(struct interface));
				ifp = ifs;	/* pointer copy */
				newif = TRUE;
				/* already bzeroed, so trailing 0 is not needed */
				strncpy(ifp->if_name, sdl->sdl_data, sdl->sdl_nlen);
				ifp->if_sdl = *sdl;	/* struct copy */
				ifp->if_flag = flags;
			} else {
				flags = ifm->ifm_flags;
				if ((flags & IFF_UP) == 0) {
					if (ifp->if_flag & IFF_JOINED)
						drop_multicast_group(ifp);
					ifp->if_flag = flags & ~(IFF_RUNNING | IFF_JOINED);
					/* if_freeaddresses( ifp ); */
					/* free will be done in install_address */
					ifp = NULL;
					continue;
				}
				if ((ifp->if_flag & IFF_UP) == 0) {
					/* wake up */
					/* counter reset */
					ifp->if_badpkt = ifp->if_badrte = ifp->if_updates = 0;
				}
				ifp->if_flag = (flags & ~(IFF_RUNNING | IFF_JOINED))
					| (ifp->if_flag & (IFF_RUNNING | IFF_JOINED));
				ifp->if_sdl = *sdl;	/* maybe MAC address
							 * was changed (?) */
			}

			ifp->if_metrc = ifm->ifm_data.ifi_metric;
			/* maybe index was changed */
			if_index(ifp) = ifm->ifm_index;
			ifp->if_lmtu = ifm->ifm_data.ifi_mtu;
			/* sanity check */
			if (ifp->if_lmtu <
			    (sizeof(struct rip6) + rt6_hdrlen +
			     sizeof(struct route_entry))) {
				/* rt6_hdrlen may be HUGER than DEFAULT(576) */
				ifp->if_flag &= ~IFF_UP;
				syslog(LOG_ERR, "Too small MTU");
				ifp = NULL;
				newif = FALSE;
			}
			continue;
		}		/* if(RTM_IFINFO) */
		if (ifm->ifm_type != RTM_NEWADDR) {
			free(buf);
			free(ifs);
			syslog(LOG_ERR, "sysctl illegal data");
			return -1;
		}
		if (ifp == NULL)
			continue;
		/* ifp without IFF_UP shall reach here */
		/* First message is RTM_NEWADDR (not RTM_IFINFO) shall
                   reach here */

		ifam = (struct ifa_msghdr *)ifm;
		rtinfo.rti_addrs = ifam->ifam_addrs;
		plp = (struct preflist *)malloc(sizeof(struct preflist));
		if (plp == NULL) {
			free(buf);
			free(ifs);
			syslog(LOG_ERR, "initialize_interface: malloc failed");
			return -1;
		}
		bzero((void *)plp, sizeof(struct preflist));

		if (get_address(ifam->ifam_addrs, (char *)(ifam + 1),
				(cp + ifam->ifam_msglen), plp) < 0) {
			free(plp);	/* plp = NULL; */
			continue;
		}
		if (flags & IFF_POINTOPOINT) {
			if (if_ifwithdstaddr(plp, ifp)) {
			/* address already on the interface list ( marked
			 * OLDADDR ) */
				free(plp);	/* plp = NULL; */
				continue;
			}
		} else {
			int i;

#define vdst  plp->pl_dest.s6_addr
#define vsrc1 plp->pl_pref.prf_addr.s6_addr
#define vsrc2 plp->pl_mask.s6_addr
			for (i = 0; i < sizeof(struct in6_addr); i++)
				vdst[i] = vsrc1[i] & vsrc2[i];
#undef vsrc2
#undef vsrc1
#undef vdst
			if (if_ifwithaddr(plp, ifp)) {
			/* address already on the interface list ( marked
			 * OLDADDR ) */
				free(plp);	/* plp = NULL; */
				continue;
			}
		}

		if (newif != FALSE) {
			if ((ifp = (struct interface *)malloc(sizeof(struct interface))) == NULL) {
				free(plp);
				free(buf);
				free(ifs);
				syslog(LOG_ERR, "initialize_interface: new if malloc :%m");
				return -1;
			}
			*ifp = *ifs;	/* struct copy */
			ifp->if_next = ifnet;
			ifnet = ifp;
			newif = FALSE;	/* CAUTION: this interface loop has
					 * not been finished */
			if ((ifp->if_flag & IFF_LOOPBACK) == 0)
				externalinterfaces++;
		}
		add_address(plp, ifp);	/* plp = NULL; */

		if (ifp->if_flag & IFF_LOOPBACK)
			foundloopback = 1;
	}			/* for */

	/* Unnumbered P2P check */
	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
		if (ifp->if_flag & IFF_POINTOPOINT
		    && ifp->if_flag & IFF_UP) {
			for (plp = ifp->if_ip6addr; plp; plp = plp->pl_next)
				if (plp->pl_flag != PL_DELADDR)
					if_duplicate(plp, ifp);
			/* Duplicate address will be zeroed */
			for (plp = ifp->if_sladdr; plp; plp = plp->pl_next)
				if (plp->pl_flag != PL_DELADDR)
					if_duplicate(plp, ifp);
			/* Duplicate address will be zeroed */
		}
	}

	/* Even if we have only one (external) interface, RIPng works */
	/* MODE_UNSPEC really needed ? */
	if (externalinterfaces == 0)
		rt6_opmode = MODE_QUIET;

	free(buf);
	free(ifs);
	return 0;
}