int inet_setip_bcast(inet_prefix *ip, int family) { if(family==AF_INET) { u_int data[MAX_IP_INT]={0, 0, 0, 0}; data[0]=INADDR_BROADCAST; inet_setip(ip, data, family); } else if(family==AF_INET6) { u_int data[MAX_IP_INT]=IPV6_ADDR_BROADCAST; inet_setip(ip, data, family); } else fatal(ERROR_MSG "family not supported", ERROR_POS); return 0; }
int inet_setip_anyaddr(inet_prefix *ip, int family) { if(family==AF_INET) { u_int data[MAX_IP_INT]={0, 0, 0, 0}; data[0]=INADDR_ANY; inet_setip(ip, data, family); } else if(family==AF_INET6) { struct in6_addr ipv6=IN6ADDR_ANY_INIT; inet_setip(ip, (u_int *)(&ipv6), family); } else fatal(ERROR_MSG "family not supported", ERROR_POS); return 0; }
int inet_setip_loopback(inet_prefix *ip, int family) { if(family==AF_INET) { u_int data[MAX_IP_INT]={0, 0, 0, 0}; data[0]=LOOPBACK_IP; inet_setip(ip, data, family); inet_htonl(ip->data, ip->family); } else if(family==AF_INET6) { u_int data[MAX_IP_INT]=LOOPBACK_IPV6; inet_setip(ip, data, family); } else fatal(ERROR_MSG "family not supported", ERROR_POS); return 0; }
/* * get_dev_ip: fetches the ip currently assigned to the interface named `dev' * and stores it to `ip'. * On success 0 is returned, -1 otherwise. */ int get_dev_ip(inet_prefix *ip, int family, char *dev) { int s=-1; int ret=0; setzero(ip, sizeof(inet_prefix)); if((s=new_socket(family)) < 0) { error("Error while setting \"%s\" ip: Cannot open socket", dev); return -1; } if(family == AF_INET) { struct ifreq req; strncpy(req.ifr_name, dev, IFNAMSIZ); req.ifr_addr.sa_family = family; if(ioctl(s, SIOCGIFADDR, &req)) ERROR_FINISH(ret, -1, finish); sockaddr_to_inet(&req.ifr_addr, ip, 0); } else if(family == AF_INET6) { struct in6_ifreq req6; /* * XXX: NOT TESTED */ req6.ifr6_ifindex=ll_name_to_index(dev); req6.ifr6_prefixlen=0; if(ioctl(s, SIOCGIFADDR, &req6)) ERROR_FINISH(ret, -1, finish); inet_setip(ip, (u_int *)&req6.ifr6_addr, family); } finish: if(s != -1) close(s); return ret; }
/* * random_ip * * It generates a new random ip. * If `ipstart' is not NULL the new ip is restricted in the `final_gid' of * `final_level', so it'll be taken inside this range: * A=ipstart + (MAXGROUPNODE^( final_level + 1)) * final_gid; * B=ipstart + (MAXGROUPNODE^( final_level + 1)) * (final_gid + 1); * A <= x <= B * If `ipstart' is NULL a completely random ip is generated. * `total_levels' is the maximum number of levels. * `ext_map' is an external map. * If `only_free_gnode' is not 0, only the available and empty gnode are chosen. * In this case -1 may be returned if there aren't any free gnode to choose. * The new ip is stored in `new_ip' and on success 0 is returned. */ int random_ip(inet_prefix * ipstart, int final_level, int final_gid, int total_levels, map_gnode ** ext_map, int only_free_gnode, inet_prefix * new_ip, int my_family) { int i, e, x, level, levels; int gid[total_levels]; quadro_group qg; setzero(new_ip, sizeof(inet_prefix)); if (!ipstart || final_level == total_levels) { u_int idata[MAX_IP_INT] = { 0, 0, 0, 0 }; for (;;) { /* * Let's choose a completely random ip. */ levels = total_levels; if (my_family == AF_INET) idata[0] = rand(); else { idata[0] = rand(); idata[1] = rand(); idata[2] = rand(); idata[3] = rand(); } inet_setip(new_ip, idata, my_family); if (!inet_validate_ip(*new_ip)) break; } return 0; } /* * We can choose only a random ip which is inside the final_gid. * `final_gid' is a gnode of the `final_level' level. * `final_level' has its `ipstart'; with it we determine * its higher levels. * The work is done in this way: * - ipstart is splitted in gnode_ids and they are placed in qg.gid. * - The final_level gid is set to `final_gid'. * - The gids of levels lower than `final_level' are chosen * randomly. * - The gids of levels higher than `final_level' are set to the * gids of qg.gid[x >= final_level]. * - The ipstart is recomposed from the gids. */ levels = final_level; iptoquadg(*ipstart, ext_map, &qg, QUADG_GID); gid[levels] = final_gid; for (i = final_level + 1; i < total_levels; i++) gid[i] = qg.gid[i]; /* Change the gids if some of them point to full gnodes */ free_gids(&qg, final_level + 1, ext_map, 0); /* * Now we choose random gids for each level so we'll have a random ip * with gidtoipstart(); */ for (level = levels - 1; level >= 0; level--) { gid[level] = rand_range(0, MAXGROUPNODE - 1); if (level && only_free_gnode) { /* * We have to be sure that we're not picking a gnode * already used in the ext_map. Generally when we hook * we have loaded the old ext_map, so skipping the * taken gnodes we increase the possibility to create a * brand new, and not already used, gnode. */ if (!(ext_map[_EL(level)][gid[level]].flags & GMAP_VOID)) { /* Take a random position and loop trough the * map */ i = rand_range(0, MAXGROUPNODE - 1); for (x = 0, e = i; e < MAXGROUPNODE; e++) { if (is_group_invalid(gid, e, level, my_family)) continue; if (ext_map[_EL(level)][e].flags & GMAP_VOID) { gid[level] = e; x = 1; break; } } if (!x) { for (x = 0; i >= 0; i--) { if (is_group_invalid(gid, i, level, my_family)) continue; if (ext_map[_EL(level)][i].flags & GMAP_VOID) { gid[level] = i; x = 1; break; } } } if (!x) /* not a single free gnode was found */ return -1; } } } /* * Ok, we've set the gids of each level so we recompose them in the * new_ip. */ gidtoipstart(gid, total_levels, total_levels, my_family, new_ip); return 0; }
/* * route_get_gw: if the route stored in `who' and `n' is matched by the * `filter', it stores the gateway address of that route in `arg', which * is a pointer to an inet_prefix struct. The address is stored in host order. * The dev name of the route is appended at `arg'+sizeof(inet_prefix). * Only the non-deleted routes are considered. */ int route_get_gw(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr *tb[RTA_MAX + 1]; inet_prefix dst; inet_prefix via; int host_len = -1; if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE) return 0; if (filter.flushb && n->nlmsg_type != RTM_NEWROUTE) return 0; len -= NLMSG_LENGTH(sizeof(*r)); if (len < 0) return -1; if (r->rtm_family == AF_INET6) host_len = 128; else if (r->rtm_family == AF_INET) host_len = 32; else if (r->rtm_family == AF_DECnet) host_len = 16; else if (r->rtm_family == AF_IPX) host_len = 80; if (r->rtm_family == AF_INET6) { if (filter.tb) { if (filter.tb < 0) { if (!(r->rtm_flags & RTM_F_CLONED)) return 0; } else { if (r->rtm_flags & RTM_F_CLONED) return 0; if (filter.tb == RT_TABLE_LOCAL) { if (r->rtm_type != RTN_LOCAL) return 0; } else if (filter.tb == RT_TABLE_MAIN) { if (r->rtm_type == RTN_LOCAL) return 0; } else { return 0; } } } } else { if (filter.tb > 0 && filter.tb != r->rtm_table) return 0; } if ((filter.protocol ^ r->rtm_protocol) & filter.protocolmask) return 0; if ((filter.scope ^ r->rtm_scope) & filter.scopemask) return 0; if ((filter.type ^ r->rtm_type) & filter.typemask) return 0; if ((filter.tos ^ r->rtm_tos) & filter.tosmask) return 0; if (filter.rdst.family && (r->rtm_family != filter.rdst.family || filter.rdst.bits > r->rtm_dst_len)) return 0; if (filter.mdst.family && (r->rtm_family != filter.mdst.family || (filter.mdst.bits < r->rtm_dst_len))) return 0; if (filter.rsrc.family && (r->rtm_family != filter.rsrc.family || filter.rsrc.bits > r->rtm_src_len)) return 0; if (filter.msrc.family && (r->rtm_family != filter.msrc.family || (filter.msrc.bits < r->rtm_src_len))) return 0; if (filter.rvia.family && r->rtm_family != filter.rvia.family) return 0; if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family) return 0; parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); setzero(&dst, sizeof(dst)); dst.family = r->rtm_family; if (tb[RTA_DST]) { memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len + 7) / 8); } if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bits)) return 0; if (filter.mdst.family && inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len)) return 0; if (n->nlmsg_type == RTM_DELROUTE) return 0; /* * ... and finally if all the tests passed, copy the gateway address */ if (tb[RTA_GATEWAY]) { memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len / 8); via.family = r->rtm_family; inet_setip(arg, (u_int *) & via.data, via.family); } else if (tb[RTA_MULTIPATH]) { struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); for (;;) { if (len < sizeof(*nh)) break; if (nh->rtnh_len > len) break; if (r->rtm_flags & RTM_F_CLONED && r->rtm_type == RTN_MULTICAST) goto skip_nexthop; if (nh->rtnh_len > sizeof(*nh)) { parse_rtattr(tb, RTA_MAX, RTNH_DATA(nh), nh->rtnh_len - sizeof(*nh)); if (tb[RTA_GATEWAY]) { memcpy(&via.data, RTA_DATA(tb[RTA_GATEWAY]), host_len / 8); via.family = r->rtm_family; inet_setip(arg, (u_int *) & via.data, via.family); /* Copy the interface name */ strncpy((char *) arg + sizeof(inet_prefix), ll_index_to_name(nh->rtnh_ifindex), IFNAMSIZ); break; } } skip_nexthop: len -= NLMSG_ALIGN(nh->rtnh_len); nh = RTNH_NEXT(nh); } } /* Copy the interface name */ if (tb[RTA_OIF] && filter.oifmask != -1) strncpy((char *) arg + sizeof(inet_prefix), ll_index_to_name(*(int *) RTA_DATA(tb[RTA_OIF])), IFNAMSIZ); return 0; }