Main Page | Class List | File List | Class Members | File Members

rtnetlink.c

Go to the documentation of this file.
00001 /* 00002 * INET An implementation of the TCP/IP protocol suite for the LINUX 00003 * operating system. INET is implemented using the BSD Socket 00004 * interface as the means of communication with the user level. 00005 * 00006 * Routing netlink socket interface: protocol independent part. 00007 * 00008 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 00009 * 00010 * This program is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU General Public License 00012 * as published by the Free Software Foundation; either version 00013 * 2 of the License, or (at your option) any later version. 00014 * 00015 * Fixes: 00016 * Vitaly E. Lavrov RTA_OK arithmetics was wrong. 00017 */ 00018 00019 #include <linux/config.h> 00020 #include <linux/errno.h> 00021 #include <linux/types.h> 00022 #include <linux/socket.h> 00023 #include <linux/kernel.h> 00024 #include <linux/major.h> 00025 #include <linux/sched.h> 00026 #include <linux/timer.h> 00027 #include <linux/string.h> 00028 #include <linux/sockios.h> 00029 #include <linux/net.h> 00030 #include <linux/fcntl.h> 00031 #include <linux/mm.h> 00032 #include <linux/slab.h> 00033 #include <linux/interrupt.h> 00034 #include <linux/capability.h> 00035 #include <linux/skbuff.h> 00036 #include <linux/init.h> 00037 00038 #include <asm/uaccess.h> 00039 #include <asm/system.h> 00040 #include <asm/string.h> 00041 00042 #include <linux/inet.h> 00043 #include <linux/netdevice.h> 00044 #include <net/ip.h> 00045 #include <net/protocol.h> 00046 #include <net/arp.h> 00047 #include <net/route.h> 00048 #include <net/udp.h> 00049 #include <net/sock.h> 00050 #include <net/pkt_sched.h> 00051 00052 DECLARE_MUTEX(rtnl_sem); 00053 00054 void rtnl_lock(void) 00055 { 00056 rtnl_shlock(); 00057 rtnl_exlock(); 00058 } 00059 00060 void rtnl_unlock(void) 00061 { 00062 rtnl_exunlock(); 00063 rtnl_shunlock(); 00064 } 00065 00066 int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) 00067 { 00068 memset(tb, 0, sizeof(struct rtattr*)*maxattr); 00069 00070 while (RTA_OK(rta, len)) { 00071 unsigned flavor = rta->rta_type; 00072 if (flavor && flavor <= maxattr) 00073 tb[flavor-1] = rta; 00074 rta = RTA_NEXT(rta, len); 00075 } 00076 return 0; 00077 } 00078 00079 struct sock *rtnl; 00080 00081 struct rtnetlink_link * rtnetlink_links[NPROTO]; 00082 00083 static const int rtm_min[(RTM_MAX+1-RTM_BASE)/4] = 00084 { 00085 NLMSG_LENGTH(sizeof(struct ifinfomsg)), 00086 NLMSG_LENGTH(sizeof(struct ifaddrmsg)), 00087 NLMSG_LENGTH(sizeof(struct rtmsg)), 00088 NLMSG_LENGTH(sizeof(struct ndmsg)), 00089 NLMSG_LENGTH(sizeof(struct rtmsg)), 00090 NLMSG_LENGTH(sizeof(struct tcmsg)), 00091 NLMSG_LENGTH(sizeof(struct tcmsg)), 00092 NLMSG_LENGTH(sizeof(struct tcmsg)) 00093 }; 00094 00095 static const int rta_max[(RTM_MAX+1-RTM_BASE)/4] = 00096 { 00097 IFLA_MAX, 00098 IFA_MAX, 00099 RTA_MAX, 00100 NDA_MAX, 00101 RTA_MAX, 00102 TCA_MAX, 00103 TCA_MAX, 00104 TCA_MAX 00105 }; 00106 00107 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 00108 { 00109 struct rtattr *rta; 00110 int size = RTA_LENGTH(attrlen); 00111 00112 rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); 00113 rta->rta_type = attrtype; 00114 rta->rta_len = size; 00115 memcpy(RTA_DATA(rta), data, attrlen); 00116 } 00117 00118 int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) 00119 { 00120 int err = 0; 00121 00122 NETLINK_CB(skb).dst_groups = group; 00123 if (echo) 00124 atomic_inc(&skb->users); 00125 netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL); 00126 if (echo) 00127 err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); 00128 return err; 00129 } 00130 00131 int rtnetlink_put_metrics(struct sk_buff *skb, unsigned *metrics) 00132 { 00133 struct rtattr *mx = (struct rtattr*)skb->tail; 00134 int i; 00135 00136 RTA_PUT(skb, RTA_METRICS, 0, NULL); 00137 for (i=0; i<RTAX_MAX; i++) { 00138 if (metrics[i]) 00139 RTA_PUT(skb, i+1, sizeof(unsigned), metrics+i); 00140 } 00141 mx->rta_len = skb->tail - (u8*)mx; 00142 if (mx->rta_len == RTA_LENGTH(0)) 00143 skb_trim(skb, (u8*)mx - skb->data); 00144 return 0; 00145 00146 rtattr_failure: 00147 skb_trim(skb, (u8*)mx - skb->data); 00148 return -1; 00149 } 00150 00151 00152 static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 00153 int type, u32 pid, u32 seq, u32 change) 00154 { 00155 struct ifinfomsg *r; 00156 struct nlmsghdr *nlh; 00157 unsigned char *b = skb->tail; 00158 00159 nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r)); 00160 if (pid) nlh->nlmsg_flags |= NLM_F_MULTI; 00161 r = NLMSG_DATA(nlh); 00162 r->ifi_family = AF_UNSPEC; 00163 r->ifi_type = dev->type; 00164 r->ifi_index = dev->ifindex; 00165 r->ifi_flags = dev->flags; 00166 r->ifi_change = change; 00167 00168 if (!netif_running(dev) || !netif_carrier_ok(dev)) 00169 r->ifi_flags &= ~IFF_RUNNING; 00170 else 00171 r->ifi_flags |= IFF_RUNNING; 00172 00173 RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); 00174 if (dev->addr_len) { 00175 RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); 00176 RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); 00177 } 00178 if (1) { 00179 unsigned mtu = dev->mtu; 00180 RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); 00181 } 00182 if (dev->ifindex != dev->iflink) 00183 RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); 00184 if (dev->qdisc_sleeping) 00185 RTA_PUT(skb, IFLA_QDISC, 00186 strlen(dev->qdisc_sleeping->ops->id) + 1, 00187 dev->qdisc_sleeping->ops->id); 00188 if (dev->master) 00189 RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex); 00190 if (dev->get_stats) { 00191 struct net_device_stats *stats = dev->get_stats(dev); 00192 if (stats) 00193 RTA_PUT(skb, IFLA_STATS, sizeof(*stats), stats); 00194 } 00195 nlh->nlmsg_len = skb->tail - b; 00196 return skb->len; 00197 00198 nlmsg_failure: 00199 rtattr_failure: 00200 skb_trim(skb, b - skb->data); 00201 return -1; 00202 } 00203 00204 int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 00205 { 00206 int idx; 00207 int s_idx = cb->args[0]; 00208 struct net_device *dev; 00209 00210 read_lock(&dev_base_lock); 00211 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { 00212 if (idx < s_idx) 00213 continue; 00214 if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0) 00215 break; 00216 } 00217 read_unlock(&dev_base_lock); 00218 cb->args[0] = idx; 00219 00220 return skb->len; 00221 } 00222 00223 int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 00224 { 00225 int idx; 00226 int s_idx = cb->family; 00227 00228 if (s_idx == 0) 00229 s_idx = 1; 00230 for (idx=1; idx<NPROTO; idx++) { 00231 int type = cb->nlh->nlmsg_type-RTM_BASE; 00232 if (idx < s_idx || idx == PF_PACKET) 00233 continue; 00234 if (rtnetlink_links[idx] == NULL || 00235 rtnetlink_links[idx][type].dumpit == NULL) 00236 continue; 00237 if (idx > s_idx) 00238 memset(&cb->args[0], 0, sizeof(cb->args)); 00239 if (rtnetlink_links[idx][type].dumpit(skb, cb)) 00240 break; 00241 } 00242 cb->family = idx; 00243 00244 return skb->len; 00245 } 00246 00247 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) 00248 { 00249 struct sk_buff *skb; 00250 int size = NLMSG_GOODSIZE; 00251 00252 skb = alloc_skb(size, GFP_KERNEL); 00253 if (!skb) 00254 return; 00255 00256 if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) { 00257 kfree_skb(skb); 00258 return; 00259 } 00260 NETLINK_CB(skb).dst_groups = RTMGRP_LINK; 00261 netlink_broadcast(rtnl, skb, 0, RTMGRP_LINK, GFP_KERNEL); 00262 } 00263 00264 static int rtnetlink_done(struct netlink_callback *cb) 00265 { 00266 return 0; 00267 } 00268 00269 /* Process one rtnetlink message. */ 00270 00271 static __inline__ int 00272 rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) 00273 { 00274 struct rtnetlink_link *link; 00275 struct rtnetlink_link *link_tab; 00276 struct rtattr *rta[RTATTR_MAX]; 00277 00278 int exclusive = 0; 00279 int sz_idx, kind; 00280 int min_len; 00281 int family; 00282 int type; 00283 int err; 00284 00285 /* Only requests are handled by kernel now */ 00286 if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) 00287 return 0; 00288 00289 type = nlh->nlmsg_type; 00290 00291 /* A control message: ignore them */ 00292 if (type < RTM_BASE) 00293 return 0; 00294 00295 /* Unknown message: reply with EINVAL */ 00296 if (type > RTM_MAX) 00297 goto err_inval; 00298 00299 type -= RTM_BASE; 00300 00301 /* All the messages must have at least 1 byte length */ 00302 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) 00303 return 0; 00304 00305 family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; 00306 if (family > NPROTO) { 00307 *errp = -EAFNOSUPPORT; 00308 return -1; 00309 } 00310 00311 link_tab = rtnetlink_links[family]; 00312 if (link_tab == NULL) 00313 link_tab = rtnetlink_links[PF_UNSPEC]; 00314 link = &link_tab[type]; 00315 00316 sz_idx = type>>2; 00317 kind = type&3; 00318 00319 if (kind != 2 && !cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { 00320 *errp = -EPERM; 00321 return -1; 00322 } 00323 00324 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 00325 u32 rlen; 00326 00327 if (link->dumpit == NULL) 00328 link = &(rtnetlink_links[PF_UNSPEC][type]); 00329 00330 if (link->dumpit == NULL) 00331 goto err_inval; 00332 00333 if ((*errp = netlink_dump_start(rtnl, skb, nlh, 00334 link->dumpit, 00335 rtnetlink_done)) != 0) { 00336 return -1; 00337 } 00338 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 00339 if (rlen > skb->len) 00340 rlen = skb->len; 00341 skb_pull(skb, rlen); 00342 return -1; 00343 } 00344 00345 if (kind != 2) { 00346 if (rtnl_exlock_nowait()) { 00347 *errp = 0; 00348 return -1; 00349 } 00350 exclusive = 1; 00351 } 00352 00353 memset(&rta, 0, sizeof(rta)); 00354 00355 min_len = rtm_min[sz_idx]; 00356 if (nlh->nlmsg_len < min_len) 00357 goto err_inval; 00358 00359 if (nlh->nlmsg_len > min_len) { 00360 int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); 00361 struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len); 00362 00363 while (RTA_OK(attr, attrlen)) { 00364 unsigned flavor = attr->rta_type; 00365 if (flavor) { 00366 if (flavor > rta_max[sz_idx]) 00367 goto err_inval; 00368 rta[flavor-1] = attr; 00369 } 00370 attr = RTA_NEXT(attr, attrlen); 00371 } 00372 } 00373 00374 if (link->doit == NULL) 00375 link = &(rtnetlink_links[PF_UNSPEC][type]); 00376 if (link->doit == NULL) 00377 goto err_inval; 00378 err = link->doit(skb, nlh, (void *)&rta); 00379 00380 if (exclusive) 00381 rtnl_exunlock(); 00382 *errp = err; 00383 return err; 00384 00385 err_inval: 00386 if (exclusive) 00387 rtnl_exunlock(); 00388 *errp = -EINVAL; 00389 return -1; 00390 } 00391 00392 /* 00393 * Process one packet of messages. 00394 * Malformed skbs with wrong lengths of messages are discarded silently. 00395 */ 00396 00397 static inline int rtnetlink_rcv_skb(struct sk_buff *skb) 00398 { 00399 int err; 00400 struct nlmsghdr * nlh; 00401 00402 while (skb->len >= NLMSG_SPACE(0)) { 00403 u32 rlen; 00404 00405 nlh = (struct nlmsghdr *)skb->data; 00406 if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) 00407 return 0; 00408 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 00409 if (rlen > skb->len) 00410 rlen = skb->len; 00411 if (rtnetlink_rcv_msg(skb, nlh, &err)) { 00412 /* Not error, but we must interrupt processing here: 00413 * Note, that in this case we do not pull message 00414 * from skb, it will be processed later. 00415 */ 00416 if (err == 0) 00417 return -1; 00418 netlink_ack(skb, nlh, err); 00419 } else if (nlh->nlmsg_flags&NLM_F_ACK) 00420 netlink_ack(skb, nlh, 0); 00421 skb_pull(skb, rlen); 00422 } 00423 00424 return 0; 00425 } 00426 00427 /* 00428 * rtnetlink input queue processing routine: 00429 * - try to acquire shared lock. If it is failed, defer processing. 00430 * - feed skbs to rtnetlink_rcv_skb, until it refuse a message, 00431 * that will occur, when a dump started and/or acquisition of 00432 * exclusive lock failed. 00433 */ 00434 00435 static void rtnetlink_rcv(struct sock *sk, int len) 00436 { 00437 do { 00438 struct sk_buff *skb; 00439 00440 if (rtnl_shlock_nowait()) 00441 return; 00442 00443 while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { 00444 if (rtnetlink_rcv_skb(skb)) { 00445 if (skb->len) 00446 skb_queue_head(&sk->receive_queue, skb); 00447 else 00448 kfree_skb(skb); 00449 break; 00450 } 00451 kfree_skb(skb); 00452 } 00453 00454 up(&rtnl_sem); 00455 } while (rtnl && rtnl->receive_queue.qlen); 00456 } 00457 00458 static struct rtnetlink_link link_rtnetlink_table[RTM_MAX-RTM_BASE+1] = 00459 { 00460 { NULL, NULL, }, 00461 { NULL, NULL, }, 00462 { NULL, rtnetlink_dump_ifinfo, }, 00463 { NULL, NULL, }, 00464 00465 { NULL, NULL, }, 00466 { NULL, NULL, }, 00467 { NULL, rtnetlink_dump_all, }, 00468 { NULL, NULL, }, 00469 00470 { NULL, NULL, }, 00471 { NULL, NULL, }, 00472 { NULL, rtnetlink_dump_all, }, 00473 { NULL, NULL, }, 00474 00475 { neigh_add, NULL, }, 00476 { neigh_delete, NULL, }, 00477 { NULL, neigh_dump_info, }, 00478 { NULL, NULL, }, 00479 00480 { NULL, NULL, }, 00481 { NULL, NULL, }, 00482 { NULL, NULL, }, 00483 { NULL, NULL, }, 00484 }; 00485 00486 00487 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) 00488 { 00489 struct net_device *dev = ptr; 00490 switch (event) { 00491 case NETDEV_UNREGISTER: 00492 rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); 00493 break; 00494 case NETDEV_REGISTER: 00495 rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); 00496 break; 00497 case NETDEV_UP: 00498 case NETDEV_DOWN: 00499 rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); 00500 break; 00501 case NETDEV_CHANGE: 00502 case NETDEV_GOING_DOWN: 00503 break; 00504 default: 00505 rtmsg_ifinfo(RTM_NEWLINK, dev, 0); 00506 break; 00507 } 00508 return NOTIFY_DONE; 00509 } 00510 00511 struct notifier_block rtnetlink_dev_notifier = { 00512 rtnetlink_event, 00513 NULL, 00514 0 00515 }; 00516 00517 00518 void __init rtnetlink_init(void) 00519 { 00520 #ifdef RTNL_DEBUG 00521 printk("Initializing RT netlink socket\n"); 00522 #endif 00523 rtnl = netlink_kernel_create(NETLINK_ROUTE, rtnetlink_rcv); 00524 if (rtnl == NULL) 00525 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 00526 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 00527 register_netdevice_notifier(&rtnetlink_dev_notifier); 00528 rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table; 00529 rtnetlink_links[PF_PACKET] = link_rtnetlink_table; 00530 }

Generated on Wed Dec 1 21:25:32 2004 for Linux 2.4.23 Networking by doxygen 1.3.8