diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
| -rw-r--r-- | net/netlink/af_netlink.c | 143 |
1 files changed, 97 insertions, 46 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a4957bf2ca60..cd96ed3ccee4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -455,9 +455,14 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, | |||
| 455 | if (nl_table[protocol].registered && | 455 | if (nl_table[protocol].registered && |
| 456 | try_module_get(nl_table[protocol].module)) | 456 | try_module_get(nl_table[protocol].module)) |
| 457 | module = nl_table[protocol].module; | 457 | module = nl_table[protocol].module; |
| 458 | else | ||
| 459 | err = -EPROTONOSUPPORT; | ||
| 458 | cb_mutex = nl_table[protocol].cb_mutex; | 460 | cb_mutex = nl_table[protocol].cb_mutex; |
| 459 | netlink_unlock_table(); | 461 | netlink_unlock_table(); |
| 460 | 462 | ||
| 463 | if (err < 0) | ||
| 464 | goto out; | ||
| 465 | |||
| 461 | err = __netlink_create(net, sock, cb_mutex, protocol); | 466 | err = __netlink_create(net, sock, cb_mutex, protocol); |
| 462 | if (err < 0) | 467 | if (err < 0) |
| 463 | goto out_module; | 468 | goto out_module; |
| @@ -540,7 +545,7 @@ static int netlink_autobind(struct socket *sock) | |||
| 540 | struct hlist_head *head; | 545 | struct hlist_head *head; |
| 541 | struct sock *osk; | 546 | struct sock *osk; |
| 542 | struct hlist_node *node; | 547 | struct hlist_node *node; |
| 543 | s32 pid = current->tgid; | 548 | s32 pid = task_tgid_vnr(current); |
| 544 | int err; | 549 | int err; |
| 545 | static s32 rover = -4097; | 550 | static s32 rover = -4097; |
| 546 | 551 | ||
| @@ -678,6 +683,9 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
| 678 | struct netlink_sock *nlk = nlk_sk(sk); | 683 | struct netlink_sock *nlk = nlk_sk(sk); |
| 679 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; | 684 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
| 680 | 685 | ||
| 686 | if (alen < sizeof(addr->sa_family)) | ||
| 687 | return -EINVAL; | ||
| 688 | |||
| 681 | if (addr->sa_family == AF_UNSPEC) { | 689 | if (addr->sa_family == AF_UNSPEC) { |
| 682 | sk->sk_state = NETLINK_UNCONNECTED; | 690 | sk->sk_state = NETLINK_UNCONNECTED; |
| 683 | nlk->dst_pid = 0; | 691 | nlk->dst_pid = 0; |
| @@ -970,6 +978,8 @@ struct netlink_broadcast_data { | |||
| 970 | int delivered; | 978 | int delivered; |
| 971 | gfp_t allocation; | 979 | gfp_t allocation; |
| 972 | struct sk_buff *skb, *skb2; | 980 | struct sk_buff *skb, *skb2; |
| 981 | int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data); | ||
| 982 | void *tx_data; | ||
| 973 | }; | 983 | }; |
| 974 | 984 | ||
| 975 | static inline int do_one_broadcast(struct sock *sk, | 985 | static inline int do_one_broadcast(struct sock *sk, |
| @@ -1012,6 +1022,9 @@ static inline int do_one_broadcast(struct sock *sk, | |||
| 1012 | p->failure = 1; | 1022 | p->failure = 1; |
| 1013 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) | 1023 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) |
| 1014 | p->delivery_failure = 1; | 1024 | p->delivery_failure = 1; |
| 1025 | } else if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) { | ||
| 1026 | kfree_skb(p->skb2); | ||
| 1027 | p->skb2 = NULL; | ||
| 1015 | } else if (sk_filter(sk, p->skb2)) { | 1028 | } else if (sk_filter(sk, p->skb2)) { |
| 1016 | kfree_skb(p->skb2); | 1029 | kfree_skb(p->skb2); |
| 1017 | p->skb2 = NULL; | 1030 | p->skb2 = NULL; |
| @@ -1030,8 +1043,10 @@ out: | |||
| 1030 | return 0; | 1043 | return 0; |
| 1031 | } | 1044 | } |
| 1032 | 1045 | ||
| 1033 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | 1046 | int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid, |
| 1034 | u32 group, gfp_t allocation) | 1047 | u32 group, gfp_t allocation, |
| 1048 | int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data), | ||
| 1049 | void *filter_data) | ||
| 1035 | { | 1050 | { |
| 1036 | struct net *net = sock_net(ssk); | 1051 | struct net *net = sock_net(ssk); |
| 1037 | struct netlink_broadcast_data info; | 1052 | struct netlink_broadcast_data info; |
| @@ -1051,6 +1066,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
| 1051 | info.allocation = allocation; | 1066 | info.allocation = allocation; |
| 1052 | info.skb = skb; | 1067 | info.skb = skb; |
| 1053 | info.skb2 = NULL; | 1068 | info.skb2 = NULL; |
| 1069 | info.tx_filter = filter; | ||
| 1070 | info.tx_data = filter_data; | ||
| 1054 | 1071 | ||
| 1055 | /* While we sleep in clone, do not allow to change socket list */ | 1072 | /* While we sleep in clone, do not allow to change socket list */ |
| 1056 | 1073 | ||
| @@ -1059,14 +1076,15 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
| 1059 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 1076 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
| 1060 | do_one_broadcast(sk, &info); | 1077 | do_one_broadcast(sk, &info); |
| 1061 | 1078 | ||
| 1062 | kfree_skb(skb); | 1079 | consume_skb(skb); |
| 1063 | 1080 | ||
| 1064 | netlink_unlock_table(); | 1081 | netlink_unlock_table(); |
| 1065 | 1082 | ||
| 1066 | kfree_skb(info.skb2); | 1083 | if (info.delivery_failure) { |
| 1067 | 1084 | kfree_skb(info.skb2); | |
| 1068 | if (info.delivery_failure) | ||
| 1069 | return -ENOBUFS; | 1085 | return -ENOBUFS; |
| 1086 | } else | ||
| 1087 | consume_skb(info.skb2); | ||
| 1070 | 1088 | ||
| 1071 | if (info.delivered) { | 1089 | if (info.delivered) { |
| 1072 | if (info.congested && (allocation & __GFP_WAIT)) | 1090 | if (info.congested && (allocation & __GFP_WAIT)) |
| @@ -1075,6 +1093,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
| 1075 | } | 1093 | } |
| 1076 | return -ESRCH; | 1094 | return -ESRCH; |
| 1077 | } | 1095 | } |
| 1096 | EXPORT_SYMBOL(netlink_broadcast_filtered); | ||
| 1097 | |||
| 1098 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | ||
| 1099 | u32 group, gfp_t allocation) | ||
| 1100 | { | ||
| 1101 | return netlink_broadcast_filtered(ssk, skb, pid, group, allocation, | ||
| 1102 | NULL, NULL); | ||
| 1103 | } | ||
| 1078 | EXPORT_SYMBOL(netlink_broadcast); | 1104 | EXPORT_SYMBOL(netlink_broadcast); |
| 1079 | 1105 | ||
| 1080 | struct netlink_set_err_data { | 1106 | struct netlink_set_err_data { |
| @@ -1088,6 +1114,7 @@ static inline int do_one_set_err(struct sock *sk, | |||
| 1088 | struct netlink_set_err_data *p) | 1114 | struct netlink_set_err_data *p) |
| 1089 | { | 1115 | { |
| 1090 | struct netlink_sock *nlk = nlk_sk(sk); | 1116 | struct netlink_sock *nlk = nlk_sk(sk); |
| 1117 | int ret = 0; | ||
| 1091 | 1118 | ||
| 1092 | if (sk == p->exclude_sk) | 1119 | if (sk == p->exclude_sk) |
| 1093 | goto out; | 1120 | goto out; |
| @@ -1099,10 +1126,15 @@ static inline int do_one_set_err(struct sock *sk, | |||
| 1099 | !test_bit(p->group - 1, nlk->groups)) | 1126 | !test_bit(p->group - 1, nlk->groups)) |
| 1100 | goto out; | 1127 | goto out; |
| 1101 | 1128 | ||
| 1129 | if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { | ||
| 1130 | ret = 1; | ||
| 1131 | goto out; | ||
| 1132 | } | ||
| 1133 | |||
| 1102 | sk->sk_err = p->code; | 1134 | sk->sk_err = p->code; |
| 1103 | sk->sk_error_report(sk); | 1135 | sk->sk_error_report(sk); |
| 1104 | out: | 1136 | out: |
| 1105 | return 0; | 1137 | return ret; |
| 1106 | } | 1138 | } |
| 1107 | 1139 | ||
| 1108 | /** | 1140 | /** |
| @@ -1111,12 +1143,16 @@ out: | |||
| 1111 | * @pid: the PID of a process that we want to skip (if any) | 1143 | * @pid: the PID of a process that we want to skip (if any) |
| 1112 | * @groups: the broadcast group that will notice the error | 1144 | * @groups: the broadcast group that will notice the error |
| 1113 | * @code: error code, must be negative (as usual in kernelspace) | 1145 | * @code: error code, must be negative (as usual in kernelspace) |
| 1146 | * | ||
| 1147 | * This function returns the number of broadcast listeners that have set the | ||
| 1148 | * NETLINK_RECV_NO_ENOBUFS socket option. | ||
| 1114 | */ | 1149 | */ |
| 1115 | void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | 1150 | int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) |
| 1116 | { | 1151 | { |
| 1117 | struct netlink_set_err_data info; | 1152 | struct netlink_set_err_data info; |
| 1118 | struct hlist_node *node; | 1153 | struct hlist_node *node; |
| 1119 | struct sock *sk; | 1154 | struct sock *sk; |
| 1155 | int ret = 0; | ||
| 1120 | 1156 | ||
| 1121 | info.exclude_sk = ssk; | 1157 | info.exclude_sk = ssk; |
| 1122 | info.pid = pid; | 1158 | info.pid = pid; |
| @@ -1127,9 +1163,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | |||
| 1127 | read_lock(&nl_table_lock); | 1163 | read_lock(&nl_table_lock); |
| 1128 | 1164 | ||
| 1129 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 1165 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
| 1130 | do_one_set_err(sk, &info); | 1166 | ret += do_one_set_err(sk, &info); |
| 1131 | 1167 | ||
| 1132 | read_unlock(&nl_table_lock); | 1168 | read_unlock(&nl_table_lock); |
| 1169 | return ret; | ||
| 1133 | } | 1170 | } |
| 1134 | EXPORT_SYMBOL(netlink_set_err); | 1171 | EXPORT_SYMBOL(netlink_set_err); |
| 1135 | 1172 | ||
| @@ -1287,19 +1324,23 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1287 | if (msg->msg_flags&MSG_OOB) | 1324 | if (msg->msg_flags&MSG_OOB) |
| 1288 | return -EOPNOTSUPP; | 1325 | return -EOPNOTSUPP; |
| 1289 | 1326 | ||
| 1290 | if (NULL == siocb->scm) | 1327 | if (NULL == siocb->scm) { |
| 1291 | siocb->scm = &scm; | 1328 | siocb->scm = &scm; |
| 1329 | memset(&scm, 0, sizeof(scm)); | ||
| 1330 | } | ||
| 1292 | err = scm_send(sock, msg, siocb->scm); | 1331 | err = scm_send(sock, msg, siocb->scm); |
| 1293 | if (err < 0) | 1332 | if (err < 0) |
| 1294 | return err; | 1333 | return err; |
| 1295 | 1334 | ||
| 1296 | if (msg->msg_namelen) { | 1335 | if (msg->msg_namelen) { |
| 1336 | err = -EINVAL; | ||
| 1297 | if (addr->nl_family != AF_NETLINK) | 1337 | if (addr->nl_family != AF_NETLINK) |
| 1298 | return -EINVAL; | 1338 | goto out; |
| 1299 | dst_pid = addr->nl_pid; | 1339 | dst_pid = addr->nl_pid; |
| 1300 | dst_group = ffs(addr->nl_groups); | 1340 | dst_group = ffs(addr->nl_groups); |
| 1341 | err = -EPERM; | ||
| 1301 | if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) | 1342 | if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) |
| 1302 | return -EPERM; | 1343 | goto out; |
| 1303 | } else { | 1344 | } else { |
| 1304 | dst_pid = nlk->dst_pid; | 1345 | dst_pid = nlk->dst_pid; |
| 1305 | dst_group = nlk->dst_group; | 1346 | dst_group = nlk->dst_group; |
| @@ -1351,6 +1392,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1351 | err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); | 1392 | err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); |
| 1352 | 1393 | ||
| 1353 | out: | 1394 | out: |
| 1395 | scm_destroy(siocb->scm); | ||
| 1354 | return err; | 1396 | return err; |
| 1355 | } | 1397 | } |
| 1356 | 1398 | ||
| @@ -1364,7 +1406,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1364 | struct netlink_sock *nlk = nlk_sk(sk); | 1406 | struct netlink_sock *nlk = nlk_sk(sk); |
| 1365 | int noblock = flags&MSG_DONTWAIT; | 1407 | int noblock = flags&MSG_DONTWAIT; |
| 1366 | size_t copied; | 1408 | size_t copied; |
| 1367 | struct sk_buff *skb, *frag __maybe_unused = NULL; | 1409 | struct sk_buff *skb, *data_skb; |
| 1368 | int err; | 1410 | int err; |
| 1369 | 1411 | ||
| 1370 | if (flags&MSG_OOB) | 1412 | if (flags&MSG_OOB) |
| @@ -1376,45 +1418,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1376 | if (skb == NULL) | 1418 | if (skb == NULL) |
| 1377 | goto out; | 1419 | goto out; |
| 1378 | 1420 | ||
| 1421 | data_skb = skb; | ||
| 1422 | |||
| 1379 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES | 1423 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES |
| 1380 | if (unlikely(skb_shinfo(skb)->frag_list)) { | 1424 | if (unlikely(skb_shinfo(skb)->frag_list)) { |
| 1381 | bool need_compat = !!(flags & MSG_CMSG_COMPAT); | ||
| 1382 | |||
| 1383 | /* | 1425 | /* |
| 1384 | * If this skb has a frag_list, then here that means that | 1426 | * If this skb has a frag_list, then here that means that we |
| 1385 | * we will have to use the frag_list skb for compat tasks | 1427 | * will have to use the frag_list skb's data for compat tasks |
| 1386 | * and the regular skb for non-compat tasks. | 1428 | * and the regular skb's data for normal (non-compat) tasks. |
| 1387 | * | 1429 | * |
| 1388 | * The skb might (and likely will) be cloned, so we can't | 1430 | * If we need to send the compat skb, assign it to the |
| 1389 | * just reset frag_list and go on with things -- we need to | 1431 | * 'data_skb' variable so that it will be used below for data |
| 1390 | * keep that. For the compat case that's easy -- simply get | 1432 | * copying. We keep 'skb' for everything else, including |
| 1391 | * a reference to the compat skb and free the regular one | 1433 | * freeing both later. |
| 1392 | * including the frag. For the non-compat case, we need to | ||
| 1393 | * avoid sending the frag to the user -- so assign NULL but | ||
| 1394 | * restore it below before freeing the skb. | ||
| 1395 | */ | 1434 | */ |
| 1396 | if (need_compat) { | 1435 | if (flags & MSG_CMSG_COMPAT) |
| 1397 | struct sk_buff *compskb = skb_shinfo(skb)->frag_list; | 1436 | data_skb = skb_shinfo(skb)->frag_list; |
| 1398 | skb_get(compskb); | ||
| 1399 | kfree_skb(skb); | ||
| 1400 | skb = compskb; | ||
| 1401 | } else { | ||
| 1402 | frag = skb_shinfo(skb)->frag_list; | ||
| 1403 | skb_shinfo(skb)->frag_list = NULL; | ||
| 1404 | } | ||
| 1405 | } | 1437 | } |
| 1406 | #endif | 1438 | #endif |
| 1407 | 1439 | ||
| 1408 | msg->msg_namelen = 0; | 1440 | msg->msg_namelen = 0; |
| 1409 | 1441 | ||
| 1410 | copied = skb->len; | 1442 | copied = data_skb->len; |
| 1411 | if (len < copied) { | 1443 | if (len < copied) { |
| 1412 | msg->msg_flags |= MSG_TRUNC; | 1444 | msg->msg_flags |= MSG_TRUNC; |
| 1413 | copied = len; | 1445 | copied = len; |
| 1414 | } | 1446 | } |
| 1415 | 1447 | ||
| 1416 | skb_reset_transport_header(skb); | 1448 | skb_reset_transport_header(data_skb); |
| 1417 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 1449 | err = skb_copy_datagram_iovec(data_skb, 0, msg->msg_iov, copied); |
| 1418 | 1450 | ||
| 1419 | if (msg->msg_name) { | 1451 | if (msg->msg_name) { |
| 1420 | struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; | 1452 | struct sockaddr_nl *addr = (struct sockaddr_nl *)msg->msg_name; |
| @@ -1434,11 +1466,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1434 | } | 1466 | } |
| 1435 | siocb->scm->creds = *NETLINK_CREDS(skb); | 1467 | siocb->scm->creds = *NETLINK_CREDS(skb); |
| 1436 | if (flags & MSG_TRUNC) | 1468 | if (flags & MSG_TRUNC) |
| 1437 | copied = skb->len; | 1469 | copied = data_skb->len; |
| 1438 | |||
| 1439 | #ifdef CONFIG_COMPAT_NETLINK_MESSAGES | ||
| 1440 | skb_shinfo(skb)->frag_list = frag; | ||
| 1441 | #endif | ||
| 1442 | 1470 | ||
| 1443 | skb_free_datagram(sk, skb); | 1471 | skb_free_datagram(sk, skb); |
| 1444 | 1472 | ||
| @@ -1973,12 +2001,12 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
| 1973 | if (v == SEQ_START_TOKEN) | 2001 | if (v == SEQ_START_TOKEN) |
| 1974 | seq_puts(seq, | 2002 | seq_puts(seq, |
| 1975 | "sk Eth Pid Groups " | 2003 | "sk Eth Pid Groups " |
| 1976 | "Rmem Wmem Dump Locks Drops\n"); | 2004 | "Rmem Wmem Dump Locks Drops Inode\n"); |
| 1977 | else { | 2005 | else { |
| 1978 | struct sock *s = v; | 2006 | struct sock *s = v; |
| 1979 | struct netlink_sock *nlk = nlk_sk(s); | 2007 | struct netlink_sock *nlk = nlk_sk(s); |
| 1980 | 2008 | ||
| 1981 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d\n", | 2009 | seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %-8d %-8d %-8lu\n", |
| 1982 | s, | 2010 | s, |
| 1983 | s->sk_protocol, | 2011 | s->sk_protocol, |
| 1984 | nlk->pid, | 2012 | nlk->pid, |
| @@ -1987,7 +2015,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
| 1987 | sk_wmem_alloc_get(s), | 2015 | sk_wmem_alloc_get(s), |
| 1988 | nlk->cb, | 2016 | nlk->cb, |
| 1989 | atomic_read(&s->sk_refcnt), | 2017 | atomic_read(&s->sk_refcnt), |
| 1990 | atomic_read(&s->sk_drops) | 2018 | atomic_read(&s->sk_drops), |
| 2019 | sock_i_ino(s) | ||
| 1991 | ); | 2020 | ); |
| 1992 | 2021 | ||
| 1993 | } | 2022 | } |
| @@ -2073,6 +2102,26 @@ static void __net_exit netlink_net_exit(struct net *net) | |||
| 2073 | #endif | 2102 | #endif |
| 2074 | } | 2103 | } |
| 2075 | 2104 | ||
| 2105 | static void __init netlink_add_usersock_entry(void) | ||
| 2106 | { | ||
| 2107 | unsigned long *listeners; | ||
| 2108 | int groups = 32; | ||
| 2109 | |||
| 2110 | listeners = kzalloc(NLGRPSZ(groups) + sizeof(struct listeners_rcu_head), | ||
| 2111 | GFP_KERNEL); | ||
| 2112 | if (!listeners) | ||
| 2113 | panic("netlink_add_usersock_entry: Cannot allocate listneres\n"); | ||
| 2114 | |||
| 2115 | netlink_table_grab(); | ||
| 2116 | |||
| 2117 | nl_table[NETLINK_USERSOCK].groups = groups; | ||
| 2118 | nl_table[NETLINK_USERSOCK].listeners = listeners; | ||
| 2119 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; | ||
| 2120 | nl_table[NETLINK_USERSOCK].registered = 1; | ||
| 2121 | |||
| 2122 | netlink_table_ungrab(); | ||
| 2123 | } | ||
| 2124 | |||
| 2076 | static struct pernet_operations __net_initdata netlink_net_ops = { | 2125 | static struct pernet_operations __net_initdata netlink_net_ops = { |
| 2077 | .init = netlink_net_init, | 2126 | .init = netlink_net_init, |
| 2078 | .exit = netlink_net_exit, | 2127 | .exit = netlink_net_exit, |
| @@ -2121,6 +2170,8 @@ static int __init netlink_proto_init(void) | |||
| 2121 | hash->rehash_time = jiffies; | 2170 | hash->rehash_time = jiffies; |
| 2122 | } | 2171 | } |
| 2123 | 2172 | ||
| 2173 | netlink_add_usersock_entry(); | ||
| 2174 | |||
| 2124 | sock_register(&netlink_family_ops); | 2175 | sock_register(&netlink_family_ops); |
| 2125 | register_pernet_subsys(&netlink_net_ops); | 2176 | register_pernet_subsys(&netlink_net_ops); |
| 2126 | /* The netlink device handler may be needed early. */ | 2177 | /* The netlink device handler may be needed early. */ |
