in_addr_t ipv4_network_addr(in_addr_t hostaddr, int masklen) { struct in_addr mask; masklen2ip(masklen, &mask); return hostaddr & mask.s_addr; }
/* Apply mask to IPv4 prefix (network byte order). */ void apply_mask_ipv4 (struct prefix_ipv4 *p) { struct in_addr mask; masklen2ip(p->prefixlen, &mask); p->prefix.s_addr &= mask.s_addr; }
/* Set up interface's IP address, netmask (and broadcas? ). *BSD may has ifaliasreq structure. */ int if_unset_prefix (struct interface *ifp, struct connected *ifc) { int ret; struct ifaliasreq addreq; struct sockaddr_in addr; struct sockaddr_in mask; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)ifc->address; memset (&addreq, 0, sizeof addreq); strncpy ((char *)&addreq.ifra_name, ifp->name, sizeof addreq.ifra_name); memset (&addr, 0, sizeof (struct sockaddr_in)); addr.sin_addr = p->prefix; addr.sin_family = p->family; #ifdef HAVE_SIN_LEN addr.sin_len = sizeof (struct sockaddr_in); #endif memcpy (&addreq.ifra_addr, &addr, sizeof (struct sockaddr_in)); memset (&mask, 0, sizeof (struct sockaddr_in)); masklen2ip (p->prefixlen, &mask.sin_addr); mask.sin_family = p->family; #ifdef HAVE_SIN_LEN mask.sin_len = sizeof (struct sockaddr_in); #endif memcpy (&addreq.ifra_mask, &mask, sizeof (struct sockaddr_in)); ret = if_ioctl (SIOCDIFADDR, (caddr_t) &addreq); if (ret < 0) return ret; return 0; }
/* Set up interface's address, netmask (and broadcas? ). Linux or Solaris uses ifname:number semantics to set IP address aliases. */ int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx) { int ret; struct ifreq ifreq; struct sockaddr_in addr; struct sockaddr_in broad; struct sockaddr_in mask; struct prefix_ipv4 ifaddr; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx); ifaddr = *p; strlcpy(ifreq.ifr_name, dplane_ctx_get_ifname(ctx), sizeof(ifreq.ifr_name)); addr.sin_addr = p->prefix; addr.sin_family = p->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); if (ret < 0) return ret; /* We need mask for make broadcast addr. */ masklen2ip(p->prefixlen, &mask.sin_addr); if (dplane_ctx_intf_is_broadcast(ctx)) { apply_mask_ipv4(&ifaddr); addr.sin_addr = ifaddr.prefix; broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); broad.sin_family = p->family; memcpy(&ifreq.ifr_broadaddr, &broad, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); if (ret < 0) return ret; } mask.sin_family = p->family; #ifdef SUNOS_5 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else memcpy(&ifreq.ifr_addr, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); if (ret < 0) return ret; return 0; }
in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen) { struct in_addr mask; masklen2ip(masklen, &mask); return (masklen != IPV4_MAX_PREFIXLEN - 1) ? /* normal case */ (hostaddr | ~mask.s_addr) : /* special case for /31 */ (hostaddr ^ ~mask.s_addr); }
/* Set up interface's address, netmask (and broadcast? ). Solaris uses ifname:number semantics to set IP address aliases. */ int if_set_prefix(struct interface *ifp, struct connected *ifc) { int ret; struct ifreq ifreq; struct sockaddr_in addr; struct sockaddr_in broad; struct sockaddr_in mask; struct prefix_ipv4 ifaddr; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)ifc->address; ifaddr = *p; strncpy(ifreq.ifr_name, ifp->name, IFNAMSIZ); addr.sin_addr = p->prefix; addr.sin_family = p->family; memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq); if (ret < 0) return ret; /* We need mask for make broadcast addr. */ masklen2ip(p->prefixlen, &mask.sin_addr); if (if_is_broadcast(ifp)) { apply_mask_ipv4(&ifaddr); addr.sin_addr = ifaddr.prefix; broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr); broad.sin_family = p->family; memcpy(&ifreq.ifr_broadaddr, &broad, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCSIFBRDADDR, (caddr_t)&ifreq); if (ret < 0) return ret; } mask.sin_family = p->family; #ifdef SUNOS_5 memcpy(&mask, &ifreq.ifr_addr, sizeof(mask)); #else memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); #endif /* SUNOS_5 */ ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq); return ((ret < 0) ? ret : 0); }
/* * Helper for interface-addr install, non-netlink */ static int if_set_prefix_ctx(const struct zebra_dplane_ctx *ctx) { int ret; struct ifaliasreq addreq; struct sockaddr_in addr, mask, peer; struct prefix_ipv4 *p; p = (struct prefix_ipv4 *)dplane_ctx_get_intf_addr(ctx); memset(&addreq, 0, sizeof(addreq)); strlcpy((char *)&addreq.ifra_name, dplane_ctx_get_ifname(ctx), sizeof(addreq.ifra_name)); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_addr = p->prefix; addr.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN addr.sin_len = sizeof(struct sockaddr_in); #endif memcpy(&addreq.ifra_addr, &addr, sizeof(struct sockaddr_in)); if (dplane_ctx_intf_is_connected(ctx)) { p = (struct prefix_ipv4 *)dplane_ctx_get_intf_dest(ctx); memset(&mask, 0, sizeof(struct sockaddr_in)); peer.sin_addr = p->prefix; peer.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN peer.sin_len = sizeof(struct sockaddr_in); #endif memcpy(&addreq.ifra_broadaddr, &peer, sizeof(struct sockaddr_in)); } memset(&mask, 0, sizeof(struct sockaddr_in)); masklen2ip(p->prefixlen, &mask.sin_addr); mask.sin_family = p->family; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN mask.sin_len = sizeof(struct sockaddr_in); #endif memcpy(&addreq.ifra_mask, &mask, sizeof(struct sockaddr_in)); ret = if_ioctl(SIOCAIFADDR, (caddr_t)&addreq); if (ret < 0) return ret; return 0; }
/* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv4(int cmd, struct prefix *p, struct rib *rib, int family) { struct sockaddr_in *mask = NULL; struct sockaddr_in sin_dest, sin_mask, sin_gate; struct nexthop *nexthop, *tnexthop; int recursing; int nexthop_num = 0; unsigned int ifindex = 0; int gate = 0; int error; char prefix_buf[INET_ADDRSTRLEN]; if (IS_ZEBRA_DEBUG_RIB) inet_ntop(AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); memset(&sin_dest, 0, sizeof(struct sockaddr_in)); sin_dest.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sin_dest.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ sin_dest.sin_addr = p->u.prefix4; memset(&sin_mask, 0, sizeof(struct sockaddr_in)); memset(&sin_gate, 0, sizeof(struct sockaddr_in)); sin_gate.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sin_gate.sin_len = sizeof(struct sockaddr_in); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Make gateway. */ for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; gate = 0; char gate_buf[INET_ADDRSTRLEN] = "NULL"; /* * XXX We need to refrain from kernel operations in some cases, * but this if statement seems overly cautious - what about * other than ADD and DELETE? */ if ((cmd == RTM_ADD && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) || (cmd == RTM_DELETE && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB) )) { if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_addr = nexthop->gate.ipv4; gate = 1; } if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) ifindex = nexthop->ifindex; if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { struct in_addr loopback; loopback.s_addr = htonl(INADDR_LOOPBACK); sin_gate.sin_addr = loopback; gate = 1; } if (gate && p->prefixlen == 32) mask = NULL; else { masklen2ip(p->prefixlen, &sin_mask.sin_addr); sin_mask.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN sin_mask.sin_len = sin_masklen(sin_mask.sin_addr); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ mask = &sin_mask; } error = rtm_write(cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, ifindex, rib->flags, rib->metric); if (IS_ZEBRA_DEBUG_RIB) { if (!gate) { zlog_debug ("%s: %s/%d: attention! gate not found for rib %p", __func__, prefix_buf, p->prefixlen, rib); rib_dump(p, rib); } else inet_ntop(AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); } switch (error) { /* We only flag nexthops as being in FIB if rtm_write() did its work. */ case ZEBRA_ERR_NOERROR: nexthop_num++; if (IS_ZEBRA_DEBUG_RIB) zlog_debug ("%s: %s/%d: successfully did NH %s", __func__, prefix_buf, p->prefixlen, gate_buf); if (cmd == RTM_ADD) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); break; /* The only valid case for this error is kernel's failure to install * a multipath route, which is common for FreeBSD. This should be * ignored silently, but logged as an error otherwise. */ case ZEBRA_ERR_RTEXIST: if (cmd != RTM_ADD) zlog_err ("%s: rtm_write() returned %d for command %d", __func__, error, cmd); continue; break; /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't * normal to get any other messages in ANY case. */ case ZEBRA_ERR_RTNOEXIST: case ZEBRA_ERR_RTUNREACH: default: /* This point is reachable regardless of debugging mode. */ if (!IS_ZEBRA_DEBUG_RIB) inet_ntop(AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN); zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s", __func__, prefix_buf, p->prefixlen, error, lookup(rtm_type_str, cmd)); break; } } /* if (cmd and flags make sense) */ else if (IS_ZEBRA_DEBUG_RIB) zlog_debug("%s: odd command %s for flags %d", __func__, lookup(rtm_type_str, cmd), nexthop->flags); } /* for (ALL_NEXTHOPS_RO(...)) */ /* If there was no useful nexthop, then complain. */ if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: No useful nexthops were found in RIB entry %p", __func__, rib); return 0; /*XXX*/}
u_char * ipFwTable (struct variable *v, oid objid[], size_t *objid_len, int exact, size_t *val_len, WriteMethod **write_method) { struct route_node *np; struct rib *rib; static int result; static int resarr[2]; static struct in_addr netmask; struct nexthop *nexthop; get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib); if (!np) return NULL; nexthop = rib->nexthop; if (! nexthop) return NULL; switch (v->magic) { case IPFORWARDDEST: *val_len = 4; return &np->p.u.prefix; break; case IPFORWARDMASK: masklen2ip(np->p.prefixlen, &netmask); *val_len = 4; return (u_char *)&netmask; break; case IPFORWARDPOLICY: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDNEXTHOP: *val_len = 4; return (u_char *)&nexthop->gate.ipv4; break; case IPFORWARDIFINDEX: *val_len = sizeof(int); return (u_char *)&nexthop->ifindex; break; case IPFORWARDTYPE: if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME) result = 3; else result = 4; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDPROTO: result = proto_trans(rib->type); *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDAGE: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDINFO: resarr[0] = 0; resarr[1] = 0; *val_len = 2 * sizeof(int); return (u_char *)resarr; break; case IPFORWARDNEXTHOPAS: result = -1; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDMETRIC1: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDMETRIC2: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDMETRIC3: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDMETRIC4: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; case IPFORWARDMETRIC5: result = 0; *val_len = sizeof(int); return (u_char *)&result; break; default: return NULL; break; } return NULL; }
/* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family) { struct sockaddr_in *mask = NULL; struct sockaddr_in sin_dest, sin_mask, sin_gate; struct nexthop *nexthop; int nexthop_num = 0; unsigned int ifindex = 0; int gate = 0; int error; memset (&sin_dest, 0, sizeof (struct sockaddr_in)); sin_dest.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_dest.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_dest.sin_addr = p->u.prefix4; memset (&sin_mask, 0, sizeof (struct sockaddr_in)); memset (&sin_gate, 0, sizeof (struct sockaddr_in)); sin_gate.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_gate.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ /* Make gateway. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { gate = 0; if ((cmd == RTM_ADD && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) || (cmd == RTM_DELETE #if 0 && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB) #endif )) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) { if (nexthop->rtype == NEXTHOP_TYPE_IPV4 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_addr = nexthop->rgate.ipv4; gate = 1; } if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX || nexthop->rtype == NEXTHOP_TYPE_IFNAME || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) ifindex = nexthop->rifindex; } else { if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_addr = nexthop->gate.ipv4; gate = 1; } if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) ifindex = nexthop->ifindex; if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) { struct in_addr loopback; loopback.s_addr = htonl (INADDR_LOOPBACK); sin_gate.sin_addr = loopback; gate = 1; } } if (cmd == RTM_ADD) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); if (gate && p->prefixlen == 32) mask = NULL; else { masklen2ip (p->prefixlen, &sin_mask.sin_addr); sin_mask.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_mask.sin_len = sin_masklen (sin_mask.sin_addr); #endif /* HAVE_SIN_LEN */ mask = &sin_mask; } } error = rtm_write (cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, ifindex, rib->flags, rib->metric); #if 0 if (error) { zlog_info ("kernel_rtm_ipv4(): nexthop %d add error=%d.", nexthop_num, error); } #endif nexthop_num++; } /* If there is no useful nexthop then return. */ if (nexthop_num == 0) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("kernel_rtm_ipv4(): No useful nexthop."); return 0; } return 0; /*XXX*/ }
/* Interface to ioctl route message. */ int kernel_add_route (struct prefix_ipv4 *dest, struct in_addr *gate, int index, int flags) { int ret; int sock; struct rtentry rtentry; struct sockaddr_in sin_dest, sin_mask, sin_gate; memset (&rtentry, 0, sizeof (struct rtentry)); /* Make destination. */ memset (&sin_dest, 0, sizeof (struct sockaddr_in)); sin_dest.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_dest.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_dest.sin_addr = dest->prefix; /* Make gateway. */ if (gate) { memset (&sin_gate, 0, sizeof (struct sockaddr_in)); sin_gate.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_gate.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_gate.sin_addr = *gate; } memset (&sin_mask, 0, sizeof (struct sockaddr_in)); sin_mask.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_gate.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ masklen2ip (dest->prefixlen, &sin_mask.sin_addr); /* Set destination address, mask and gateway.*/ memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in)); if (gate) memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in)); #ifndef SUNOS_5 memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in)); #endif /* SUNOS_5 */ /* Routing entry flag set. */ if (dest->prefixlen == 32) rtentry.rt_flags |= RTF_HOST; if (gate && gate->s_addr != INADDR_ANY) rtentry.rt_flags |= RTF_GATEWAY; rtentry.rt_flags |= RTF_UP; /* Additional flags */ rtentry.rt_flags |= flags; /* For tagging route. */ /* rtentry.rt_flags |= RTF_DYNAMIC; */ /* Open socket for ioctl. */ sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock < 0) { zlog_warn ("can't make socket\n"); return -1; } /* Send message by ioctl(). */ ret = ioctl (sock, SIOCADDRT, &rtentry); if (ret < 0) { switch (errno) { case EEXIST: close (sock); return ZEBRA_ERR_RTEXIST; break; case ENETUNREACH: close (sock); return ZEBRA_ERR_RTUNREACH; break; case EPERM: close (sock); return ZEBRA_ERR_EPERM; break; } close (sock); zlog_warn ("write : %s (%d)", strerror (errno), errno); return 1; } close (sock); return ret; }
/* Interface to ioctl route message. */ int kernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family) { int ret; int sock; struct rtentry rtentry; struct sockaddr_in sin_dest, sin_mask, sin_gate; struct nexthop *nexthop; int nexthop_num = 0; struct interface *ifp; memset (&rtentry, 0, sizeof (struct rtentry)); /* Make destination. */ memset (&sin_dest, 0, sizeof (struct sockaddr_in)); sin_dest.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_dest.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_dest.sin_addr = p->u.prefix4; if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE)) { SET_FLAG (rtentry.rt_flags, RTF_REJECT); if (cmd == SIOCADDRT) for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); goto skip; } memset (&sin_gate, 0, sizeof (struct sockaddr_in)); /* Make gateway. */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { if ((cmd == SIOCADDRT && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE)) || (cmd == SIOCDELRT && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB))) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) { if (nexthop->rtype == NEXTHOP_TYPE_IPV4 || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_gate.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_gate.sin_addr = nexthop->rgate.ipv4; rtentry.rt_flags |= RTF_GATEWAY; } if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX || nexthop->rtype == NEXTHOP_TYPE_IFNAME) { ifp = if_lookup_by_index (nexthop->rifindex); if (ifp) rtentry.rt_dev = ifp->name; else return -1; } } else { if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_gate.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ sin_gate.sin_addr = nexthop->gate.ipv4; rtentry.rt_flags |= RTF_GATEWAY; } if (nexthop->type == NEXTHOP_TYPE_IFINDEX || nexthop->type == NEXTHOP_TYPE_IFNAME) { ifp = if_lookup_by_index (nexthop->ifindex); if (ifp) rtentry.rt_dev = ifp->name; else return -1; } } if (cmd == SIOCADDRT) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); nexthop_num++; break; } } /* If there is no useful nexthop then return. */ if (nexthop_num == 0) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_info ("netlink_route_multipath(): No useful nexthop."); return 0; } skip: memset (&sin_mask, 0, sizeof (struct sockaddr_in)); sin_mask.sin_family = AF_INET; #ifdef HAVE_SIN_LEN sin_mask.sin_len = sizeof (struct sockaddr_in); #endif /* HAVE_SIN_LEN */ masklen2ip (p->prefixlen, &sin_mask.sin_addr); /* Set destination address, mask and gateway.*/ memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in)); if (rtentry.rt_flags & RTF_GATEWAY) memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in)); #ifndef SUNOS_5 memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in)); #endif /* SUNOS_5 */ /* Metric. It seems metric minus one value is installed... */ rtentry.rt_metric = rib->metric; /* Routing entry flag set. */ if (p->prefixlen == 32) rtentry.rt_flags |= RTF_HOST; rtentry.rt_flags |= RTF_UP; /* Additional flags */ /* rtentry.rt_flags |= flags; */ /* For tagging route. */ /* rtentry.rt_flags |= RTF_DYNAMIC; */ /* Open socket for ioctl. */ sock = socket (AF_INET, SOCK_DGRAM, 0); if (sock < 0) { zlog_warn ("can't make socket\n"); return -1; } /* Send message by ioctl(). */ ret = ioctl (sock, cmd, &rtentry); if (ret < 0) { switch (errno) { case EEXIST: close (sock); return ZEBRA_ERR_RTEXIST; break; case ENETUNREACH: close (sock); return ZEBRA_ERR_RTUNREACH; break; case EPERM: close (sock); return ZEBRA_ERR_EPERM; break; } close (sock); zlog_warn ("write : %s (%d)", strerror (errno), errno); return ret; } close (sock); return ret; }
void rt_policy_for_logic_restore_dbtable(void) { s32 i = 0; u32 count = 0; s32 sys_ret = 0; s32 sequence = 0; u32 policyid = 0; s8 *src = NULL; s8 *dest = NULL; s8 *iifname = NULL; s32 protocol; s32 minsrcport, maxsrcport, mindstport, maxdstport; s32 flag = 0; s32 tos = 0; s8 sql_select[512] = {0}; s32 iifindex; s32 sys_error_code = 0; sqlite3_res res = NULL; rtp_logicplcy_s add; struct prefix_ipv4 prefix_src; struct prefix_ipv4 prefix_dest; struct in_addr srcmask; struct in_addr dstmask; void *buffer = NULL; /*打开数据库连接*/ if (NULL == db) { db = sqlite3_open_ex(1, DATABASE_RT_POLICY_PATH); if (NULL == db) { return; } } /*查询策略个数*/ sprintf(sql_select, "select count(*) as count from tb_logic_policy;"); if ( SQLITE_OK != sqlite3_exec_query_ex(db, sql_select, &res) ) { goto lable_ret; } sqlite3_get_u32_ex(res, 0, "count", &count); sqlite3_res_free_ex(res); res = NULL; if(0 == count) { goto lable_ret; } /*按sequence排序*/ sprintf(sql_select, "select * from tb_logic_policy order by sequence;"); if ( SQLITE_OK != sqlite3_exec_query_ex(db, sql_select, &res) ) { goto lable_ret; } for (i = 0; i <(s32) count; i++) { sqlite3_get_u32_ex(res, i, "policy_id", &policyid); sqlite3_get_str_ex(res, i, "src", &src); sqlite3_get_str_ex(res, i, "dest", &dest); sqlite3_get_str_ex(res, i, "iifname", &iifname); sqlite3_get_s32_ex(res, i, "tos", &tos); sqlite3_get_s32_ex(res, i, "protocol", &protocol); sqlite3_get_s32_ex(res, i, "minsrcport", &minsrcport); sqlite3_get_s32_ex(res, i, "maxsrcport", &maxsrcport); sqlite3_get_s32_ex(res, i, "mindstport", &mindstport); sqlite3_get_s32_ex(res, i, "maxdstport", &maxdstport); sqlite3_get_s32_ex(res, i, "flag", &flag); /*将公网地址由点分十进制转换为网络二进制数*/ if (0 == str2prefix_ipv4(src, &prefix_src)) { goto lable_ret; } if (0 == str2prefix_ipv4(dest, &prefix_dest)) { goto lable_ret; } masklen2ip ((s32)prefix_src.prefixlen, &srcmask); prefix_src.prefix.s_addr &= srcmask.s_addr; masklen2ip ((s32)prefix_dest.prefixlen, &dstmask); prefix_dest.prefix.s_addr &= dstmask.s_addr; /*将接口名转换成接口索引*/ if ((!strcmp("any", iifname))||(!strcmp("Any", iifname))) { iifindex = 0; } else { if (0 != if_get_index_by_name(iifname, &iifindex)) { goto lable_ret; } } /*填充要向数据面发送的数据*/ add.id = policyid; add.src = prefix_src.prefix.s_addr; add.srcmask = srcmask.s_addr; add.dst = prefix_dest.prefix.s_addr; add.dstmask = dstmask.s_addr; add.iifindex = iifindex; add.tos = (u8)tos; add.protocol = (u8)protocol; add.srcminportnum = (u16)minsrcport; add.srcmaxportnum = (u16)maxsrcport; add.dstminportnum = (u16)mindstport; add.dstmaxportnum = (u16)maxdstport; add.flag = (u16)flag; buffer = malloc(sizeof(s32) + sizeof(rtp_logicplcy_s)); if(NULL == buffer) { goto lable_ret; } *(s32 *)buffer = sequence; memcpy(buffer + sizeof(s32), &add, sizeof(rtp_logicplcy_s)); sys_ret = conplat_syscall(MODULEID_RT_POLICY, RTP_LOGICPLCY_SYSCALL_ADD_OR_MODIFY, buffer, sizeof(s32) + sizeof(rtp_logicplcy_s), (s32*)&sys_error_code); /* 如果系统调用不成功,返回系统错误 */ if((0 != sys_error_code && 1 != sys_error_code) || 0 != sys_ret) { goto lable_ret; } cpuproxy_list_item_addmod(sequence, &add); } lable_ret: if (NULL != buffer) { free (buffer); buffer = NULL; } /*释放结果集*/ if (NULL != res) { sqlite3_res_free_ex(res); res = NULL; } return; }
/******************************************************************************* 函数名称 : rt_policy_restore_dbtable 函数功能 : 策略路由配置恢复 输入参数 : 无 输出参数 : 无 返回结果 : 无 -------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者 : wangchao 修改目的 :将策略路由配置恢复移至策略路由deamon进程 修改日期 : 2010年12月30日 *******************************************************************************/ void rt_policy_restore_dbtable(s32 listflag, u32 *dcdm_needed) { s32 i = 0, j = 0; u32 count = 0; s32 sys_ret = 0; s32 sequence = 0; u32 policyid = 0; s8 *src = NULL; s8 *dest = NULL; s8 *iifname = NULL; s8 *oifname; s8 *nexthop; s8 *weight; s32 nexthop_count, protocol, netappid; u32 flag = 0; s32 minsrcport, maxsrcport, mindstport, maxdstport; s8 *tos = NULL; s8 sql_select[512] = {0}; s8 tb_name[32] = {0}; s32 iifindex; s32 sys_error_code = 0; sqlite3_res res = NULL; rt_policy_s add; struct prefix_ipv4 prefix_src = {0}; struct prefix_ipv4 prefix_dest = {0}; struct in_addr nexthop_addr[RT_POLICY_MAX_NEXTHOP]; struct in_addr srcmask = {0}; struct in_addr dstmask = {0}; u32 srcgroup = 0; u32 destgroup = 0; void *buffer = NULL; s8 oifname_str[RT_POLICY_MAX_NEXTHOP][20]; s8 nexthop_str[RT_POLICY_MAX_NEXTHOP][100]; s8 weight_str[RT_POLICY_MAX_NEXTHOP][10]; s8 *str_point[3], *line_point[3]; s32 oifindex[RT_POLICY_MAX_NEXTHOP]; s32 weightvalue[RT_POLICY_MAX_NEXTHOP]; switch (listflag) { case RT_POLICY_BEFORE_ROUTE: strcpy(tb_name, "tb_rt_policy_pre"); break; case RT_POLICY_AFTER_ROUTE: strcpy(tb_name, "tb_rt_policy_aft"); break; case RT_POLICY_LOCAL_ROUTE: strcpy(tb_name, "tb_rt_policy_loc"); break; case RT_POLICY_PRE_LOCAL_ROUTE: strcpy(tb_name, "tb_rt_policy_pre_loc"); break; } /*打开数据库连接*/ if (NULL == db) { db = sqlite3_open_ex(2, DATABASE_RT_POLICY_PATH, "/config/db/netaddr_cfg.db"); if (NULL == db) { return; } } /*查询策略个数*/ sprintf(sql_select, "select count(*) as count from %s;", tb_name); sys_error_code = sqlite3_exec_query_ex(db, sql_select, &res); if ( SQLITE_OK != sys_error_code ) { goto lable_ret; } sqlite3_get_u32_ex(res, 0, "count", &count); sqlite3_res_free_ex(res); res = NULL; if(0 == count) { goto lable_ret; } memset(sql_select, 0, 512); /*按sequence排序*/ sprintf(sql_select, "select * from %s order by sequence;", tb_name); sys_error_code = sqlite3_exec_query_ex(db, sql_select, &res); if ( SQLITE_OK != sys_error_code ) { goto lable_ret; } buffer = calloc(1, sizeof(s32) * 2 + sizeof(rt_policy_s)); if(NULL == buffer) { goto lable_ret; } /*赋值*/ for (i = 0; i <(s32) count; i++) { sqlite3_get_u32_ex(res, i, "policy_id", &policyid); sqlite3_get_str_ex(res, i, "src", &src); sqlite3_get_str_ex(res, i, "dest", &dest); sqlite3_get_str_ex(res, i, "iifname", &iifname); sqlite3_get_str_ex(res, i, "oifname", &oifname); sqlite3_get_str_ex(res, i, "nexthop", &nexthop); sqlite3_get_str_ex(res, i, "weight", &weight); sqlite3_get_str_ex(res, i, "tos", &tos); sqlite3_get_s32_ex(res, i, "nexthopcount", &nexthop_count); sqlite3_get_s32_ex(res, i, "netappid", &netappid); sqlite3_get_s32_ex(res, i, "protocol", &protocol); sqlite3_get_s32_ex(res, i, "minsrcport", &minsrcport); sqlite3_get_s32_ex(res, i, "maxsrcport", &maxsrcport); sqlite3_get_s32_ex(res, i, "mindstport", &mindstport); sqlite3_get_s32_ex(res, i, "maxdstport", &maxdstport); sqlite3_get_u32_ex(res, i, "flag", &flag); str_point[0] = oifname; str_point[1] = weight; str_point[2] = nexthop; /*解析下一跳信息*/ for(j = 0; j < nexthop_count; j++) { if(j != (nexthop_count - 1)) { line_point[0] = static_strchr(str_point[0],';'); static_strncpy(oifname_str[j], str_point[0], line_point[0] - str_point[0]); str_point[0] = line_point[0] + 1; line_point[1] = static_strchr(str_point[1],';'); static_strncpy(weight_str[j], str_point[1], line_point[1] - str_point[1]); str_point[1] = line_point[1] + 1; line_point[2] = static_strchr(str_point[2],';'); static_strncpy(nexthop_str[j], str_point[2], line_point[2] - str_point[2]); str_point[2] = line_point[2] + 1; } else { line_point[0] = static_strchr(str_point[0],'\0'); static_strncpy(oifname_str[j], str_point[0], line_point[0] - str_point[0]); line_point[1] = static_strchr(str_point[1],'\0'); static_strncpy(weight_str[j], str_point[1], line_point[1] - str_point[1]); line_point[2] = static_strchr(str_point[2],'\0'); static_strncpy(nexthop_str[j], str_point[2], line_point[2] - str_point[2]); } } for(j = 0; j < nexthop_count; j++) { sys_error_code = if_get_index_by_name(oifname_str[j], &oifindex[j]); if (sys_error_code != ERROR_SUCCESS) { goto lable_ret; } weightvalue[j] = atoi(weight_str[j]); inet_aton (nexthop_str[j], &nexthop_addr[j]); } for(; j < RT_POLICY_MAX_NEXTHOP; j++) { oifindex[j] = 0; nexthop_addr[j].s_addr = 0; weightvalue[j] = 0; } /*将公网地址由点分十进制转换为网络二进制数*/ if(flag & RT_POLICY_SRC_NETADDR_GROUP) { if (0 != netaddr_group_get_id_by_name(db, "",src, &srcgroup)) { flag &= (~RT_POLICY_SRC_NETADDR_GROUP); prefix_src.prefix.s_addr = 0; } else { prefix_src.prefix.s_addr = srcgroup; } srcmask.s_addr = 0; } else { sys_error_code = str2prefix_ipv4(src, &prefix_src); if (sys_error_code <= 0) { goto lable_ret; } masklen2ip ((s32)prefix_src.prefixlen, &srcmask); prefix_src.prefix.s_addr &= srcmask.s_addr; } if(flag & RT_POLICY_DST_NETADDR_GROUP) { if (0 != netaddr_group_get_id_by_name(db, "",dest, &destgroup)) { flag &= (~RT_POLICY_DST_NETADDR_GROUP); prefix_dest.prefix.s_addr = 0; } else { prefix_dest.prefix.s_addr = destgroup; } dstmask.s_addr = 0; } else { sys_error_code = str2prefix_ipv4(dest, &prefix_dest); if (sys_error_code <= 0) { goto lable_ret; } masklen2ip ((s32)prefix_dest.prefixlen, &dstmask); prefix_dest.prefix.s_addr &= dstmask.s_addr; } /*将接口名转换成接口索引*/ if (!strcmp("any", iifname)) { iifindex = 0; } else { sys_error_code = if_get_index_by_name(iifname, &iifindex); if (sys_error_code != 0) { goto lable_ret; } } /*填充要向数据面发送的数据*/ add.id = policyid; add.src = prefix_src.prefix.s_addr; add.srcmask = srcmask.s_addr; add.dst = prefix_dest.prefix.s_addr; add.dstmask = dstmask.s_addr; add.iifindex = iifindex; add.nexthopcount = (u8)nexthop_count; for(j = 0; j < RT_POLICY_MAX_NEXTHOP; j++) { add.oifindex[j] = oifindex[j]; add.nexthop[j] = nexthop_addr[j].s_addr; add.weight[j] = (u8)weightvalue[j]; add.nhflag[j] = 0; } add.tos = (u8)atoi(tos); add.netappid = (u32)netappid; add.protocol = (u8)protocol; add.srcminportnum = (u16)minsrcport; add.srcmaxportnum = (u16)maxsrcport; add.dstminportnum = (u16)mindstport; add.dstmaxportnum = (u16)maxdstport; add.flag = flag; memcpy(buffer, &listflag, sizeof(s32)); memcpy(buffer + sizeof(s32), &sequence, sizeof(s32)); memcpy(buffer + sizeof(s32) * 2, &add, sizeof(rt_policy_s)); sys_ret = conplat_syscall(MODULEID_RT_POLICY, RT_POLICY_SYSCALL_ADD_OR_MODIFY, buffer, 2 * sizeof(s32) + sizeof(rt_policy_s), (s32*)&sys_error_code); /* 如果系统调用不成功,返回系统错误 */ if((0 != sys_error_code && 1 != sys_error_code) || 0 != sys_ret) { goto lable_ret; } if ( (0 != netappid) && (0 == *dcdm_needed) ) { *dcdm_needed = 1; } if(RT_POLICY_BEFORE_ROUTE == listflag) { /* ignore the return value here */ rtpolicy_list_item_addmod(sequence, &add); neighindex_list_item_add(&add); } } lable_ret: if (NULL != buffer) { free (buffer); buffer = NULL; } /*释放结果集*/ if (NULL != res) { sqlite3_res_free_ex(res); res = NULL; } return; }