⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rt_netlink.c

📁 zebra测试源代码用于 SOCKET 通信
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Looking up routing table by netlink interface. */intnetlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h){  int len;  struct rtmsg *rtm;  struct rtattr *tb [RTA_MAX + 1];  u_char flags = 0;    char anyaddr[16] = {0};  int index;  int table;  void *dest;  void *gate;  rtm = NLMSG_DATA (h);  if (h->nlmsg_type != RTM_NEWROUTE)    return 0;  if (rtm->rtm_type != RTN_UNICAST)    return 0;  table = rtm->rtm_table;#if 0		/* we weed them out later in rib_weed_tables () */  if (table != RT_TABLE_MAIN && table != rtm_table_default)    return 0;#endif  len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));  if (len < 0)    return -1;  memset (tb, 0, sizeof tb);  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);  if (rtm->rtm_flags & RTM_F_CLONED)    return 0;  if (rtm->rtm_protocol == RTPROT_REDIRECT)    return 0;  if (rtm->rtm_protocol == RTPROT_KERNEL)    return 0;  if (rtm->rtm_src_len != 0)    return 0;  /* Route which inserted by Zebra. */  if (rtm->rtm_protocol == RTPROT_ZEBRA)    flags |= ZEBRA_FLAG_SELFROUTE;    index = 0;  dest = NULL;  gate = NULL;  if (tb[RTA_OIF])    index = *(int *) RTA_DATA (tb[RTA_OIF]);  if (tb[RTA_DST])    dest = RTA_DATA (tb[RTA_DST]);  else    dest = anyaddr;  /* Multipath treatment is needed. */  if (tb[RTA_GATEWAY])    gate = RTA_DATA (tb[RTA_GATEWAY]);  if (rtm->rtm_family == AF_INET)    {      struct prefix_ipv4 p;      p.family = AF_INET;      memcpy (&p.prefix, dest, 4);      p.prefixlen = rtm->rtm_dst_len;      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, 0, 0);    }#ifdef HAVE_IPV6  if (rtm->rtm_family == AF_INET6)    {      struct prefix_ipv6 p;      p.family = AF_INET6;      memcpy (&p.prefix, dest, 16);      p.prefixlen = rtm->rtm_dst_len;      rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);    }#endif /* HAVE_IPV6 */  return 0;}struct message rtproto_str [] = {  {RTPROT_REDIRECT, "redirect"},  {RTPROT_KERNEL,   "kernel"},  {RTPROT_BOOT,     "boot"},  {RTPROT_STATIC,   "static"},  {RTPROT_GATED,    "GateD"},  {RTPROT_RA,       "router advertisement"},  {RTPROT_MRT,      "MRT"},  {RTPROT_ZEBRA,    "Zebra"},#ifdef RTPROT_BIRD  {RTPROT_BIRD,     "BIRD"},#endif /* RTPROT_BIRD */  {0,               NULL}};/* Routing information change from the kernel. */intnetlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h){  int len;  struct rtmsg *rtm;  struct rtattr *tb [RTA_MAX + 1];    char anyaddr[16] = {0};  int index;  int table;  void *dest;  void *gate;  rtm = NLMSG_DATA (h);  if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))    {      /* If this is not route add/delete message print warning. */      zlog_warn ("Kernel message: %d\n", h->nlmsg_type);      return 0;    }  /* Connected route. */  if (IS_ZEBRA_DEBUG_KERNEL)    zlog_info ("%s %s %s proto %s",	       h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",	       rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",	       rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",	       lookup (rtproto_str, rtm->rtm_protocol));  if (rtm->rtm_type != RTN_UNICAST)    {      return 0;    }  table = rtm->rtm_table;  if (table != RT_TABLE_MAIN && table != rtm_table_default)    {      return 0;    }  len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));  if (len < 0)    return -1;  memset (tb, 0, sizeof tb);  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);  if (rtm->rtm_flags & RTM_F_CLONED)    return 0;  if (rtm->rtm_protocol == RTPROT_REDIRECT)    return 0;  if (rtm->rtm_protocol == RTPROT_KERNEL)    return 0;  if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)    return 0;  if (rtm->rtm_src_len != 0)    {      zlog_warn ("netlink_route_change(): no src len");      return 0;    }    index = 0;  dest = NULL;  gate = NULL;  if (tb[RTA_OIF])    index = *(int *) RTA_DATA (tb[RTA_OIF]);  if (tb[RTA_DST])    dest = RTA_DATA (tb[RTA_DST]);  else    dest = anyaddr;  if (tb[RTA_GATEWAY])    gate = RTA_DATA (tb[RTA_GATEWAY]);  if (rtm->rtm_family == AF_INET)    {      struct prefix_ipv4 p;      p.family = AF_INET;      memcpy (&p.prefix, dest, 4);      p.prefixlen = rtm->rtm_dst_len;      if (IS_ZEBRA_DEBUG_KERNEL)	{	  if (h->nlmsg_type == RTM_NEWROUTE)	    zlog_info ("RTM_NEWROUTE %s/%d",		       inet_ntoa (p.prefix), p.prefixlen);	  else	    zlog_info ("RTM_DELROUTE %s/%d",		       inet_ntoa (p.prefix), p.prefixlen);	}      if (h->nlmsg_type == RTM_NEWROUTE)	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);      else	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);    }#ifdef HAVE_IPV6  if (rtm->rtm_family == AF_INET6)    {      struct prefix_ipv6 p;      char buf[BUFSIZ];      p.family = AF_INET6;      memcpy (&p.prefix, dest, 16);      p.prefixlen = rtm->rtm_dst_len;      if (IS_ZEBRA_DEBUG_KERNEL)	{	  if (h->nlmsg_type == RTM_NEWROUTE)	    zlog_info ("RTM_NEWROUTE %s/%d",		       inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),		       p.prefixlen);	  else	    zlog_info ("RTM_DELROUTE %s/%d",		       inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),		       p.prefixlen);	}      if (h->nlmsg_type == RTM_NEWROUTE)	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);      else	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);    }#endif /* HAVE_IPV6 */  return 0;}intnetlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h){  int len;  struct ifinfomsg *ifi;  struct rtattr *tb [IFLA_MAX + 1];  struct interface *ifp;  char *name;  ifi = NLMSG_DATA (h);  if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))    {      /* If this is not link add/delete message so print warning. */      zlog_warn ("netlink_link_change: wrong kernel message %d\n",		 h->nlmsg_type);      return 0;    }  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));  if (len < 0)    return -1;  /* Looking up interface name. */  memset (tb, 0, sizeof tb);  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);  if (tb[IFLA_IFNAME] == NULL)    return -1;  name = (char *)RTA_DATA(tb[IFLA_IFNAME]);  /* Add interface. */  if (h->nlmsg_type == RTM_NEWLINK)    {      ifp = if_lookup_by_name (name);      if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))	{	  if (ifp == NULL)	    ifp = if_get_by_name (name);	  ifp->ifindex = ifi->ifi_index;	  ifp->flags = ifi->ifi_flags & 0x0000fffff;	  ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);	  ifp->metric = 1;	  /* If new link is added. */	  if_add_update(ifp);	}            else	{	  /* Interface status change. */	  ifp->ifindex = ifi->ifi_index;	  ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);	  ifp->metric = 1;	  if (if_is_up (ifp))	    {	      ifp->flags = ifi->ifi_flags & 0x0000fffff;	      if (! if_is_up (ifp))		if_down (ifp);	    }	  else	    {	      ifp->flags = ifi->ifi_flags & 0x0000fffff;	      if (if_is_up (ifp))		if_up (ifp);	    }	}    }  else    {      /* RTM_DELLINK. */      ifp = if_lookup_by_name (name);      if (ifp == NULL)	{	  zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",                name);	  return 0;	}            if_delete_update (ifp);    }  return 0;}intnetlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h){  switch (h->nlmsg_type)    {    case RTM_NEWROUTE:      return netlink_route_change (snl, h);      break;    case RTM_DELROUTE:      return netlink_route_change (snl, h);      break;    case RTM_NEWLINK:      return netlink_link_change (snl, h);      break;    case RTM_DELLINK:      return netlink_link_change (snl, h);      break;    case RTM_NEWADDR:      return netlink_interface_addr (snl, h);      break;    case RTM_DELADDR:      return netlink_interface_addr (snl, h);      break;    default:      zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);      break;    }  return 0;}/* Interface lookup by netlink socket. */intinterface_lookup_netlink (){  int ret;  /* Get interface information. */  ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);  if (ret < 0)    return ret;  ret = netlink_parse_info (netlink_interface, &netlink_cmd);  if (ret < 0)    return ret;  /* Get IPv4 address of the interfaces. */  ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);  if (ret < 0)    return ret;  ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);  if (ret < 0)    return ret;#ifdef HAVE_IPV6  /* Get IPv6 address of the interfaces. */  ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);  if (ret < 0)    return ret;  ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);  if (ret < 0)    return ret;#endif /* HAVE_IPV6 */  return 0;}/* Routing table read function using netlink interface.  Only called   bootstrap time. */intnetlink_route_read (){  int ret;  /* Get IPv4 routing table. */  ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);  if (ret < 0)    return ret;  ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);  if (ret < 0)    return ret;#ifdef HAVE_IPV6  /* Get IPv6 routing table. */  ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);  if (ret < 0)    return ret;  ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);  if (ret < 0)    return ret;#endif /* HAVE_IPV6 */  return 0;}/* Utility function  comes from iproute2.    Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */intaddattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen){  int len;  struct rtattr *rta;  len = RTA_LENGTH(alen);  if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)    return -1;  rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));  rta->rta_type = type;  rta->rta_len = len;  memcpy (RTA_DATA(rta), data, alen);  n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;  return 0;}intrta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen){  int len;  struct rtattr *subrta;  len = RTA_LENGTH(alen);  if (RTA_ALIGN(rta->rta_len) + len > maxlen)    return -1;  subrta = (struct rtattr*) (((char*)rta) + RTA_ALIGN (rta->rta_len));  subrta->rta_type = type;  subrta->rta_len = len;  memcpy (RTA_DATA(subrta), data, alen);  rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;  return 0;}/* Utility function comes from iproute2.    Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */intaddattr32 (struct nlmsghdr *n, int maxlen, int type, int data){  int len;  struct rtattr *rta;    len = RTA_LENGTH(4);    if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)    return -1;  rta = (struct rtattr*) (((char*)n) + NLMSG_ALIGN (n->nlmsg_len));  rta->rta_type = type;  rta->rta_len = len;  memcpy (RTA_DATA(rta), &data, 4);  n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;  return 0;}static intnetlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h){  zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);  return 0;}/* sendmsg() to netlink socket then recvmsg(). */intnetlink_talk (struct nlmsghdr *n, struct nlsock *nl){  int status;  struct sockaddr_nl snl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -