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

📄 kernel_routes.c

📁 wifi 无线网络路由协议OLSR linux下C代码
💻 C
字号:
/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2004, Andreas T鴑nesen(andreto@olsr.org) * Copyright (c) 2007, Sven-Ola for the policy routing stuff * All rights reserved. * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met: * * * Redistributions of source code must retain the above copyright  *   notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright  *   notice, this list of conditions and the following disclaimer in  *   the documentation and/or other materials provided with the  *   distribution. * * Neither the name of olsr.org, olsrd nor the names of its  *   contributors may be used to endorse or promote products derived  *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: kernel_routes.c,v 1.29 2007/10/13 12:31:04 bernd67 Exp $ */#include "kernel_routes.h"#include "ipc_frontend.h"#if !LINUX_POLICY_ROUTING#include "log.h"static int delete_all_inet_gws(void);#else /* !LINUX_POLICY_ROUTING */#include <assert.h>#include <linux/types.h>#include <linux/rtnetlink.h>struct olsr_rtreq{	struct nlmsghdr		n;	struct rtmsg		r;	char			buf[512];};static void olsr_netlink_addreq(struct olsr_rtreq *req, int type, void *data, int len){	struct rtattr *rta = (struct rtattr*)(((char*)req) + NLMSG_ALIGN(req->n.nlmsg_len));	req->n.nlmsg_len = NLMSG_ALIGN(req->n.nlmsg_len) + RTA_LENGTH(len);	assert(req->n.nlmsg_len < sizeof(struct olsr_rtreq));	rta->rta_type = type;	rta->rta_len = RTA_LENGTH(len);	memcpy(RTA_DATA(rta), data, len);}static int olsr_netlink_route(struct rt_entry *rt, olsr_u8_t family, olsr_u8_t rttable, __u16 cmd){	int ret = 0;	struct olsr_rtreq req;	struct iovec iov;	struct sockaddr_nl nladdr;	struct msghdr msg =	{		&nladdr,		sizeof(nladdr),		&iov,		1,		NULL,		0,		0	};	olsr_u32_t metric = 1;	struct rt_nexthop* nexthop = (RTM_NEWROUTE == cmd) ?		&rt->rt_best->rtp_nexthop : &rt->rt_nexthop;	memset(&req, 0, sizeof(req));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;	req.n.nlmsg_type = cmd;	req.r.rtm_family = family;	req.r.rtm_table = rttable;	req.r.rtm_protocol = RTPROT_BOOT;	req.r.rtm_scope = RT_SCOPE_LINK;	req.r.rtm_type = RTN_UNICAST;	req.r.rtm_dst_len = rt->rt_dst.prefix_len;	if (AF_INET == family)	{		if (rt->rt_dst.prefix.v4 != nexthop->gateway.v4)		{			olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v4, sizeof(nexthop->gateway.v4));			req.r.rtm_scope = RT_SCOPE_UNIVERSE;			metric = RT_METRIC_DEFAULT;		}		olsr_netlink_addreq(&req, RTA_DST, &rt->rt_dst.prefix.v4, sizeof(rt->rt_dst.prefix.v4));	}	else	{		if (0 != memcmp(&rt->rt_dst.prefix.v6, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6)))		{			olsr_netlink_addreq(&req, RTA_GATEWAY, &nexthop->gateway.v6, sizeof(nexthop->gateway.v6));			req.r.rtm_scope = RT_SCOPE_UNIVERSE;			metric = RT_METRIC_DEFAULT;		}		olsr_netlink_addreq(&req, RTA_DST, &rt->rt_dst.prefix.v6, sizeof(rt->rt_dst.prefix.v6));	}	//!!!olsr_netlink_addreq(&req, RTA_PRIORITY, &rt->rt_best->rtp_metric.hops, sizeof(rt->rt_best->rtp_metric.hops));	olsr_netlink_addreq(&req, RTA_PRIORITY, &metric, sizeof(metric));	olsr_netlink_addreq(&req, RTA_OIF, &nexthop->iif_index, sizeof(nexthop->iif_index));	iov.iov_base = &req.n;	iov.iov_len = req.n.nlmsg_len;	memset(&nladdr, 0, sizeof(nladdr));	nladdr.nl_family = AF_NETLINK;	if (0 <= (ret = sendmsg(olsr_cnf->rtnl_s, &msg, 0)))	{		iov.iov_base = req.buf;		iov.iov_len = sizeof(req.buf);		if (0 < (ret = recvmsg(olsr_cnf->rtnl_s, &msg, 0)))		{			struct nlmsghdr* h = (struct nlmsghdr*)req.buf;			while (NLMSG_OK(h, (unsigned int)ret)) {				if (NLMSG_DONE == h->nlmsg_type) break;				if (NLMSG_ERROR == h->nlmsg_type)				{					if (NLMSG_LENGTH(sizeof(struct nlmsgerr) <= h->nlmsg_len))					{						struct nlmsgerr *l_err = (struct nlmsgerr*)NLMSG_DATA(h);						errno = -l_err->error;						if (0 != errno) ret = -1;					}					break;				}				h = NLMSG_NEXT(h, ret);			}		}		if (0 <= ret && olsr_cnf->open_ipc)		{			ipc_route_send_rtentry(				&rt->rt_dst.prefix,				&nexthop->gateway,			       	metric,			       	RTM_NEWROUTE == cmd,			       	if_ifwithindex_name(nexthop->iif_index));		}	}	return ret;}#endif /* LINUX_POLICY_ROUTING *//** * Insert a route in the kernel routing table * * @param destination the route to add * * @return negative on error */intolsr_ioctl_add_route(struct rt_entry *rt){#if !LINUX_POLICY_ROUTING  struct rtentry kernel_route;  union olsr_ip_addr mask;  int rslt;#endif /* LINUX_POLICY_ROUTING */  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));#if !LINUX_POLICY_ROUTING  memset(&kernel_route, 0, sizeof(struct rtentry));  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr =    rt->rt_dst.prefix.v4;  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {    return -1;  }  ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = mask.v4;  if (rt->rt_dst.prefix.v4 != rt->rt_best->rtp_nexthop.gateway.v4) {    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr =      rt->rt_best->rtp_nexthop.gateway.v4;  }  kernel_route.rt_flags = olsr_rt_flags(rt);  kernel_route.rt_metric = RT_METRIC_DEFAULT;  /*   * Set interface   */  kernel_route.rt_dev = if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index);  /* delete existing default route before ? */  if((olsr_cnf->del_gws) &&     (rt->rt_dst.prefix.v4 == INADDR_ANY) &&     (rt->rt_dst.prefix_len == INADDR_ANY)) {    delete_all_inet_gws();    olsr_cnf->del_gws = OLSR_FALSE;  }  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {    /*     * Send IPC route update message     */    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway,                           rt->rt_best->rtp_metric.hops, 1,                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));  }  return rslt;#else /* !LINUX_POLICY_ROUTING */	if (0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable)	{		/*		 * Users start whining about not having internet with policy		 * routing activated and no static default route in table 254.		 * We maintain a fallback defroute in the default=253 table.		 */		olsr_netlink_route(rt, AF_INET, 253, RTM_NEWROUTE);	}	return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_NEWROUTE);#endif /* LINUX_POLICY_ROUTING */}/** *Insert a route in the kernel routing table * *@param destination the route to add * *@return negative on error */intolsr_ioctl_add_route6(struct rt_entry *rt){#if !LINUX_POLICY_ROUTING  struct in6_rtmsg kernel_route;  int rslt;  OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best));  memset(&kernel_route, 0, sizeof(struct in6_rtmsg));  COPY_IP(&kernel_route.rtmsg_dst, &rt->rt_dst.prefix);  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;  COPY_IP(&kernel_route.rtmsg_gateway, &rt->rt_best->rtp_nexthop.gateway);  kernel_route.rtmsg_flags = olsr_rt_flags(rt);  kernel_route.rtmsg_metric = RT_METRIC_DEFAULT;    /*   * set interface   */  kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index;    /* XXX delete 0/0 route before ? */  if((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) {    /*     * Send IPC route update message     */    ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway,                            rt->rt_best->rtp_metric.hops, 1,                           if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index));  }  return rslt;#else /* !LINUX_POLICY_ROUTING */	return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_NEWROUTE);#endif /* LINUX_POLICY_ROUTING */}/** *Remove a route from the kernel * *@param destination the route to remove * *@return negative on error */intolsr_ioctl_del_route(struct rt_entry *rt){#if !LINUX_POLICY_ROUTING  struct rtentry kernel_route;  union olsr_ip_addr mask;  int rslt;#endif /* LINUX_POLICY_ROUTING */  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));#if !LINUX_POLICY_ROUTING  memset(&kernel_route,0,sizeof(struct rtentry));  ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET;  ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET;  ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET;  ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr =    rt->rt_dst.prefix.v4;  if (rt->rt_dst.prefix.v4 != rt->rt_nexthop.gateway.v4) {    ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr =      rt->rt_nexthop.gateway.v4;  }  if (!olsr_prefix_to_netmask(&mask, rt->rt_dst.prefix_len)) {    return -1;  } else {    ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = mask.v4;  }  kernel_route.rt_flags = olsr_rt_flags(rt);  kernel_route.rt_metric = RT_METRIC_DEFAULT;  /*   * Set interface   */  kernel_route.rt_dev = NULL;  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route)) >= 0) {    /*     * Send IPC route update message     */    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);  }  return rslt;#else /* !LINUX_POLICY_ROUTING */	if (0 == rt->rt_dst.prefix_len && 253 > olsr_cnf->rttable)	{		/*		 * Also remove the fallback default route		 */		olsr_netlink_route(rt, AF_INET, 253, RTM_DELROUTE);	}	return olsr_netlink_route(rt, AF_INET, olsr_cnf->rttable, RTM_DELROUTE);#endif /* LINUX_POLICY_ROUTING */}/** *Remove a route from the kernel * *@param destination the route to remove * *@return negative on error */intolsr_ioctl_del_route6(struct rt_entry *rt){#if !LINUX_POLICY_ROUTING  struct in6_rtmsg kernel_route;  int rslt;#endif /* LINUX_POLICY_ROUTING */  OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt));#if !LINUX_POLICY_ROUTING  memset(&kernel_route,0,sizeof(struct in6_rtmsg));  COPY_IP(&kernel_route.rtmsg_dst, &rt->rt_dst.prefix);  kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len;  COPY_IP(&kernel_route.rtmsg_gateway, &rt->rt_best->rtp_nexthop.gateway);  kernel_route.rtmsg_flags = olsr_rt_flags(rt);  kernel_route.rtmsg_metric = RT_METRIC_DEFAULT;  if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) {    /*     * Send IPC route update message     */    ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL);  }  return rslt;#else /* !LINUX_POLICY_ROUTING */	return olsr_netlink_route(rt, AF_INET6, olsr_cnf->rttable, RTM_DELROUTE);#endif /* LINUX_POLICY_ROUTING */}#if !LINUX_POLICY_ROUTINGstatic int delete_all_inet_gws(void){    int s;  char buf[BUFSIZ], *cp, *cplim;  struct ifconf ifc;  struct ifreq *ifr;    OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n");    /* Get a socket */  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)     {      olsr_syslog(OLSR_LOG_ERR, "socket: %m");      return -1;    }    ifc.ifc_len = sizeof (buf);  ifc.ifc_buf = buf;  if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)     {      olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)");      close(s);      return -1;    }  ifr = ifc.ifc_req;  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_addr))     {      struct rtentry kernel_route;      ifr = (struct ifreq *)cp;                  if(strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0)	{          OLSR_PRINTF(1, "Skipping loopback...\n");	  continue;	}      OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name);                  memset(&kernel_route,0,sizeof(struct rtentry));            ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0;      ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family=AF_INET;      ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0;      ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family=AF_INET;      ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY;      ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family=AF_INET;            kernel_route.rt_flags = RTF_UP | RTF_GATEWAY;	         kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name;      if((ioctl(s, SIOCDELRT, &kernel_route)) < 0)         OLSR_PRINTF(1, "NO\n");      else         OLSR_PRINTF(1, "YES\n");    }    close(s);  return 0;       }#endif /* LINUX_POLICY_ROUTING *//* * Local Variables: * c-basic-offset: 2 * End: */

⌨️ 快捷键说明

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