rtnetlink.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * INET An implementation of the TCP/IP protocol suite for the LINUX
  3.  * operating system.  INET is implemented using the  BSD Socket
  4.  * interface as the means of communication with the user level.
  5.  *
  6.  * Routing netlink socket interface: protocol independent part.
  7.  *
  8.  * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version
  13.  * 2 of the License, or (at your option) any later version.
  14.  *
  15.  * Fixes:
  16.  * Vitaly E. Lavrov RTA_OK arithmetics was wrong.
  17.  */
  18. #include <linux/config.h>
  19. #include <linux/errno.h>
  20. #include <linux/types.h>
  21. #include <linux/socket.h>
  22. #include <linux/kernel.h>
  23. #include <linux/major.h>
  24. #include <linux/sched.h>
  25. #include <linux/timer.h>
  26. #include <linux/string.h>
  27. #include <linux/sockios.h>
  28. #include <linux/net.h>
  29. #include <linux/fcntl.h>
  30. #include <linux/mm.h>
  31. #include <linux/slab.h>
  32. #include <linux/interrupt.h>
  33. #include <linux/capability.h>
  34. #include <linux/skbuff.h>
  35. #include <linux/init.h>
  36. #include <asm/uaccess.h>
  37. #include <asm/system.h>
  38. #include <asm/string.h>
  39. #include <linux/inet.h>
  40. #include <linux/netdevice.h>
  41. #include <net/ip.h>
  42. #include <net/protocol.h>
  43. #include <net/arp.h>
  44. #include <net/route.h>
  45. #include <net/udp.h>
  46. #include <net/sock.h>
  47. #include <net/pkt_sched.h>
  48. DECLARE_MUTEX(rtnl_sem);
  49. void rtnl_lock(void)
  50. {
  51. rtnl_shlock();
  52. rtnl_exlock();
  53. }
  54.  
  55. void rtnl_unlock(void)
  56. {
  57. rtnl_exunlock();
  58. rtnl_shunlock();
  59. }
  60. int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
  61. {
  62. memset(tb, 0, sizeof(struct rtattr*)*maxattr);
  63. while (RTA_OK(rta, len)) {
  64. unsigned flavor = rta->rta_type;
  65. if (flavor && flavor <= maxattr)
  66. tb[flavor-1] = rta;
  67. rta = RTA_NEXT(rta, len);
  68. }
  69. return 0;
  70. }
  71. struct sock *rtnl;
  72. struct rtnetlink_link * rtnetlink_links[NPROTO];
  73. static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] =
  74. {
  75. NLMSG_LENGTH(sizeof(struct ifinfomsg)),
  76. NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
  77. NLMSG_LENGTH(sizeof(struct rtmsg)),
  78. NLMSG_LENGTH(sizeof(struct ndmsg)),
  79. NLMSG_LENGTH(sizeof(struct rtmsg)),
  80. NLMSG_LENGTH(sizeof(struct tcmsg)),
  81. NLMSG_LENGTH(sizeof(struct tcmsg)),
  82. NLMSG_LENGTH(sizeof(struct tcmsg))
  83. };
  84. static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] =
  85. {
  86. IFLA_MAX,
  87. IFA_MAX,
  88. RTA_MAX,
  89. NDA_MAX,
  90. RTA_MAX,
  91. TCA_MAX,
  92. TCA_MAX,
  93. TCA_MAX
  94. };
  95. void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
  96. {
  97. struct rtattr *rta;
  98. int size = RTA_LENGTH(attrlen);
  99. rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
  100. rta->rta_type = attrtype;
  101. rta->rta_len = size;
  102. memcpy(RTA_DATA(rta), data, attrlen);
  103. }
  104. int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
  105. {
  106. int err = 0;
  107. NETLINK_CB(skb).dst_groups = group;
  108. if (echo)
  109. atomic_inc(&skb->users);
  110. netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
  111. if (echo)
  112. err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
  113. return err;
  114. }
  115. int rtnetlink_put_metrics(struct sk_buff *skb, unsigned *metrics)
  116. {
  117. struct rtattr *mx = (struct rtattr*)skb->tail;
  118. int i;
  119. RTA_PUT(skb, RTA_METRICS, 0, NULL);
  120. for (i=0; i<RTAX_MAX; i++) {
  121. if (metrics[i])
  122. RTA_PUT(skb, i+1, sizeof(unsigned), metrics+i);
  123. }
  124. mx->rta_len = skb->tail - (u8*)mx;
  125. if (mx->rta_len == RTA_LENGTH(0))
  126. skb_trim(skb, (u8*)mx - skb->data);
  127. return 0;
  128. rtattr_failure:
  129. skb_trim(skb, (u8*)mx - skb->data);
  130. return -1;
  131. }
  132. static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
  133.  int type, u32 pid, u32 seq, u32 change)
  134. {
  135. struct ifinfomsg *r;
  136. struct nlmsghdr  *nlh;
  137. unsigned char  *b = skb->tail;
  138. nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
  139. if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
  140. r = NLMSG_DATA(nlh);
  141. r->ifi_family = AF_UNSPEC;
  142. r->ifi_type = dev->type;
  143. r->ifi_index = dev->ifindex;
  144. r->ifi_flags = dev->flags;
  145. r->ifi_change = change;
  146. if (!netif_running(dev) || !netif_carrier_ok(dev))
  147. r->ifi_flags &= ~IFF_RUNNING;
  148. else
  149. r->ifi_flags |= IFF_RUNNING;
  150. RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
  151. if (dev->addr_len) {
  152. RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
  153. RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
  154. }
  155. if (1) {
  156. unsigned mtu = dev->mtu;
  157. RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
  158. }
  159. if (dev->ifindex != dev->iflink)
  160. RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
  161. if (dev->qdisc_sleeping)
  162. RTA_PUT(skb, IFLA_QDISC,
  163. strlen(dev->qdisc_sleeping->ops->id) + 1,
  164. dev->qdisc_sleeping->ops->id);
  165. if (dev->master)
  166. RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex);
  167. if (dev->get_stats) {
  168. struct net_device_stats *stats = dev->get_stats(dev);
  169. if (stats)
  170. RTA_PUT(skb, IFLA_STATS, sizeof(*stats), stats);
  171. }
  172. nlh->nlmsg_len = skb->tail - b;
  173. return skb->len;
  174. nlmsg_failure:
  175. rtattr_failure:
  176. skb_trim(skb, b - skb->data);
  177. return -1;
  178. }
  179. int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
  180. {
  181. int idx;
  182. int s_idx = cb->args[0];
  183. struct net_device *dev;
  184. read_lock(&dev_base_lock);
  185. for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
  186. if (idx < s_idx)
  187. continue;
  188. if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
  189. break;
  190. }
  191. read_unlock(&dev_base_lock);
  192. cb->args[0] = idx;
  193. return skb->len;
  194. }
  195. int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
  196. {
  197. int idx;
  198. int s_idx = cb->family;
  199. if (s_idx == 0)
  200. s_idx = 1;
  201. for (idx=1; idx<NPROTO; idx++) {
  202. int type = cb->nlh->nlmsg_type-RTM_BASE;
  203. if (idx < s_idx || idx == PF_PACKET)
  204. continue;
  205. if (rtnetlink_links[idx] == NULL ||
  206.     rtnetlink_links[idx][type].dumpit == NULL)
  207. continue;
  208. if (idx > s_idx)
  209. memset(&cb->args[0], 0, sizeof(cb->args));
  210. if (rtnetlink_links[idx][type].dumpit(skb, cb))
  211. break;
  212. }
  213. cb->family = idx;
  214. return skb->len;
  215. }
  216. void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
  217. {
  218. struct sk_buff *skb;
  219. int size = NLMSG_GOODSIZE;
  220. skb = alloc_skb(size, GFP_KERNEL);
  221. if (!skb)
  222. return;
  223. if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
  224. kfree_skb(skb);
  225. return;
  226. }
  227. NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
  228. netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_KERNEL);
  229. }
  230. static int rtnetlink_done(struct netlink_callback *cb)
  231. {
  232. return 0;
  233. }
  234. /* Process one rtnetlink message. */
  235. static __inline__ int
  236. rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
  237. {
  238. struct rtnetlink_link *link;
  239. struct rtnetlink_link *link_tab;
  240. struct rtattr *rta[RTATTR_MAX];
  241. int exclusive = 0;
  242. int sz_idx, kind;
  243. int min_len;
  244. int family;
  245. int type;
  246. int err;
  247. /* Only requests are handled by kernel now */
  248. if (!(nlh->nlmsg_flags&NLM_F_REQUEST))
  249. return 0;
  250. type = nlh->nlmsg_type;
  251. /* A control message: ignore them */
  252. if (type < RTM_BASE)
  253. return 0;
  254. /* Unknown message: reply with EINVAL */
  255. if (type > RTM_MAX)
  256. goto err_inval;
  257. type -= RTM_BASE;
  258. /* All the messages must have at least 1 byte length */
  259. if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg)))
  260. return 0;
  261. family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family;
  262. if (family > NPROTO) {
  263. *errp = -EAFNOSUPPORT;
  264. return -1;
  265. }
  266. link_tab = rtnetlink_links[family];
  267. if (link_tab == NULL)
  268. link_tab = rtnetlink_links[PF_UNSPEC];
  269. link = &link_tab[type];
  270. sz_idx = type>>2;
  271. kind = type&3;
  272. if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) {
  273. *errp = -EPERM;
  274. return -1;
  275. }
  276. if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
  277. u32 rlen;
  278. if (link->dumpit == NULL)
  279. link = &(rtnetlink_links[PF_UNSPEC][type]);
  280. if (link->dumpit == NULL)
  281. goto err_inval;
  282. if ((*errp = netlink_dump_start(rtnl, skb, nlh,
  283. link->dumpit,
  284. rtnetlink_done)) != 0) {
  285. return -1;
  286. }
  287. rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  288. if (rlen > skb->len)
  289. rlen = skb->len;
  290. skb_pull(skb, rlen);
  291. return -1;
  292. }
  293. if (kind != 2) {
  294. if (rtnl_exlock_nowait()) {
  295. *errp = 0;
  296. return -1;
  297. }
  298. exclusive = 1;
  299. }
  300. memset(&rta, 0, sizeof(rta));
  301. min_len = rtm_min[sz_idx];
  302. if (nlh->nlmsg_len < min_len)
  303. goto err_inval;
  304. if (nlh->nlmsg_len > min_len) {
  305. int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
  306. struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len);
  307. while (RTA_OK(attr, attrlen)) {
  308. unsigned flavor = attr->rta_type;
  309. if (flavor) {
  310. if (flavor > rta_max[sz_idx])
  311. goto err_inval;
  312. rta[flavor-1] = attr;
  313. }
  314. attr = RTA_NEXT(attr, attrlen);
  315. }
  316. }
  317. if (link->doit == NULL)
  318. link = &(rtnetlink_links[PF_UNSPEC][type]);
  319. if (link->doit == NULL)
  320. goto err_inval;
  321. err = link->doit(skb, nlh, (void *)&rta);
  322. if (exclusive)
  323. rtnl_exunlock();
  324. *errp = err;
  325. return err;
  326. err_inval:
  327. if (exclusive)
  328. rtnl_exunlock();
  329. *errp = -EINVAL;
  330. return -1;
  331. }
  332. /* 
  333.  * Process one packet of messages.
  334.  * Malformed skbs with wrong lengths of messages are discarded silently.
  335.  */
  336. extern __inline__ int rtnetlink_rcv_skb(struct sk_buff *skb)
  337. {
  338. int err;
  339. struct nlmsghdr * nlh;
  340. while (skb->len >= NLMSG_SPACE(0)) {
  341. u32 rlen;
  342. nlh = (struct nlmsghdr *)skb->data;
  343. if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
  344. return 0;
  345. rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  346. if (rlen > skb->len)
  347. rlen = skb->len;
  348. if (rtnetlink_rcv_msg(skb, nlh, &err)) {
  349. /* Not error, but we must interrupt processing here:
  350.  *   Note, that in this case we do not pull message
  351.  *   from skb, it will be processed later.
  352.  */
  353. if (err == 0)
  354. return -1;
  355. netlink_ack(skb, nlh, err);
  356. } else if (nlh->nlmsg_flags&NLM_F_ACK)
  357. netlink_ack(skb, nlh, 0);
  358. skb_pull(skb, rlen);
  359. }
  360. return 0;
  361. }
  362. /*
  363.  *  rtnetlink input queue processing routine:
  364.  * - try to acquire shared lock. If it is failed, defer processing.
  365.  * - feed skbs to rtnetlink_rcv_skb, until it refuse a message,
  366.  *   that will occur, when a dump started and/or acquisition of
  367.  *   exclusive lock failed.
  368.  */
  369. static void rtnetlink_rcv(struct sock *sk, int len)
  370. {
  371. do {
  372. struct sk_buff *skb;
  373. if (rtnl_shlock_nowait())
  374. return;
  375. while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
  376. if (rtnetlink_rcv_skb(skb)) {
  377. if (skb->len)
  378. skb_queue_head(&sk->receive_queue, skb);
  379. else
  380. kfree_skb(skb);
  381. break;
  382. }
  383. kfree_skb(skb);
  384. }
  385. up(&rtnl_sem);
  386. } while (rtnl && rtnl->receive_queue.qlen);
  387. }
  388. static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
  389. {
  390. { NULL, NULL, },
  391. { NULL, NULL, },
  392. { NULL, rtnetlink_dump_ifinfo, },
  393. { NULL, NULL, },
  394. { NULL, NULL, },
  395. { NULL, NULL, },
  396. { NULL, rtnetlink_dump_all, },
  397. { NULL, NULL, },
  398. { NULL, NULL, },
  399. { NULL, NULL, },
  400. { NULL, rtnetlink_dump_all, },
  401. { NULL, NULL, },
  402. { neigh_add, NULL, },
  403. { neigh_delete, NULL, },
  404. { NULL, neigh_dump_info, },
  405. { NULL, NULL, },
  406. { NULL, NULL, },
  407. { NULL, NULL, },
  408. { NULL, NULL, },
  409. { NULL, NULL, },
  410. };
  411. static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
  412. {
  413. struct net_device *dev = ptr;
  414. switch (event) {
  415. case NETDEV_UNREGISTER:
  416. rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
  417. break;
  418. case NETDEV_REGISTER:
  419. rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U);
  420. break;
  421. case NETDEV_UP:
  422. case NETDEV_DOWN:
  423. rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING);
  424. break;
  425. case NETDEV_CHANGE:
  426. case NETDEV_GOING_DOWN:
  427. break;
  428. default:
  429. rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
  430. break;
  431. }
  432. return NOTIFY_DONE;
  433. }
  434. struct notifier_block rtnetlink_dev_notifier = {
  435. rtnetlink_event,
  436. NULL,
  437. 0
  438. };
  439. void __init rtnetlink_init(void)
  440. {
  441. #ifdef RTNL_DEBUG
  442. printk("Initializing RT netlink socketn");
  443. #endif
  444. rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv);
  445. if (rtnl == NULL)
  446. panic("rtnetlink_init: cannot initialize rtnetlinkn");
  447. register_netdevice_notifier(&rtnetlink_dev_notifier);
  448. rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table;
  449. rtnetlink_links[PF_PACKET] = link_rtnetlink_table;
  450. }