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

📄 rt_netlink.c

📁 zebra测试源代码用于 SOCKET 通信
💻 C
📖 第 1 页 / 共 3 页
字号:
  struct iovec iov = { (void*) n, n->nlmsg_len };  struct msghdr msg = {(void*) &snl, sizeof snl, &iov, 1, NULL, 0, 0};  int flags = 0;    memset (&snl, 0, sizeof snl);  snl.nl_family = AF_NETLINK;    n->nlmsg_seq = ++netlink_cmd.seq;  /* Request an acknowledgement by setting NLM_F_ACK */  n->nlmsg_flags |= NLM_F_ACK;    if (IS_ZEBRA_DEBUG_KERNEL)     zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd.name,	      lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,	      n->nlmsg_seq);  /* Send message to netlink interface. */  status = sendmsg (nl->sock, &msg, 0);  if (status < 0)    {      zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",	    strerror (errno));      return -1;    }    /*    * Change socket flags for blocking I/O.    * This ensures we wait for a reply in netlink_parse_info().   */  if((flags = fcntl(nl->sock, F_GETFL, 0)) < 0)     {      zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",               __FUNCTION__, __LINE__, strerror (errno));    }  flags &= ~O_NONBLOCK;  if(fcntl(nl->sock, F_SETFL, flags) < 0)     {      zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",               __FUNCTION__, __LINE__, strerror (errno));    }  /*    * Get reply from netlink socket.    * The reply should either be an acknowlegement or an error.   */  status = netlink_parse_info (netlink_talk_filter, nl);    /* Restore socket flags for nonblocking I/O */  flags |= O_NONBLOCK;  if(fcntl(nl->sock, F_SETFL, flags) < 0)     {      zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",               __FUNCTION__, __LINE__, strerror (errno));    }    return status;}/* Routing table change via netlink interface. */intnetlink_route (int cmd, int family, void *dest, int length, void *gate,	       int index, int zebra_flags, int table){  int ret;  int bytelen;  struct sockaddr_nl snl;  int discard;  struct   {    struct nlmsghdr n;    struct rtmsg r;    char buf[1024];  } req;  memset (&req, 0, sizeof req);  bytelen = (family == AF_INET ? 4 : 16);  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;  req.n.nlmsg_type = cmd;  req.r.rtm_family = family;  req.r.rtm_table = table;  req.r.rtm_dst_len = length;  if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)    discard = 1;  else    discard = 0;  if (cmd == RTM_NEWROUTE)     {#if 0      req.r.rtm_protocol = RTPROT_ZEBRA;#endif      req.r.rtm_scope = RT_SCOPE_UNIVERSE;      if (discard)	req.r.rtm_type = RTN_BLACKHOLE;      else	req.r.rtm_type = RTN_UNICAST;    }  if (dest)    addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);  if (! discard)    {      if (gate)	addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);      if (index > 0)	addattr32 (&req.n, sizeof req, RTA_OIF, index);    }  /* Destination netlink address. */  memset (&snl, 0, sizeof snl);  snl.nl_family = AF_NETLINK;  /* Talk to netlink socket. */  ret = netlink_talk (&req.n, &netlink);  if (ret < 0)    return -1;  return 0;}/* Routing table change via netlink interface. */intnetlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,			 int family){  int bytelen;  struct sockaddr_nl snl;  struct nexthop *nexthop = NULL;  int nexthop_num = 0;  struct nlsock *nl;  int discard;  struct   {    struct nlmsghdr n;    struct rtmsg r;    char buf[1024];  } req;  memset (&req, 0, sizeof req);  bytelen = (family == AF_INET ? 4 : 16);  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;  req.n.nlmsg_type = cmd;  req.r.rtm_family = family;  req.r.rtm_table = rib->table;  req.r.rtm_dst_len = p->prefixlen;#ifdef RTM_F_EQUALIZE  req.r.rtm_flags |= RTM_F_EQUALIZE;#endif /* RTM_F_EQUALIZE */  if (rib->flags & ZEBRA_FLAG_BLACKHOLE)    discard = 1;  else    discard = 0;  if (cmd == RTM_NEWROUTE)     {      req.r.rtm_protocol = RTPROT_ZEBRA;      req.r.rtm_scope = RT_SCOPE_UNIVERSE;      if (discard)	req.r.rtm_type = RTN_BLACKHOLE;      else	req.r.rtm_type = RTN_UNICAST;    }  addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);  /* Metric. */  addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);  if (discard)    {      if (cmd == RTM_NEWROUTE)	for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)	  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);      goto skip;    }  /* Multipath case. */  if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)    {      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)	{	  if ((cmd == RTM_NEWROUTE 	       && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))	      || (cmd == RTM_DELROUTE		  && 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)		    addattr_l (&req.n, sizeof req, RTA_GATEWAY,			       &nexthop->rgate.ipv4, bytelen);#ifdef HAVE_IPV6		  if (nexthop->rtype == NEXTHOP_TYPE_IPV6 		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX 		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)		    addattr_l (&req.n, sizeof req, RTA_GATEWAY,			       &nexthop->rgate.ipv6, bytelen);#endif /* HAVE_IPV6 */		  if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IFNAME		      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)		    addattr32 (&req.n, sizeof req, RTA_OIF,			       nexthop->rifindex);		}	      else		{		  if (nexthop->type == NEXTHOP_TYPE_IPV4 		      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)		    addattr_l (&req.n, sizeof req, RTA_GATEWAY,			       &nexthop->gate.ipv4, bytelen);#ifdef HAVE_IPV6		  if (nexthop->type == NEXTHOP_TYPE_IPV6 		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)		    addattr_l (&req.n, sizeof req, RTA_GATEWAY,			       &nexthop->gate.ipv6, bytelen);#endif /* HAVE_IPV6 */		  if (nexthop->type == NEXTHOP_TYPE_IFINDEX		      || nexthop->type == NEXTHOP_TYPE_IFNAME		      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)		    addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);		}	      if (cmd == RTM_NEWROUTE)		SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);	      nexthop_num++;	      break;	    }	}    }  else    {      char buf[1024];      struct rtattr *rta = (void *) buf;      struct rtnexthop *rtnh;      rta->rta_type = RTA_MULTIPATH;      rta->rta_len = RTA_LENGTH(0);      rtnh = RTA_DATA(rta);      nexthop_num = 0;      for (nexthop = rib->nexthop;	   nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);	   nexthop = nexthop->next)	{	  if ((cmd == RTM_NEWROUTE 	       && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))	      || (cmd == RTM_DELROUTE		  && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))	    {	      nexthop_num++;	      rtnh->rtnh_len = sizeof (*rtnh);	      rtnh->rtnh_flags = 0;	      rtnh->rtnh_hops = 0;	      rta->rta_len += rtnh->rtnh_len;	      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))		{		  if (nexthop->rtype == NEXTHOP_TYPE_IPV4		      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)		    {		      rta_addattr_l (rta, 4096, RTA_GATEWAY,				     &nexthop->rgate.ipv4, bytelen);		      rtnh->rtnh_len += sizeof (struct rtattr) + 4;		    }#ifdef HAVE_IPV6		  if (nexthop->rtype == NEXTHOP_TYPE_IPV6		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)		    rta_addattr_l (rta, 4096, RTA_GATEWAY,				   &nexthop->rgate.ipv6, bytelen);#endif /* HAVE_IPV6 */		  /* ifindex */		  if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IFNAME		      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX		      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)		    rtnh->rtnh_ifindex = nexthop->rifindex;		  else		    rtnh->rtnh_ifindex = 0;		}	      else		{		  if (nexthop->type == NEXTHOP_TYPE_IPV4		      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)		    {		      rta_addattr_l (rta, 4096, RTA_GATEWAY,				     &nexthop->gate.ipv4, bytelen);		      rtnh->rtnh_len += sizeof (struct rtattr) + 4;		    }#ifdef HAVE_IPV6		  if (nexthop->type == NEXTHOP_TYPE_IPV6		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)		    rta_addattr_l (rta, 4096, RTA_GATEWAY,				   &nexthop->gate.ipv6, bytelen);#endif /* HAVE_IPV6 */		  /* ifindex */		  if (nexthop->type == NEXTHOP_TYPE_IFINDEX		      || nexthop->type == NEXTHOP_TYPE_IFNAME		      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME		      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)		    rtnh->rtnh_ifindex = nexthop->ifindex;		  else		    rtnh->rtnh_ifindex = 0;		}	      rtnh = RTNH_NEXT(rtnh);	      if (cmd == RTM_NEWROUTE)		SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);	    }	}      if (rta->rta_len > RTA_LENGTH (0))	addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA(rta),		   RTA_PAYLOAD(rta));    }  /* 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:  /* Destination netlink address. */  memset (&snl, 0, sizeof snl);  snl.nl_family = AF_NETLINK;  if (family == AF_INET)    nl = &netlink_cmd;  else    nl = &netlink;  /* Talk to netlink socket. */  return netlink_talk (&req.n, nl);}intkernel_add_ipv4 (struct prefix *p, struct rib *rib){  return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);}intkernel_delete_ipv4 (struct prefix *p, struct rib *rib){  return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);}#ifdef HAVE_IPV6intkernel_add_ipv6 (struct prefix *p, struct rib *rib){  return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);}intkernel_delete_ipv6 (struct prefix *p, struct rib *rib){  return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);}/* Delete IPv6 route from the kernel. */intkernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,			int index, int flags, int table){  return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, dest->prefixlen,			gate, index, flags, table);}#endif /* HAVE_IPV6 *//* Interface address modification. */intnetlink_address (int cmd, int family, struct interface *ifp,		 struct connected *ifc){  int bytelen;  struct prefix *p;  struct   {    struct nlmsghdr n;    struct ifaddrmsg ifa;    char buf[1024];  } req;  p = ifc->address;  memset (&req, 0, sizeof req);  bytelen = (family == AF_INET ? 4 : 16);  req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg));  req.n.nlmsg_flags = NLM_F_REQUEST;  req.n.nlmsg_type = cmd;  req.ifa.ifa_family = family;  req.ifa.ifa_index = ifp->ifindex;  req.ifa.ifa_prefixlen = p->prefixlen;  addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);  if (family == AF_INET && cmd == RTM_NEWADDR)    {      if (if_is_broadcast (ifp) && ifc->destination)	{	  p = ifc->destination;	  addattr_l(&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix, bytelen);	}    }  if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))    SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);      if (ifc->label)    addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,	       strlen (ifc->label) + 1);  return netlink_talk (&req.n, &netlink_cmd);}intkernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc){  return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);}intkernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc){  return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);}#include "thread.h"extern struct thread_master *master;/* Kernel route reflection. */intkernel_read (struct thread *thread){  int ret;  int sock;  sock = THREAD_FD (thread);  ret = netlink_parse_info (netlink_information_fetch, &netlink);  thread_add_read (master, kernel_read, NULL, netlink.sock);  return 0;}/* Exported interface function.  This function simply calls   netlink_socket (). */voidkernel_init (){  unsigned long groups;  groups = RTMGRP_LINK|RTMGRP_IPV4_ROUTE|RTMGRP_IPV4_IFADDR;#ifdef HAVE_IPV6  groups |= RTMGRP_IPV6_ROUTE|RTMGRP_IPV6_IFADDR;#endif /* HAVE_IPV6 */  netlink_socket (&netlink, groups);  netlink_socket (&netlink_cmd, 0);  /* Register kernel socket. */  if (netlink.sock > 0)    thread_add_read (master, kernel_read, NULL, netlink.sock);}

⌨️ 快捷键说明

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