00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
00286
if (!(nlh->
nlmsg_flags&
NLM_F_REQUEST))
00287
return 0;
00288
00289 type = nlh->
nlmsg_type;
00290
00291
00292
if (type < RTM_BASE)
00293
return 0;
00294
00295
00296
if (type > RTM_MAX)
00297
goto err_inval;
00298
00299 type -= RTM_BASE;
00300
00301
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
00394
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
00413
00414
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
00429
00430
00431
00432
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 }