diff options
author | Simon Horman <horms@verge.net.au> | 2008-10-06 17:40:11 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2008-10-06 17:40:11 -0400 |
commit | a5e8546a8bff5d2047adc279df5753c44ba7b1a1 (patch) | |
tree | d9ca91f74d8279adbb1d3e942cc7ab145780ee29 /net | |
parent | cb7f6a7b716e801097b564dec3ccb58d330aef56 (diff) | |
parent | c7004482e8dcb7c3c72666395cfa98a216a4fb70 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6 into lvs-next-2.6
Diffstat (limited to 'net')
88 files changed, 4637 insertions, 1180 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 2ffe40cf2f01..10e320307ec0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -75,7 +75,6 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
75 | int option; | 75 | int option; |
76 | int ret = 0; | 76 | int ret = 0; |
77 | 77 | ||
78 | clnt->trans_mod = v9fs_default_trans(); | ||
79 | clnt->dotu = 1; | 78 | clnt->dotu = 1; |
80 | clnt->msize = 8192; | 79 | clnt->msize = 8192; |
81 | 80 | ||
@@ -108,7 +107,7 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
108 | clnt->msize = option; | 107 | clnt->msize = option; |
109 | break; | 108 | break; |
110 | case Opt_trans: | 109 | case Opt_trans: |
111 | clnt->trans_mod = v9fs_match_trans(&args[0]); | 110 | clnt->trans_mod = v9fs_get_trans_by_name(&args[0]); |
112 | break; | 111 | break; |
113 | case Opt_legacy: | 112 | case Opt_legacy: |
114 | clnt->dotu = 0; | 113 | clnt->dotu = 0; |
@@ -117,6 +116,10 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
117 | continue; | 116 | continue; |
118 | } | 117 | } |
119 | } | 118 | } |
119 | |||
120 | if (!clnt->trans_mod) | ||
121 | clnt->trans_mod = v9fs_get_default_trans(); | ||
122 | |||
120 | kfree(options); | 123 | kfree(options); |
121 | return ret; | 124 | return ret; |
122 | } | 125 | } |
@@ -150,6 +153,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
150 | if (!clnt) | 153 | if (!clnt) |
151 | return ERR_PTR(-ENOMEM); | 154 | return ERR_PTR(-ENOMEM); |
152 | 155 | ||
156 | clnt->trans_mod = NULL; | ||
153 | clnt->trans = NULL; | 157 | clnt->trans = NULL; |
154 | spin_lock_init(&clnt->lock); | 158 | spin_lock_init(&clnt->lock); |
155 | INIT_LIST_HEAD(&clnt->fidlist); | 159 | INIT_LIST_HEAD(&clnt->fidlist); |
@@ -235,6 +239,8 @@ void p9_client_destroy(struct p9_client *clnt) | |||
235 | clnt->trans = NULL; | 239 | clnt->trans = NULL; |
236 | } | 240 | } |
237 | 241 | ||
242 | v9fs_put_trans(clnt->trans_mod); | ||
243 | |||
238 | list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) | 244 | list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) |
239 | p9_fid_destroy(fid); | 245 | p9_fid_destroy(fid); |
240 | 246 | ||
diff --git a/net/9p/conv.c b/net/9p/conv.c index 44547201f5bc..5ad3a3bd73b2 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c | |||
@@ -451,8 +451,10 @@ p9_put_data(struct cbuf *bufp, const char *data, int count, | |||
451 | unsigned char **pdata) | 451 | unsigned char **pdata) |
452 | { | 452 | { |
453 | *pdata = buf_alloc(bufp, count); | 453 | *pdata = buf_alloc(bufp, count); |
454 | if (*pdata == NULL) | ||
455 | return -ENOMEM; | ||
454 | memmove(*pdata, data, count); | 456 | memmove(*pdata, data, count); |
455 | return count; | 457 | return 0; |
456 | } | 458 | } |
457 | 459 | ||
458 | static int | 460 | static int |
@@ -460,6 +462,8 @@ p9_put_user_data(struct cbuf *bufp, const char __user *data, int count, | |||
460 | unsigned char **pdata) | 462 | unsigned char **pdata) |
461 | { | 463 | { |
462 | *pdata = buf_alloc(bufp, count); | 464 | *pdata = buf_alloc(bufp, count); |
465 | if (*pdata == NULL) | ||
466 | return -ENOMEM; | ||
463 | return copy_from_user(*pdata, data, count); | 467 | return copy_from_user(*pdata, data, count); |
464 | } | 468 | } |
465 | 469 | ||
diff --git a/net/9p/mod.c b/net/9p/mod.c index bdee1fb7cc62..1084feb24cb0 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/parser.h> | 31 | #include <linux/parser.h> |
32 | #include <net/9p/transport.h> | 32 | #include <net/9p/transport.h> |
33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
34 | #include <linux/spinlock.h> | ||
34 | 35 | ||
35 | #ifdef CONFIG_NET_9P_DEBUG | 36 | #ifdef CONFIG_NET_9P_DEBUG |
36 | unsigned int p9_debug_level = 0; /* feature-rific global debug level */ | 37 | unsigned int p9_debug_level = 0; /* feature-rific global debug level */ |
@@ -44,8 +45,8 @@ MODULE_PARM_DESC(debug, "9P debugging level"); | |||
44 | * | 45 | * |
45 | */ | 46 | */ |
46 | 47 | ||
48 | static DEFINE_SPINLOCK(v9fs_trans_lock); | ||
47 | static LIST_HEAD(v9fs_trans_list); | 49 | static LIST_HEAD(v9fs_trans_list); |
48 | static struct p9_trans_module *v9fs_default_transport; | ||
49 | 50 | ||
50 | /** | 51 | /** |
51 | * v9fs_register_trans - register a new transport with 9p | 52 | * v9fs_register_trans - register a new transport with 9p |
@@ -54,48 +55,87 @@ static struct p9_trans_module *v9fs_default_transport; | |||
54 | */ | 55 | */ |
55 | void v9fs_register_trans(struct p9_trans_module *m) | 56 | void v9fs_register_trans(struct p9_trans_module *m) |
56 | { | 57 | { |
58 | spin_lock(&v9fs_trans_lock); | ||
57 | list_add_tail(&m->list, &v9fs_trans_list); | 59 | list_add_tail(&m->list, &v9fs_trans_list); |
58 | if (m->def) | 60 | spin_unlock(&v9fs_trans_lock); |
59 | v9fs_default_transport = m; | ||
60 | } | 61 | } |
61 | EXPORT_SYMBOL(v9fs_register_trans); | 62 | EXPORT_SYMBOL(v9fs_register_trans); |
62 | 63 | ||
63 | /** | 64 | /** |
64 | * v9fs_match_trans - match transport versus registered transports | 65 | * v9fs_unregister_trans - unregister a 9p transport |
66 | * @m: the transport to remove | ||
67 | * | ||
68 | */ | ||
69 | void v9fs_unregister_trans(struct p9_trans_module *m) | ||
70 | { | ||
71 | spin_lock(&v9fs_trans_lock); | ||
72 | list_del_init(&m->list); | ||
73 | spin_unlock(&v9fs_trans_lock); | ||
74 | } | ||
75 | EXPORT_SYMBOL(v9fs_unregister_trans); | ||
76 | |||
77 | /** | ||
78 | * v9fs_get_trans_by_name - get transport with the matching name | ||
65 | * @name: string identifying transport | 79 | * @name: string identifying transport |
66 | * | 80 | * |
67 | */ | 81 | */ |
68 | struct p9_trans_module *v9fs_match_trans(const substring_t *name) | 82 | struct p9_trans_module *v9fs_get_trans_by_name(const substring_t *name) |
69 | { | 83 | { |
70 | struct list_head *p; | 84 | struct p9_trans_module *t, *found = NULL; |
71 | struct p9_trans_module *t = NULL; | 85 | |
72 | 86 | spin_lock(&v9fs_trans_lock); | |
73 | list_for_each(p, &v9fs_trans_list) { | 87 | |
74 | t = list_entry(p, struct p9_trans_module, list); | 88 | list_for_each_entry(t, &v9fs_trans_list, list) |
75 | if (strncmp(t->name, name->from, name->to-name->from) == 0) | 89 | if (strncmp(t->name, name->from, name->to-name->from) == 0 && |
76 | return t; | 90 | try_module_get(t->owner)) { |
77 | } | 91 | found = t; |
78 | return NULL; | 92 | break; |
93 | } | ||
94 | |||
95 | spin_unlock(&v9fs_trans_lock); | ||
96 | return found; | ||
79 | } | 97 | } |
80 | EXPORT_SYMBOL(v9fs_match_trans); | 98 | EXPORT_SYMBOL(v9fs_get_trans_by_name); |
81 | 99 | ||
82 | /** | 100 | /** |
83 | * v9fs_default_trans - returns pointer to default transport | 101 | * v9fs_get_default_trans - get the default transport |
84 | * | 102 | * |
85 | */ | 103 | */ |
86 | 104 | ||
87 | struct p9_trans_module *v9fs_default_trans(void) | 105 | struct p9_trans_module *v9fs_get_default_trans(void) |
88 | { | 106 | { |
89 | if (v9fs_default_transport) | 107 | struct p9_trans_module *t, *found = NULL; |
90 | return v9fs_default_transport; | 108 | |
91 | else if (!list_empty(&v9fs_trans_list)) | 109 | spin_lock(&v9fs_trans_lock); |
92 | return list_first_entry(&v9fs_trans_list, | 110 | |
93 | struct p9_trans_module, list); | 111 | list_for_each_entry(t, &v9fs_trans_list, list) |
94 | else | 112 | if (t->def && try_module_get(t->owner)) { |
95 | return NULL; | 113 | found = t; |
114 | break; | ||
115 | } | ||
116 | |||
117 | if (!found) | ||
118 | list_for_each_entry(t, &v9fs_trans_list, list) | ||
119 | if (try_module_get(t->owner)) { | ||
120 | found = t; | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | spin_unlock(&v9fs_trans_lock); | ||
125 | return found; | ||
96 | } | 126 | } |
97 | EXPORT_SYMBOL(v9fs_default_trans); | 127 | EXPORT_SYMBOL(v9fs_get_default_trans); |
98 | 128 | ||
129 | /** | ||
130 | * v9fs_put_trans - put trans | ||
131 | * @m: transport to put | ||
132 | * | ||
133 | */ | ||
134 | void v9fs_put_trans(struct p9_trans_module *m) | ||
135 | { | ||
136 | if (m) | ||
137 | module_put(m->owner); | ||
138 | } | ||
99 | 139 | ||
100 | /** | 140 | /** |
101 | * v9fs_init - Initialize module | 141 | * v9fs_init - Initialize module |
@@ -120,6 +160,8 @@ static int __init init_p9(void) | |||
120 | static void __exit exit_p9(void) | 160 | static void __exit exit_p9(void) |
121 | { | 161 | { |
122 | printk(KERN_INFO "Unloading 9P2000 support\n"); | 162 | printk(KERN_INFO "Unloading 9P2000 support\n"); |
163 | |||
164 | p9_trans_fd_exit(); | ||
123 | } | 165 | } |
124 | 166 | ||
125 | module_init(init_p9) | 167 | module_init(init_p9) |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index cdf137af7adc..d652baf5ff91 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -151,7 +151,6 @@ struct p9_mux_poll_task { | |||
151 | * @trans: reference to transport instance for this connection | 151 | * @trans: reference to transport instance for this connection |
152 | * @tagpool: id accounting for transactions | 152 | * @tagpool: id accounting for transactions |
153 | * @err: error state | 153 | * @err: error state |
154 | * @equeue: event wait_q (?) | ||
155 | * @req_list: accounting for requests which have been sent | 154 | * @req_list: accounting for requests which have been sent |
156 | * @unsent_req_list: accounting for requests that haven't been sent | 155 | * @unsent_req_list: accounting for requests that haven't been sent |
157 | * @rcall: current response &p9_fcall structure | 156 | * @rcall: current response &p9_fcall structure |
@@ -178,7 +177,6 @@ struct p9_conn { | |||
178 | struct p9_trans *trans; | 177 | struct p9_trans *trans; |
179 | struct p9_idpool *tagpool; | 178 | struct p9_idpool *tagpool; |
180 | int err; | 179 | int err; |
181 | wait_queue_head_t equeue; | ||
182 | struct list_head req_list; | 180 | struct list_head req_list; |
183 | struct list_head unsent_req_list; | 181 | struct list_head unsent_req_list; |
184 | struct p9_fcall *rcall; | 182 | struct p9_fcall *rcall; |
@@ -240,22 +238,6 @@ static int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, | |||
240 | 238 | ||
241 | static void p9_conn_cancel(struct p9_conn *m, int err); | 239 | static void p9_conn_cancel(struct p9_conn *m, int err); |
242 | 240 | ||
243 | static int p9_mux_global_init(void) | ||
244 | { | ||
245 | int i; | ||
246 | |||
247 | for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) | ||
248 | p9_mux_poll_tasks[i].task = NULL; | ||
249 | |||
250 | p9_mux_wq = create_workqueue("v9fs"); | ||
251 | if (!p9_mux_wq) { | ||
252 | printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); | ||
253 | return -ENOMEM; | ||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static u16 p9_mux_get_tag(struct p9_conn *m) | 241 | static u16 p9_mux_get_tag(struct p9_conn *m) |
260 | { | 242 | { |
261 | int tag; | 243 | int tag; |
@@ -409,11 +391,11 @@ static void p9_mux_poll_stop(struct p9_conn *m) | |||
409 | static struct p9_conn *p9_conn_create(struct p9_trans *trans) | 391 | static struct p9_conn *p9_conn_create(struct p9_trans *trans) |
410 | { | 392 | { |
411 | int i, n; | 393 | int i, n; |
412 | struct p9_conn *m, *mtmp; | 394 | struct p9_conn *m; |
413 | 395 | ||
414 | P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, | 396 | P9_DPRINTK(P9_DEBUG_MUX, "transport %p msize %d\n", trans, |
415 | trans->msize); | 397 | trans->msize); |
416 | m = kmalloc(sizeof(struct p9_conn), GFP_KERNEL); | 398 | m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); |
417 | if (!m) | 399 | if (!m) |
418 | return ERR_PTR(-ENOMEM); | 400 | return ERR_PTR(-ENOMEM); |
419 | 401 | ||
@@ -424,25 +406,14 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) | |||
424 | m->trans = trans; | 406 | m->trans = trans; |
425 | m->tagpool = p9_idpool_create(); | 407 | m->tagpool = p9_idpool_create(); |
426 | if (IS_ERR(m->tagpool)) { | 408 | if (IS_ERR(m->tagpool)) { |
427 | mtmp = ERR_PTR(-ENOMEM); | ||
428 | kfree(m); | 409 | kfree(m); |
429 | return mtmp; | 410 | return ERR_PTR(-ENOMEM); |
430 | } | 411 | } |
431 | 412 | ||
432 | m->err = 0; | ||
433 | init_waitqueue_head(&m->equeue); | ||
434 | INIT_LIST_HEAD(&m->req_list); | 413 | INIT_LIST_HEAD(&m->req_list); |
435 | INIT_LIST_HEAD(&m->unsent_req_list); | 414 | INIT_LIST_HEAD(&m->unsent_req_list); |
436 | m->rcall = NULL; | ||
437 | m->rpos = 0; | ||
438 | m->rbuf = NULL; | ||
439 | m->wpos = m->wsize = 0; | ||
440 | m->wbuf = NULL; | ||
441 | INIT_WORK(&m->rq, p9_read_work); | 415 | INIT_WORK(&m->rq, p9_read_work); |
442 | INIT_WORK(&m->wq, p9_write_work); | 416 | INIT_WORK(&m->wq, p9_write_work); |
443 | m->wsched = 0; | ||
444 | memset(&m->poll_waddr, 0, sizeof(m->poll_waddr)); | ||
445 | m->poll_task = NULL; | ||
446 | n = p9_mux_poll_start(m); | 417 | n = p9_mux_poll_start(m); |
447 | if (n) { | 418 | if (n) { |
448 | kfree(m); | 419 | kfree(m); |
@@ -463,10 +434,8 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) | |||
463 | for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { | 434 | for (i = 0; i < ARRAY_SIZE(m->poll_waddr); i++) { |
464 | if (IS_ERR(m->poll_waddr[i])) { | 435 | if (IS_ERR(m->poll_waddr[i])) { |
465 | p9_mux_poll_stop(m); | 436 | p9_mux_poll_stop(m); |
466 | mtmp = (void *)m->poll_waddr; /* the error code */ | ||
467 | kfree(m); | 437 | kfree(m); |
468 | m = mtmp; | 438 | return (void *)m->poll_waddr; /* the error code */ |
469 | break; | ||
470 | } | 439 | } |
471 | } | 440 | } |
472 | 441 | ||
@@ -483,18 +452,13 @@ static void p9_conn_destroy(struct p9_conn *m) | |||
483 | { | 452 | { |
484 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, | 453 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, |
485 | m->mux_list.prev, m->mux_list.next); | 454 | m->mux_list.prev, m->mux_list.next); |
486 | p9_conn_cancel(m, -ECONNRESET); | ||
487 | |||
488 | if (!list_empty(&m->req_list)) { | ||
489 | /* wait until all processes waiting on this session exit */ | ||
490 | P9_DPRINTK(P9_DEBUG_MUX, | ||
491 | "mux %p waiting for empty request queue\n", m); | ||
492 | wait_event_timeout(m->equeue, (list_empty(&m->req_list)), 5000); | ||
493 | P9_DPRINTK(P9_DEBUG_MUX, "mux %p request queue empty: %d\n", m, | ||
494 | list_empty(&m->req_list)); | ||
495 | } | ||
496 | 455 | ||
497 | p9_mux_poll_stop(m); | 456 | p9_mux_poll_stop(m); |
457 | cancel_work_sync(&m->rq); | ||
458 | cancel_work_sync(&m->wq); | ||
459 | |||
460 | p9_conn_cancel(m, -ECONNRESET); | ||
461 | |||
498 | m->trans = NULL; | 462 | m->trans = NULL; |
499 | p9_idpool_destroy(m->tagpool); | 463 | p9_idpool_destroy(m->tagpool); |
500 | kfree(m); | 464 | kfree(m); |
@@ -840,8 +804,6 @@ static void p9_read_work(struct work_struct *work) | |||
840 | (*req->cb) (req, req->cba); | 804 | (*req->cb) (req, req->cba); |
841 | else | 805 | else |
842 | kfree(req->rcall); | 806 | kfree(req->rcall); |
843 | |||
844 | wake_up(&m->equeue); | ||
845 | } | 807 | } |
846 | } else { | 808 | } else { |
847 | if (err >= 0 && rcall->id != P9_RFLUSH) | 809 | if (err >= 0 && rcall->id != P9_RFLUSH) |
@@ -908,8 +870,10 @@ static struct p9_req *p9_send_request(struct p9_conn *m, | |||
908 | else | 870 | else |
909 | n = p9_mux_get_tag(m); | 871 | n = p9_mux_get_tag(m); |
910 | 872 | ||
911 | if (n < 0) | 873 | if (n < 0) { |
874 | kfree(req); | ||
912 | return ERR_PTR(-ENOMEM); | 875 | return ERR_PTR(-ENOMEM); |
876 | } | ||
913 | 877 | ||
914 | p9_set_tag(tc, n); | 878 | p9_set_tag(tc, n); |
915 | 879 | ||
@@ -984,8 +948,6 @@ static void p9_mux_flush_cb(struct p9_req *freq, void *a) | |||
984 | (*req->cb) (req, req->cba); | 948 | (*req->cb) (req, req->cba); |
985 | else | 949 | else |
986 | kfree(req->rcall); | 950 | kfree(req->rcall); |
987 | |||
988 | wake_up(&m->equeue); | ||
989 | } | 951 | } |
990 | 952 | ||
991 | kfree(freq->tcall); | 953 | kfree(freq->tcall); |
@@ -1191,8 +1153,6 @@ void p9_conn_cancel(struct p9_conn *m, int err) | |||
1191 | else | 1153 | else |
1192 | kfree(req->rcall); | 1154 | kfree(req->rcall); |
1193 | } | 1155 | } |
1194 | |||
1195 | wake_up(&m->equeue); | ||
1196 | } | 1156 | } |
1197 | 1157 | ||
1198 | /** | 1158 | /** |
@@ -1370,7 +1330,6 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) | |||
1370 | { | 1330 | { |
1371 | int ret, n; | 1331 | int ret, n; |
1372 | struct p9_trans_fd *ts = NULL; | 1332 | struct p9_trans_fd *ts = NULL; |
1373 | mm_segment_t oldfs; | ||
1374 | 1333 | ||
1375 | if (trans && trans->status == Connected) | 1334 | if (trans && trans->status == Connected) |
1376 | ts = trans->priv; | 1335 | ts = trans->priv; |
@@ -1384,24 +1343,17 @@ p9_fd_poll(struct p9_trans *trans, struct poll_table_struct *pt) | |||
1384 | if (!ts->wr->f_op || !ts->wr->f_op->poll) | 1343 | if (!ts->wr->f_op || !ts->wr->f_op->poll) |
1385 | return -EIO; | 1344 | return -EIO; |
1386 | 1345 | ||
1387 | oldfs = get_fs(); | ||
1388 | set_fs(get_ds()); | ||
1389 | |||
1390 | ret = ts->rd->f_op->poll(ts->rd, pt); | 1346 | ret = ts->rd->f_op->poll(ts->rd, pt); |
1391 | if (ret < 0) | 1347 | if (ret < 0) |
1392 | goto end; | 1348 | return ret; |
1393 | 1349 | ||
1394 | if (ts->rd != ts->wr) { | 1350 | if (ts->rd != ts->wr) { |
1395 | n = ts->wr->f_op->poll(ts->wr, pt); | 1351 | n = ts->wr->f_op->poll(ts->wr, pt); |
1396 | if (n < 0) { | 1352 | if (n < 0) |
1397 | ret = n; | 1353 | return n; |
1398 | goto end; | ||
1399 | } | ||
1400 | ret = (ret & ~POLLOUT) | (n & ~POLLIN); | 1354 | ret = (ret & ~POLLOUT) | (n & ~POLLIN); |
1401 | } | 1355 | } |
1402 | 1356 | ||
1403 | end: | ||
1404 | set_fs(oldfs); | ||
1405 | return ret; | 1357 | return ret; |
1406 | } | 1358 | } |
1407 | 1359 | ||
@@ -1629,6 +1581,7 @@ static struct p9_trans_module p9_tcp_trans = { | |||
1629 | .maxsize = MAX_SOCK_BUF, | 1581 | .maxsize = MAX_SOCK_BUF, |
1630 | .def = 1, | 1582 | .def = 1, |
1631 | .create = p9_trans_create_tcp, | 1583 | .create = p9_trans_create_tcp, |
1584 | .owner = THIS_MODULE, | ||
1632 | }; | 1585 | }; |
1633 | 1586 | ||
1634 | static struct p9_trans_module p9_unix_trans = { | 1587 | static struct p9_trans_module p9_unix_trans = { |
@@ -1636,6 +1589,7 @@ static struct p9_trans_module p9_unix_trans = { | |||
1636 | .maxsize = MAX_SOCK_BUF, | 1589 | .maxsize = MAX_SOCK_BUF, |
1637 | .def = 0, | 1590 | .def = 0, |
1638 | .create = p9_trans_create_unix, | 1591 | .create = p9_trans_create_unix, |
1592 | .owner = THIS_MODULE, | ||
1639 | }; | 1593 | }; |
1640 | 1594 | ||
1641 | static struct p9_trans_module p9_fd_trans = { | 1595 | static struct p9_trans_module p9_fd_trans = { |
@@ -1643,14 +1597,20 @@ static struct p9_trans_module p9_fd_trans = { | |||
1643 | .maxsize = MAX_SOCK_BUF, | 1597 | .maxsize = MAX_SOCK_BUF, |
1644 | .def = 0, | 1598 | .def = 0, |
1645 | .create = p9_trans_create_fd, | 1599 | .create = p9_trans_create_fd, |
1600 | .owner = THIS_MODULE, | ||
1646 | }; | 1601 | }; |
1647 | 1602 | ||
1648 | int p9_trans_fd_init(void) | 1603 | int p9_trans_fd_init(void) |
1649 | { | 1604 | { |
1650 | int ret = p9_mux_global_init(); | 1605 | int i; |
1651 | if (ret) { | 1606 | |
1652 | printk(KERN_WARNING "9p: starting mux failed\n"); | 1607 | for (i = 0; i < ARRAY_SIZE(p9_mux_poll_tasks); i++) |
1653 | return ret; | 1608 | p9_mux_poll_tasks[i].task = NULL; |
1609 | |||
1610 | p9_mux_wq = create_workqueue("v9fs"); | ||
1611 | if (!p9_mux_wq) { | ||
1612 | printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n"); | ||
1613 | return -ENOMEM; | ||
1654 | } | 1614 | } |
1655 | 1615 | ||
1656 | v9fs_register_trans(&p9_tcp_trans); | 1616 | v9fs_register_trans(&p9_tcp_trans); |
@@ -1659,4 +1619,12 @@ int p9_trans_fd_init(void) | |||
1659 | 1619 | ||
1660 | return 0; | 1620 | return 0; |
1661 | } | 1621 | } |
1662 | EXPORT_SYMBOL(p9_trans_fd_init); | 1622 | |
1623 | void p9_trans_fd_exit(void) | ||
1624 | { | ||
1625 | v9fs_unregister_trans(&p9_tcp_trans); | ||
1626 | v9fs_unregister_trans(&p9_unix_trans); | ||
1627 | v9fs_unregister_trans(&p9_fd_trans); | ||
1628 | |||
1629 | destroy_workqueue(p9_mux_wq); | ||
1630 | } | ||
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 42adc052b149..94912e077a55 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -528,6 +528,7 @@ static struct p9_trans_module p9_virtio_trans = { | |||
528 | .create = p9_virtio_create, | 528 | .create = p9_virtio_create, |
529 | .maxsize = PAGE_SIZE*16, | 529 | .maxsize = PAGE_SIZE*16, |
530 | .def = 0, | 530 | .def = 0, |
531 | .owner = THIS_MODULE, | ||
531 | }; | 532 | }; |
532 | 533 | ||
533 | /* The standard init function */ | 534 | /* The standard init function */ |
@@ -545,6 +546,7 @@ static int __init p9_virtio_init(void) | |||
545 | static void __exit p9_virtio_cleanup(void) | 546 | static void __exit p9_virtio_cleanup(void) |
546 | { | 547 | { |
547 | unregister_virtio_driver(&p9_virtio_drv); | 548 | unregister_virtio_driver(&p9_virtio_drv); |
549 | v9fs_unregister_trans(&p9_virtio_trans); | ||
548 | } | 550 | } |
549 | 551 | ||
550 | module_init(p9_virtio_init); | 552 | module_init(p9_virtio_init); |
diff --git a/net/Kconfig b/net/Kconfig index d87de48ba656..9103a16a77be 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -232,6 +232,7 @@ source "net/can/Kconfig" | |||
232 | source "net/irda/Kconfig" | 232 | source "net/irda/Kconfig" |
233 | source "net/bluetooth/Kconfig" | 233 | source "net/bluetooth/Kconfig" |
234 | source "net/rxrpc/Kconfig" | 234 | source "net/rxrpc/Kconfig" |
235 | source "net/phonet/Kconfig" | ||
235 | 236 | ||
236 | config FIB_RULES | 237 | config FIB_RULES |
237 | bool | 238 | bool |
diff --git a/net/Makefile b/net/Makefile index 4f43e7f874f3..acaf819f24aa 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_AF_RXRPC) += rxrpc/ | |||
42 | obj-$(CONFIG_ATM) += atm/ | 42 | obj-$(CONFIG_ATM) += atm/ |
43 | obj-$(CONFIG_DECNET) += decnet/ | 43 | obj-$(CONFIG_DECNET) += decnet/ |
44 | obj-$(CONFIG_ECONET) += econet/ | 44 | obj-$(CONFIG_ECONET) += econet/ |
45 | obj-$(CONFIG_PHONET) += phonet/ | ||
45 | ifneq ($(CONFIG_VLAN_8021Q),) | 46 | ifneq ($(CONFIG_VLAN_8021Q),) |
46 | obj-y += 8021q/ | 47 | obj-y += 8021q/ |
47 | endif | 48 | endif |
diff --git a/net/atm/lec.c b/net/atm/lec.c index 5799fb52365a..8f701cde5945 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -1931,7 +1931,6 @@ static struct atm_vcc *lec_arp_resolve(struct lec_priv *priv, | |||
1931 | switch (priv->lane_version) { | 1931 | switch (priv->lane_version) { |
1932 | case 1: | 1932 | case 1: |
1933 | return priv->mcast_vcc; | 1933 | return priv->mcast_vcc; |
1934 | break; | ||
1935 | case 2: /* LANE2 wants arp for multicast addresses */ | 1934 | case 2: /* LANE2 wants arp for multicast addresses */ |
1936 | if (!compare_ether_addr(mac_to_find, bus_mac)) | 1935 | if (!compare_ether_addr(mac_to_find, bus_mac)) |
1937 | return priv->mcast_vcc; | 1936 | return priv->mcast_vcc; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f5b21cb93699..278a3ace14f6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -164,6 +164,9 @@ static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev * | |||
164 | { | 164 | { |
165 | int ret; | 165 | int ret; |
166 | 166 | ||
167 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
168 | return -ENETDOWN; | ||
169 | |||
167 | /* Serialize all requests */ | 170 | /* Serialize all requests */ |
168 | hci_req_lock(hdev); | 171 | hci_req_lock(hdev); |
169 | ret = __hci_request(hdev, req, opt, timeout); | 172 | ret = __hci_request(hdev, req, opt, timeout); |
diff --git a/net/core/dev.c b/net/core/dev.c index fdfc4b6a6448..7091040e32ac 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -122,6 +122,7 @@ | |||
122 | #include <linux/if_arp.h> | 122 | #include <linux/if_arp.h> |
123 | #include <linux/if_vlan.h> | 123 | #include <linux/if_vlan.h> |
124 | #include <linux/ip.h> | 124 | #include <linux/ip.h> |
125 | #include <net/ip.h> | ||
125 | #include <linux/ipv6.h> | 126 | #include <linux/ipv6.h> |
126 | #include <linux/in.h> | 127 | #include <linux/in.h> |
127 | #include <linux/jhash.h> | 128 | #include <linux/jhash.h> |
@@ -890,7 +891,7 @@ int dev_alloc_name(struct net_device *dev, const char *name) | |||
890 | * Change name of a device, can pass format strings "eth%d". | 891 | * Change name of a device, can pass format strings "eth%d". |
891 | * for wildcarding. | 892 | * for wildcarding. |
892 | */ | 893 | */ |
893 | int dev_change_name(struct net_device *dev, char *newname) | 894 | int dev_change_name(struct net_device *dev, const char *newname) |
894 | { | 895 | { |
895 | char oldname[IFNAMSIZ]; | 896 | char oldname[IFNAMSIZ]; |
896 | int err = 0; | 897 | int err = 0; |
@@ -916,7 +917,6 @@ int dev_change_name(struct net_device *dev, char *newname) | |||
916 | err = dev_alloc_name(dev, newname); | 917 | err = dev_alloc_name(dev, newname); |
917 | if (err < 0) | 918 | if (err < 0) |
918 | return err; | 919 | return err; |
919 | strcpy(newname, dev->name); | ||
920 | } | 920 | } |
921 | else if (__dev_get_by_name(net, newname)) | 921 | else if (__dev_get_by_name(net, newname)) |
922 | return -EEXIST; | 922 | return -EEXIST; |
@@ -954,6 +954,38 @@ rollback: | |||
954 | } | 954 | } |
955 | 955 | ||
956 | /** | 956 | /** |
957 | * dev_set_alias - change ifalias of a device | ||
958 | * @dev: device | ||
959 | * @alias: name up to IFALIASZ | ||
960 | * @len: limit of bytes to copy from info | ||
961 | * | ||
962 | * Set ifalias for a device, | ||
963 | */ | ||
964 | int dev_set_alias(struct net_device *dev, const char *alias, size_t len) | ||
965 | { | ||
966 | ASSERT_RTNL(); | ||
967 | |||
968 | if (len >= IFALIASZ) | ||
969 | return -EINVAL; | ||
970 | |||
971 | if (!len) { | ||
972 | if (dev->ifalias) { | ||
973 | kfree(dev->ifalias); | ||
974 | dev->ifalias = NULL; | ||
975 | } | ||
976 | return 0; | ||
977 | } | ||
978 | |||
979 | dev->ifalias = krealloc(dev->ifalias, len+1, GFP_KERNEL); | ||
980 | if (!dev->ifalias) | ||
981 | return -ENOMEM; | ||
982 | |||
983 | strlcpy(dev->ifalias, alias, len+1); | ||
984 | return len; | ||
985 | } | ||
986 | |||
987 | |||
988 | /** | ||
957 | * netdev_features_change - device changes features | 989 | * netdev_features_change - device changes features |
958 | * @dev: device to cause notification | 990 | * @dev: device to cause notification |
959 | * | 991 | * |
@@ -1667,7 +1699,7 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) | |||
1667 | { | 1699 | { |
1668 | u32 addr1, addr2, ports; | 1700 | u32 addr1, addr2, ports; |
1669 | u32 hash, ihl; | 1701 | u32 hash, ihl; |
1670 | u8 ip_proto; | 1702 | u8 ip_proto = 0; |
1671 | 1703 | ||
1672 | if (unlikely(!simple_tx_hashrnd_initialized)) { | 1704 | if (unlikely(!simple_tx_hashrnd_initialized)) { |
1673 | get_random_bytes(&simple_tx_hashrnd, 4); | 1705 | get_random_bytes(&simple_tx_hashrnd, 4); |
@@ -1676,7 +1708,8 @@ static u16 simple_tx_hash(struct net_device *dev, struct sk_buff *skb) | |||
1676 | 1708 | ||
1677 | switch (skb->protocol) { | 1709 | switch (skb->protocol) { |
1678 | case htons(ETH_P_IP): | 1710 | case htons(ETH_P_IP): |
1679 | ip_proto = ip_hdr(skb)->protocol; | 1711 | if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET))) |
1712 | ip_proto = ip_hdr(skb)->protocol; | ||
1680 | addr1 = ip_hdr(skb)->saddr; | 1713 | addr1 = ip_hdr(skb)->saddr; |
1681 | addr2 = ip_hdr(skb)->daddr; | 1714 | addr2 = ip_hdr(skb)->daddr; |
1682 | ihl = ip_hdr(skb)->ihl; | 1715 | ihl = ip_hdr(skb)->ihl; |
@@ -3300,6 +3333,12 @@ static void dev_addr_discard(struct net_device *dev) | |||
3300 | netif_addr_unlock_bh(dev); | 3333 | netif_addr_unlock_bh(dev); |
3301 | } | 3334 | } |
3302 | 3335 | ||
3336 | /** | ||
3337 | * dev_get_flags - get flags reported to userspace | ||
3338 | * @dev: device | ||
3339 | * | ||
3340 | * Get the combination of flag bits exported through APIs to userspace. | ||
3341 | */ | ||
3303 | unsigned dev_get_flags(const struct net_device *dev) | 3342 | unsigned dev_get_flags(const struct net_device *dev) |
3304 | { | 3343 | { |
3305 | unsigned flags; | 3344 | unsigned flags; |
@@ -3324,6 +3363,14 @@ unsigned dev_get_flags(const struct net_device *dev) | |||
3324 | return flags; | 3363 | return flags; |
3325 | } | 3364 | } |
3326 | 3365 | ||
3366 | /** | ||
3367 | * dev_change_flags - change device settings | ||
3368 | * @dev: device | ||
3369 | * @flags: device state flags | ||
3370 | * | ||
3371 | * Change settings on device based state flags. The flags are | ||
3372 | * in the userspace exported format. | ||
3373 | */ | ||
3327 | int dev_change_flags(struct net_device *dev, unsigned flags) | 3374 | int dev_change_flags(struct net_device *dev, unsigned flags) |
3328 | { | 3375 | { |
3329 | int ret, changes; | 3376 | int ret, changes; |
@@ -3393,6 +3440,13 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
3393 | return ret; | 3440 | return ret; |
3394 | } | 3441 | } |
3395 | 3442 | ||
3443 | /** | ||
3444 | * dev_set_mtu - Change maximum transfer unit | ||
3445 | * @dev: device | ||
3446 | * @new_mtu: new transfer unit | ||
3447 | * | ||
3448 | * Change the maximum transfer size of the network device. | ||
3449 | */ | ||
3396 | int dev_set_mtu(struct net_device *dev, int new_mtu) | 3450 | int dev_set_mtu(struct net_device *dev, int new_mtu) |
3397 | { | 3451 | { |
3398 | int err; | 3452 | int err; |
@@ -3417,6 +3471,13 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) | |||
3417 | return err; | 3471 | return err; |
3418 | } | 3472 | } |
3419 | 3473 | ||
3474 | /** | ||
3475 | * dev_set_mac_address - Change Media Access Control Address | ||
3476 | * @dev: device | ||
3477 | * @sa: new address | ||
3478 | * | ||
3479 | * Change the hardware (MAC) address of the device | ||
3480 | */ | ||
3420 | int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) | 3481 | int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) |
3421 | { | 3482 | { |
3422 | int err; | 3483 | int err; |
@@ -4320,7 +4381,12 @@ void free_netdev(struct net_device *dev) | |||
4320 | put_device(&dev->dev); | 4381 | put_device(&dev->dev); |
4321 | } | 4382 | } |
4322 | 4383 | ||
4323 | /* Synchronize with packet receive processing. */ | 4384 | /** |
4385 | * synchronize_net - Synchronize with packet receive processing | ||
4386 | * | ||
4387 | * Wait for packets currently being received to be done. | ||
4388 | * Does not block later packets from starting. | ||
4389 | */ | ||
4324 | void synchronize_net(void) | 4390 | void synchronize_net(void) |
4325 | { | 4391 | { |
4326 | might_sleep(); | 4392 | might_sleep(); |
@@ -4622,7 +4688,7 @@ netdev_dma_event(struct dma_client *client, struct dma_chan *chan, | |||
4622 | } | 4688 | } |
4623 | 4689 | ||
4624 | /** | 4690 | /** |
4625 | * netdev_dma_regiser - register the networking subsystem as a DMA client | 4691 | * netdev_dma_register - register the networking subsystem as a DMA client |
4626 | */ | 4692 | */ |
4627 | static int __init netdev_dma_register(void) | 4693 | static int __init netdev_dma_register(void) |
4628 | { | 4694 | { |
@@ -4723,10 +4789,18 @@ err_name: | |||
4723 | return -ENOMEM; | 4789 | return -ENOMEM; |
4724 | } | 4790 | } |
4725 | 4791 | ||
4726 | char *netdev_drivername(struct net_device *dev, char *buffer, int len) | 4792 | /** |
4793 | * netdev_drivername - network driver for the device | ||
4794 | * @dev: network device | ||
4795 | * @buffer: buffer for resulting name | ||
4796 | * @len: size of buffer | ||
4797 | * | ||
4798 | * Determine network driver for device. | ||
4799 | */ | ||
4800 | char *netdev_drivername(const struct net_device *dev, char *buffer, int len) | ||
4727 | { | 4801 | { |
4728 | struct device_driver *driver; | 4802 | const struct device_driver *driver; |
4729 | struct device *parent; | 4803 | const struct device *parent; |
4730 | 4804 | ||
4731 | if (len <= 0 || !buffer) | 4805 | if (len <= 0 || !buffer) |
4732 | return buffer; | 4806 | return buffer; |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 9d92e41826e7..1dc728b38589 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -927,8 +927,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) | |||
927 | if (skb_queue_len(&neigh->arp_queue) >= | 927 | if (skb_queue_len(&neigh->arp_queue) >= |
928 | neigh->parms->queue_len) { | 928 | neigh->parms->queue_len) { |
929 | struct sk_buff *buff; | 929 | struct sk_buff *buff; |
930 | buff = neigh->arp_queue.next; | 930 | buff = __skb_dequeue(&neigh->arp_queue); |
931 | __skb_unlink(buff, &neigh->arp_queue); | ||
932 | kfree_skb(buff); | 931 | kfree_skb(buff); |
933 | NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards); | 932 | NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards); |
934 | } | 933 | } |
@@ -1259,24 +1258,20 @@ static void neigh_proxy_process(unsigned long arg) | |||
1259 | struct neigh_table *tbl = (struct neigh_table *)arg; | 1258 | struct neigh_table *tbl = (struct neigh_table *)arg; |
1260 | long sched_next = 0; | 1259 | long sched_next = 0; |
1261 | unsigned long now = jiffies; | 1260 | unsigned long now = jiffies; |
1262 | struct sk_buff *skb; | 1261 | struct sk_buff *skb, *n; |
1263 | 1262 | ||
1264 | spin_lock(&tbl->proxy_queue.lock); | 1263 | spin_lock(&tbl->proxy_queue.lock); |
1265 | 1264 | ||
1266 | skb = tbl->proxy_queue.next; | 1265 | skb_queue_walk_safe(&tbl->proxy_queue, skb, n) { |
1267 | 1266 | long tdif = NEIGH_CB(skb)->sched_next - now; | |
1268 | while (skb != (struct sk_buff *)&tbl->proxy_queue) { | ||
1269 | struct sk_buff *back = skb; | ||
1270 | long tdif = NEIGH_CB(back)->sched_next - now; | ||
1271 | 1267 | ||
1272 | skb = skb->next; | ||
1273 | if (tdif <= 0) { | 1268 | if (tdif <= 0) { |
1274 | struct net_device *dev = back->dev; | 1269 | struct net_device *dev = skb->dev; |
1275 | __skb_unlink(back, &tbl->proxy_queue); | 1270 | __skb_unlink(skb, &tbl->proxy_queue); |
1276 | if (tbl->proxy_redo && netif_running(dev)) | 1271 | if (tbl->proxy_redo && netif_running(dev)) |
1277 | tbl->proxy_redo(back); | 1272 | tbl->proxy_redo(skb); |
1278 | else | 1273 | else |
1279 | kfree_skb(back); | 1274 | kfree_skb(skb); |
1280 | 1275 | ||
1281 | dev_put(dev); | 1276 | dev_put(dev); |
1282 | } else if (!sched_next || tdif < sched_next) | 1277 | } else if (!sched_next || tdif < sched_next) |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c1f4e0d428c0..92d6b9467314 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -209,9 +209,44 @@ static ssize_t store_tx_queue_len(struct device *dev, | |||
209 | return netdev_store(dev, attr, buf, len, change_tx_queue_len); | 209 | return netdev_store(dev, attr, buf, len, change_tx_queue_len); |
210 | } | 210 | } |
211 | 211 | ||
212 | static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, | ||
213 | const char *buf, size_t len) | ||
214 | { | ||
215 | struct net_device *netdev = to_net_dev(dev); | ||
216 | size_t count = len; | ||
217 | ssize_t ret; | ||
218 | |||
219 | if (!capable(CAP_NET_ADMIN)) | ||
220 | return -EPERM; | ||
221 | |||
222 | /* ignore trailing newline */ | ||
223 | if (len > 0 && buf[len - 1] == '\n') | ||
224 | --count; | ||
225 | |||
226 | rtnl_lock(); | ||
227 | ret = dev_set_alias(netdev, buf, count); | ||
228 | rtnl_unlock(); | ||
229 | |||
230 | return ret < 0 ? ret : len; | ||
231 | } | ||
232 | |||
233 | static ssize_t show_ifalias(struct device *dev, | ||
234 | struct device_attribute *attr, char *buf) | ||
235 | { | ||
236 | const struct net_device *netdev = to_net_dev(dev); | ||
237 | ssize_t ret = 0; | ||
238 | |||
239 | rtnl_lock(); | ||
240 | if (netdev->ifalias) | ||
241 | ret = sprintf(buf, "%s\n", netdev->ifalias); | ||
242 | rtnl_unlock(); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
212 | static struct device_attribute net_class_attributes[] = { | 246 | static struct device_attribute net_class_attributes[] = { |
213 | __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), | 247 | __ATTR(addr_len, S_IRUGO, show_addr_len, NULL), |
214 | __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), | 248 | __ATTR(dev_id, S_IRUGO, show_dev_id, NULL), |
249 | __ATTR(ifalias, S_IRUGO | S_IWUSR, show_ifalias, store_ifalias), | ||
215 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), | 250 | __ATTR(iflink, S_IRUGO, show_iflink, NULL), |
216 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), | 251 | __ATTR(ifindex, S_IRUGO, show_ifindex, NULL), |
217 | __ATTR(features, S_IRUGO, show_features, NULL), | 252 | __ATTR(features, S_IRUGO, show_features, NULL), |
@@ -418,6 +453,7 @@ static void netdev_release(struct device *d) | |||
418 | 453 | ||
419 | BUG_ON(dev->reg_state != NETREG_RELEASED); | 454 | BUG_ON(dev->reg_state != NETREG_RELEASED); |
420 | 455 | ||
456 | kfree(dev->ifalias); | ||
421 | kfree((char *)dev - dev->padded); | 457 | kfree((char *)dev - dev->padded); |
422 | } | 458 | } |
423 | 459 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 71edb8b36341..8862498fd4a6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -586,6 +586,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
586 | { | 586 | { |
587 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 587 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
588 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 588 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
589 | + nla_total_size(IFALIASZ) /* IFLA_IFALIAS */ | ||
589 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ | 590 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
590 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) | 591 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) |
591 | + nla_total_size(sizeof(struct rtnl_link_stats)) | 592 | + nla_total_size(sizeof(struct rtnl_link_stats)) |
@@ -640,6 +641,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
640 | if (txq->qdisc_sleeping) | 641 | if (txq->qdisc_sleeping) |
641 | NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id); | 642 | NLA_PUT_STRING(skb, IFLA_QDISC, txq->qdisc_sleeping->ops->id); |
642 | 643 | ||
644 | if (dev->ifalias) | ||
645 | NLA_PUT_STRING(skb, IFLA_IFALIAS, dev->ifalias); | ||
646 | |||
643 | if (1) { | 647 | if (1) { |
644 | struct rtnl_link_ifmap map = { | 648 | struct rtnl_link_ifmap map = { |
645 | .mem_start = dev->mem_start, | 649 | .mem_start = dev->mem_start, |
@@ -713,6 +717,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
713 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 717 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
714 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 718 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
715 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 719 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
720 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | ||
716 | }; | 721 | }; |
717 | 722 | ||
718 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 723 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
@@ -853,6 +858,14 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
853 | modified = 1; | 858 | modified = 1; |
854 | } | 859 | } |
855 | 860 | ||
861 | if (tb[IFLA_IFALIAS]) { | ||
862 | err = dev_set_alias(dev, nla_data(tb[IFLA_IFALIAS]), | ||
863 | nla_len(tb[IFLA_IFALIAS])); | ||
864 | if (err < 0) | ||
865 | goto errout; | ||
866 | modified = 1; | ||
867 | } | ||
868 | |||
856 | if (tb[IFLA_BROADCAST]) { | 869 | if (tb[IFLA_BROADCAST]) { |
857 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); | 870 | nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); |
858 | send_addr_notify = 1; | 871 | send_addr_notify = 1; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ca1ccdf1ef76..8bd248a64879 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -363,8 +363,7 @@ static void kfree_skbmem(struct sk_buff *skb) | |||
363 | } | 363 | } |
364 | } | 364 | } |
365 | 365 | ||
366 | /* Free everything but the sk_buff shell. */ | 366 | static void skb_release_head_state(struct sk_buff *skb) |
367 | static void skb_release_all(struct sk_buff *skb) | ||
368 | { | 367 | { |
369 | dst_release(skb->dst); | 368 | dst_release(skb->dst); |
370 | #ifdef CONFIG_XFRM | 369 | #ifdef CONFIG_XFRM |
@@ -388,6 +387,12 @@ static void skb_release_all(struct sk_buff *skb) | |||
388 | skb->tc_verd = 0; | 387 | skb->tc_verd = 0; |
389 | #endif | 388 | #endif |
390 | #endif | 389 | #endif |
390 | } | ||
391 | |||
392 | /* Free everything but the sk_buff shell. */ | ||
393 | static void skb_release_all(struct sk_buff *skb) | ||
394 | { | ||
395 | skb_release_head_state(skb); | ||
391 | skb_release_data(skb); | 396 | skb_release_data(skb); |
392 | } | 397 | } |
393 | 398 | ||
@@ -424,6 +429,38 @@ void kfree_skb(struct sk_buff *skb) | |||
424 | __kfree_skb(skb); | 429 | __kfree_skb(skb); |
425 | } | 430 | } |
426 | 431 | ||
432 | int skb_recycle_check(struct sk_buff *skb, int skb_size) | ||
433 | { | ||
434 | struct skb_shared_info *shinfo; | ||
435 | |||
436 | if (skb_is_nonlinear(skb) || skb->fclone != SKB_FCLONE_UNAVAILABLE) | ||
437 | return 0; | ||
438 | |||
439 | skb_size = SKB_DATA_ALIGN(skb_size + NET_SKB_PAD); | ||
440 | if (skb_end_pointer(skb) - skb->head < skb_size) | ||
441 | return 0; | ||
442 | |||
443 | if (skb_shared(skb) || skb_cloned(skb)) | ||
444 | return 0; | ||
445 | |||
446 | skb_release_head_state(skb); | ||
447 | shinfo = skb_shinfo(skb); | ||
448 | atomic_set(&shinfo->dataref, 1); | ||
449 | shinfo->nr_frags = 0; | ||
450 | shinfo->gso_size = 0; | ||
451 | shinfo->gso_segs = 0; | ||
452 | shinfo->gso_type = 0; | ||
453 | shinfo->ip6_frag_id = 0; | ||
454 | shinfo->frag_list = NULL; | ||
455 | |||
456 | memset(skb, 0, offsetof(struct sk_buff, tail)); | ||
457 | skb_reset_tail_pointer(skb); | ||
458 | skb->data = skb->head + NET_SKB_PAD; | ||
459 | |||
460 | return 1; | ||
461 | } | ||
462 | EXPORT_SYMBOL(skb_recycle_check); | ||
463 | |||
427 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | 464 | static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) |
428 | { | 465 | { |
429 | new->tstamp = old->tstamp; | 466 | new->tstamp = old->tstamp; |
@@ -701,6 +738,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
701 | #endif | 738 | #endif |
702 | long off; | 739 | long off; |
703 | 740 | ||
741 | BUG_ON(nhead < 0); | ||
742 | |||
704 | if (skb_shared(skb)) | 743 | if (skb_shared(skb)) |
705 | BUG(); | 744 | BUG(); |
706 | 745 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 23b8b9da36b3..2d358dd8a03e 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -154,7 +154,8 @@ static const char *af_family_key_strings[AF_MAX+1] = { | |||
154 | "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , | 154 | "sk_lock-AF_PPPOX" , "sk_lock-AF_WANPIPE" , "sk_lock-AF_LLC" , |
155 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , | 155 | "sk_lock-27" , "sk_lock-28" , "sk_lock-AF_CAN" , |
156 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , | 156 | "sk_lock-AF_TIPC" , "sk_lock-AF_BLUETOOTH", "sk_lock-IUCV" , |
157 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_MAX" | 157 | "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN" , "sk_lock-AF_PHONET" , |
158 | "sk_lock-AF_MAX" | ||
158 | }; | 159 | }; |
159 | static const char *af_family_slock_key_strings[AF_MAX+1] = { | 160 | static const char *af_family_slock_key_strings[AF_MAX+1] = { |
160 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , | 161 | "slock-AF_UNSPEC", "slock-AF_UNIX" , "slock-AF_INET" , |
@@ -168,7 +169,8 @@ static const char *af_family_slock_key_strings[AF_MAX+1] = { | |||
168 | "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , | 169 | "slock-AF_PPPOX" , "slock-AF_WANPIPE" , "slock-AF_LLC" , |
169 | "slock-27" , "slock-28" , "slock-AF_CAN" , | 170 | "slock-27" , "slock-28" , "slock-AF_CAN" , |
170 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , | 171 | "slock-AF_TIPC" , "slock-AF_BLUETOOTH", "slock-AF_IUCV" , |
171 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_MAX" | 172 | "slock-AF_RXRPC" , "slock-AF_ISDN" , "slock-AF_PHONET" , |
173 | "slock-AF_MAX" | ||
172 | }; | 174 | }; |
173 | static const char *af_family_clock_key_strings[AF_MAX+1] = { | 175 | static const char *af_family_clock_key_strings[AF_MAX+1] = { |
174 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , | 176 | "clock-AF_UNSPEC", "clock-AF_UNIX" , "clock-AF_INET" , |
@@ -182,7 +184,8 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = { | |||
182 | "clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" , | 184 | "clock-AF_PPPOX" , "clock-AF_WANPIPE" , "clock-AF_LLC" , |
183 | "clock-27" , "clock-28" , "clock-AF_CAN" , | 185 | "clock-27" , "clock-28" , "clock-AF_CAN" , |
184 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , | 186 | "clock-AF_TIPC" , "clock-AF_BLUETOOTH", "clock-AF_IUCV" , |
185 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_MAX" | 187 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
188 | "clock-AF_MAX" | ||
186 | }; | 189 | }; |
187 | #endif | 190 | #endif |
188 | 191 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 8a3ac1fa71a9..1fbff5fa4241 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -469,7 +469,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
469 | */ | 469 | */ |
470 | err = -EADDRNOTAVAIL; | 470 | err = -EADDRNOTAVAIL; |
471 | if (!sysctl_ip_nonlocal_bind && | 471 | if (!sysctl_ip_nonlocal_bind && |
472 | !inet->freebind && | 472 | !(inet->freebind || inet->transparent) && |
473 | addr->sin_addr.s_addr != htonl(INADDR_ANY) && | 473 | addr->sin_addr.s_addr != htonl(INADDR_ANY) && |
474 | chk_addr_ret != RTN_LOCAL && | 474 | chk_addr_ret != RTN_LOCAL && |
475 | chk_addr_ret != RTN_MULTICAST && | 475 | chk_addr_ret != RTN_MULTICAST && |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 0c1ae68ee84b..21fcc5a9045f 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -335,6 +335,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, | |||
335 | .saddr = ireq->loc_addr, | 335 | .saddr = ireq->loc_addr, |
336 | .tos = RT_CONN_FLAGS(sk) } }, | 336 | .tos = RT_CONN_FLAGS(sk) } }, |
337 | .proto = sk->sk_protocol, | 337 | .proto = sk->sk_protocol, |
338 | .flags = inet_sk_flowi_flags(sk), | ||
338 | .uli_u = { .ports = | 339 | .uli_u = { .ports = |
339 | { .sport = inet_sk(sk)->sport, | 340 | { .sport = inet_sk(sk)->sport, |
340 | .dport = ireq->rmt_port } } }; | 341 | .dport = ireq->rmt_port } } }; |
@@ -515,6 +516,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, | |||
515 | newicsk->icsk_bind_hash = NULL; | 516 | newicsk->icsk_bind_hash = NULL; |
516 | 517 | ||
517 | inet_sk(newsk)->dport = inet_rsk(req)->rmt_port; | 518 | inet_sk(newsk)->dport = inet_rsk(req)->rmt_port; |
519 | inet_sk(newsk)->num = ntohs(inet_rsk(req)->loc_port); | ||
520 | inet_sk(newsk)->sport = inet_rsk(req)->loc_port; | ||
518 | newsk->sk_write_space = sk_stream_write_space; | 521 | newsk->sk_write_space = sk_stream_write_space; |
519 | 522 | ||
520 | newicsk->icsk_retransmits = 0; | 523 | newicsk->icsk_retransmits = 0; |
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 743f011b9a84..1c5fd38f8824 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c | |||
@@ -126,6 +126,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat | |||
126 | tw->tw_reuse = sk->sk_reuse; | 126 | tw->tw_reuse = sk->sk_reuse; |
127 | tw->tw_hash = sk->sk_hash; | 127 | tw->tw_hash = sk->sk_hash; |
128 | tw->tw_ipv6only = 0; | 128 | tw->tw_ipv6only = 0; |
129 | tw->tw_transparent = inet->transparent; | ||
129 | tw->tw_prot = sk->sk_prot_creator; | 130 | tw->tw_prot = sk->sk_prot_creator; |
130 | twsk_net_set(tw, hold_net(sock_net(sk))); | 131 | twsk_net_set(tw, hold_net(sock_net(sk))); |
131 | atomic_set(&tw->tw_refcnt, 1); | 132 | atomic_set(&tw->tw_refcnt, 1); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index d533a89e08de..d2a8f8bb78a6 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -340,6 +340,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) | |||
340 | .saddr = inet->saddr, | 340 | .saddr = inet->saddr, |
341 | .tos = RT_CONN_FLAGS(sk) } }, | 341 | .tos = RT_CONN_FLAGS(sk) } }, |
342 | .proto = sk->sk_protocol, | 342 | .proto = sk->sk_protocol, |
343 | .flags = inet_sk_flowi_flags(sk), | ||
343 | .uli_u = { .ports = | 344 | .uli_u = { .ports = |
344 | { .sport = inet->sport, | 345 | { .sport = inet->sport, |
345 | .dport = inet->dport } } }; | 346 | .dport = inet->dport } } }; |
@@ -1371,7 +1372,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1371 | .uli_u = { .ports = | 1372 | .uli_u = { .ports = |
1372 | { .sport = tcp_hdr(skb)->dest, | 1373 | { .sport = tcp_hdr(skb)->dest, |
1373 | .dport = tcp_hdr(skb)->source } }, | 1374 | .dport = tcp_hdr(skb)->source } }, |
1374 | .proto = sk->sk_protocol }; | 1375 | .proto = sk->sk_protocol, |
1376 | .flags = ip_reply_arg_flowi_flags(arg) }; | ||
1375 | security_skb_classify_flow(skb, &fl); | 1377 | security_skb_classify_flow(skb, &fl); |
1376 | if (ip_route_output_key(sock_net(sk), &rt, &fl)) | 1378 | if (ip_route_output_key(sock_net(sk), &rt, &fl)) |
1377 | return; | 1379 | return; |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 105d92a039b9..465abf0a9869 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -419,7 +419,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
419 | (1<<IP_TTL) | (1<<IP_HDRINCL) | | 419 | (1<<IP_TTL) | (1<<IP_HDRINCL) | |
420 | (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | | 420 | (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | |
421 | (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | | 421 | (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | |
422 | (1<<IP_PASSSEC))) || | 422 | (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) || |
423 | optname == IP_MULTICAST_TTL || | 423 | optname == IP_MULTICAST_TTL || |
424 | optname == IP_MULTICAST_LOOP) { | 424 | optname == IP_MULTICAST_LOOP) { |
425 | if (optlen >= sizeof(int)) { | 425 | if (optlen >= sizeof(int)) { |
@@ -878,6 +878,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
878 | err = xfrm_user_policy(sk, optname, optval, optlen); | 878 | err = xfrm_user_policy(sk, optname, optval, optlen); |
879 | break; | 879 | break; |
880 | 880 | ||
881 | case IP_TRANSPARENT: | ||
882 | if (!capable(CAP_NET_ADMIN)) { | ||
883 | err = -EPERM; | ||
884 | break; | ||
885 | } | ||
886 | if (optlen < 1) | ||
887 | goto e_inval; | ||
888 | inet->transparent = !!val; | ||
889 | break; | ||
890 | |||
881 | default: | 891 | default: |
882 | err = -ENOPROTOOPT; | 892 | err = -ENOPROTOOPT; |
883 | break; | 893 | break; |
@@ -1130,6 +1140,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, | |||
1130 | case IP_FREEBIND: | 1140 | case IP_FREEBIND: |
1131 | val = inet->freebind; | 1141 | val = inet->freebind; |
1132 | break; | 1142 | break; |
1143 | case IP_TRANSPARENT: | ||
1144 | val = inet->transparent; | ||
1145 | break; | ||
1133 | default: | 1146 | default: |
1134 | release_sock(sk); | 1147 | release_sock(sk); |
1135 | return -ENOPROTOOPT; | 1148 | return -ENOPROTOOPT; |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index f8edacdf991d..01671ad51ed3 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -20,6 +20,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
20 | unsigned int type; | 20 | unsigned int type; |
21 | 21 | ||
22 | type = inet_addr_type(&init_net, iph->saddr); | 22 | type = inet_addr_type(&init_net, iph->saddr); |
23 | if (skb->sk && inet_sk(skb->sk)->transparent) | ||
24 | type = RTN_LOCAL; | ||
23 | if (addr_type == RTN_UNSPEC) | 25 | if (addr_type == RTN_UNSPEC) |
24 | addr_type = type; | 26 | addr_type = type; |
25 | 27 | ||
@@ -33,6 +35,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type) | |||
33 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); | 35 | fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); |
34 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; | 36 | fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0; |
35 | fl.mark = skb->mark; | 37 | fl.mark = skb->mark; |
38 | fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0; | ||
36 | if (ip_route_output_key(&init_net, &rt, &fl) != 0) | 39 | if (ip_route_output_key(&init_net, &rt, &fl) != 0) |
37 | return -1; | 40 | return -1; |
38 | 41 | ||
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 11976ea29884..112dcfa12900 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/udp.h> | 16 | #include <linux/udp.h> |
17 | #include <net/checksum.h> | 17 | #include <net/checksum.h> |
18 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
19 | #include <net/route.h> | ||
19 | 20 | ||
20 | #include <linux/netfilter_ipv4.h> | 21 | #include <linux/netfilter_ipv4.h> |
21 | #include <net/netfilter/nf_conntrack.h> | 22 | #include <net/netfilter/nf_conntrack.h> |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index f62187bb6d08..a6d7c584f53b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -2361,11 +2361,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2361 | ipv4_is_zeronet(oldflp->fl4_src)) | 2361 | ipv4_is_zeronet(oldflp->fl4_src)) |
2362 | goto out; | 2362 | goto out; |
2363 | 2363 | ||
2364 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ | ||
2365 | dev_out = ip_dev_find(net, oldflp->fl4_src); | ||
2366 | if (dev_out == NULL) | ||
2367 | goto out; | ||
2368 | |||
2369 | /* I removed check for oif == dev_out->oif here. | 2364 | /* I removed check for oif == dev_out->oif here. |
2370 | It was wrong for two reasons: | 2365 | It was wrong for two reasons: |
2371 | 1. ip_dev_find(net, saddr) can return wrong iface, if saddr | 2366 | 1. ip_dev_find(net, saddr) can return wrong iface, if saddr |
@@ -2377,6 +2372,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2377 | if (oldflp->oif == 0 | 2372 | if (oldflp->oif == 0 |
2378 | && (ipv4_is_multicast(oldflp->fl4_dst) || | 2373 | && (ipv4_is_multicast(oldflp->fl4_dst) || |
2379 | oldflp->fl4_dst == htonl(0xFFFFFFFF))) { | 2374 | oldflp->fl4_dst == htonl(0xFFFFFFFF))) { |
2375 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ | ||
2376 | dev_out = ip_dev_find(net, oldflp->fl4_src); | ||
2377 | if (dev_out == NULL) | ||
2378 | goto out; | ||
2379 | |||
2380 | /* Special hack: user can direct multicasts | 2380 | /* Special hack: user can direct multicasts |
2381 | and limited broadcast via necessary interface | 2381 | and limited broadcast via necessary interface |
2382 | without fiddling with IP_MULTICAST_IF or IP_PKTINFO. | 2382 | without fiddling with IP_MULTICAST_IF or IP_PKTINFO. |
@@ -2395,9 +2395,15 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp, | |||
2395 | fl.oif = dev_out->ifindex; | 2395 | fl.oif = dev_out->ifindex; |
2396 | goto make_route; | 2396 | goto make_route; |
2397 | } | 2397 | } |
2398 | if (dev_out) | 2398 | |
2399 | if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) { | ||
2400 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ | ||
2401 | dev_out = ip_dev_find(net, oldflp->fl4_src); | ||
2402 | if (dev_out == NULL) | ||
2403 | goto out; | ||
2399 | dev_put(dev_out); | 2404 | dev_put(dev_out); |
2400 | dev_out = NULL; | 2405 | dev_out = NULL; |
2406 | } | ||
2401 | } | 2407 | } |
2402 | 2408 | ||
2403 | 2409 | ||
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 9d38005abbac..d346c22aa6ae 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/cryptohash.h> | 16 | #include <linux/cryptohash.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <net/tcp.h> | 18 | #include <net/tcp.h> |
19 | #include <net/route.h> | ||
19 | 20 | ||
20 | /* Timestamps: lowest 9 bits store TCP options */ | 21 | /* Timestamps: lowest 9 bits store TCP options */ |
21 | #define TSBITS 9 | 22 | #define TSBITS 9 |
@@ -296,6 +297,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
296 | treq->rcv_isn = ntohl(th->seq) - 1; | 297 | treq->rcv_isn = ntohl(th->seq) - 1; |
297 | treq->snt_isn = cookie; | 298 | treq->snt_isn = cookie; |
298 | req->mss = mss; | 299 | req->mss = mss; |
300 | ireq->loc_port = th->dest; | ||
299 | ireq->rmt_port = th->source; | 301 | ireq->rmt_port = th->source; |
300 | ireq->loc_addr = ip_hdr(skb)->daddr; | 302 | ireq->loc_addr = ip_hdr(skb)->daddr; |
301 | ireq->rmt_addr = ip_hdr(skb)->saddr; | 303 | ireq->rmt_addr = ip_hdr(skb)->saddr; |
@@ -337,6 +339,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
337 | .saddr = ireq->loc_addr, | 339 | .saddr = ireq->loc_addr, |
338 | .tos = RT_CONN_FLAGS(sk) } }, | 340 | .tos = RT_CONN_FLAGS(sk) } }, |
339 | .proto = IPPROTO_TCP, | 341 | .proto = IPPROTO_TCP, |
342 | .flags = inet_sk_flowi_flags(sk), | ||
340 | .uli_u = { .ports = | 343 | .uli_u = { .ports = |
341 | { .sport = th->dest, | 344 | { .sport = th->dest, |
342 | .dport = th->source } } }; | 345 | .dport = th->source } } }; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1ab341e5d3e0..7d81a1ee5507 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -384,13 +384,17 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
384 | 384 | ||
385 | /* Connected? */ | 385 | /* Connected? */ |
386 | if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) { | 386 | if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) { |
387 | int target = sock_rcvlowat(sk, 0, INT_MAX); | ||
388 | |||
389 | if (tp->urg_seq == tp->copied_seq && | ||
390 | !sock_flag(sk, SOCK_URGINLINE) && | ||
391 | tp->urg_data) | ||
392 | target--; | ||
393 | |||
387 | /* Potential race condition. If read of tp below will | 394 | /* Potential race condition. If read of tp below will |
388 | * escape above sk->sk_state, we can be illegally awaken | 395 | * escape above sk->sk_state, we can be illegally awaken |
389 | * in SYN_* states. */ | 396 | * in SYN_* states. */ |
390 | if ((tp->rcv_nxt != tp->copied_seq) && | 397 | if (tp->rcv_nxt - tp->copied_seq >= target) |
391 | (tp->urg_seq != tp->copied_seq || | ||
392 | tp->rcv_nxt != tp->copied_seq + 1 || | ||
393 | sock_flag(sk, SOCK_URGINLINE) || !tp->urg_data)) | ||
394 | mask |= POLLIN | POLLRDNORM; | 398 | mask |= POLLIN | POLLRDNORM; |
395 | 399 | ||
396 | if (!(sk->sk_shutdown & SEND_SHUTDOWN)) { | 400 | if (!(sk->sk_shutdown & SEND_SHUTDOWN)) { |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 85627f83665f..3b76bce769dd 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1746,6 +1746,8 @@ int tcp_use_frto(struct sock *sk) | |||
1746 | return 0; | 1746 | return 0; |
1747 | 1747 | ||
1748 | skb = tcp_write_queue_head(sk); | 1748 | skb = tcp_write_queue_head(sk); |
1749 | if (tcp_skb_is_last(sk, skb)) | ||
1750 | return 1; | ||
1749 | skb = tcp_write_queue_next(sk, skb); /* Skips head */ | 1751 | skb = tcp_write_queue_next(sk, skb); /* Skips head */ |
1750 | tcp_for_write_queue_from(skb, sk) { | 1752 | tcp_for_write_queue_from(skb, sk) { |
1751 | if (skb == tcp_send_head(sk)) | 1753 | if (skb == tcp_send_head(sk)) |
@@ -4156,7 +4158,7 @@ drop: | |||
4156 | skb1 = skb1->prev; | 4158 | skb1 = skb1->prev; |
4157 | } | 4159 | } |
4158 | } | 4160 | } |
4159 | __skb_insert(skb, skb1, skb1->next, &tp->out_of_order_queue); | 4161 | __skb_queue_after(&tp->out_of_order_queue, skb1, skb); |
4160 | 4162 | ||
4161 | /* And clean segments covered by new one as whole. */ | 4163 | /* And clean segments covered by new one as whole. */ |
4162 | while ((skb1 = skb->next) != | 4164 | while ((skb1 = skb->next) != |
@@ -4254,7 +4256,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, | |||
4254 | memcpy(nskb->head, skb->head, header); | 4256 | memcpy(nskb->head, skb->head, header); |
4255 | memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); | 4257 | memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); |
4256 | TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start; | 4258 | TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(nskb)->end_seq = start; |
4257 | __skb_insert(nskb, skb->prev, skb, list); | 4259 | __skb_queue_before(list, skb, nskb); |
4258 | skb_set_owner_r(nskb, sk); | 4260 | skb_set_owner_r(nskb, sk); |
4259 | 4261 | ||
4260 | /* Copy data, releasing collapsed skbs. */ | 4262 | /* Copy data, releasing collapsed skbs. */ |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 44aef1c1f373..8b24bd833cb4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -591,6 +591,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
591 | ip_hdr(skb)->saddr, /* XXX */ | 591 | ip_hdr(skb)->saddr, /* XXX */ |
592 | sizeof(struct tcphdr), IPPROTO_TCP, 0); | 592 | sizeof(struct tcphdr), IPPROTO_TCP, 0); |
593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; | 593 | arg.csumoffset = offsetof(struct tcphdr, check) / 2; |
594 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | ||
594 | 595 | ||
595 | net = dev_net(skb->dst->dev); | 596 | net = dev_net(skb->dst->dev); |
596 | ip_send_reply(net->ipv4.tcp_sock, skb, | 597 | ip_send_reply(net->ipv4.tcp_sock, skb, |
@@ -606,7 +607,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
606 | 607 | ||
607 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 608 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
608 | u32 win, u32 ts, int oif, | 609 | u32 win, u32 ts, int oif, |
609 | struct tcp_md5sig_key *key) | 610 | struct tcp_md5sig_key *key, |
611 | int reply_flags) | ||
610 | { | 612 | { |
611 | struct tcphdr *th = tcp_hdr(skb); | 613 | struct tcphdr *th = tcp_hdr(skb); |
612 | struct { | 614 | struct { |
@@ -618,7 +620,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
618 | ]; | 620 | ]; |
619 | } rep; | 621 | } rep; |
620 | struct ip_reply_arg arg; | 622 | struct ip_reply_arg arg; |
621 | struct net *net = dev_net(skb->dev); | 623 | struct net *net = dev_net(skb->dst->dev); |
622 | 624 | ||
623 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 625 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
624 | memset(&arg, 0, sizeof(arg)); | 626 | memset(&arg, 0, sizeof(arg)); |
@@ -659,6 +661,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
659 | ip_hdr(skb)->daddr, &rep.th); | 661 | ip_hdr(skb)->daddr, &rep.th); |
660 | } | 662 | } |
661 | #endif | 663 | #endif |
664 | arg.flags = reply_flags; | ||
662 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, | 665 | arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, |
663 | ip_hdr(skb)->saddr, /* XXX */ | 666 | ip_hdr(skb)->saddr, /* XXX */ |
664 | arg.iov[0].iov_len, IPPROTO_TCP, 0); | 667 | arg.iov[0].iov_len, IPPROTO_TCP, 0); |
@@ -681,7 +684,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
681 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 684 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
682 | tcptw->tw_ts_recent, | 685 | tcptw->tw_ts_recent, |
683 | tw->tw_bound_dev_if, | 686 | tw->tw_bound_dev_if, |
684 | tcp_twsk_md5_key(tcptw) | 687 | tcp_twsk_md5_key(tcptw), |
688 | tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0 | ||
685 | ); | 689 | ); |
686 | 690 | ||
687 | inet_twsk_put(tw); | 691 | inet_twsk_put(tw); |
@@ -694,7 +698,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
694 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 698 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, |
695 | req->ts_recent, | 699 | req->ts_recent, |
696 | 0, | 700 | 0, |
697 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr)); | 701 | tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr), |
702 | inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0); | ||
698 | } | 703 | } |
699 | 704 | ||
700 | /* | 705 | /* |
@@ -1244,6 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1244 | ireq = inet_rsk(req); | 1249 | ireq = inet_rsk(req); |
1245 | ireq->loc_addr = daddr; | 1250 | ireq->loc_addr = daddr; |
1246 | ireq->rmt_addr = saddr; | 1251 | ireq->rmt_addr = saddr; |
1252 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1247 | ireq->opt = tcp_v4_save_options(sk, skb); | 1253 | ireq->opt = tcp_v4_save_options(sk, skb); |
1248 | if (!want_cookie) | 1254 | if (!want_cookie) |
1249 | TCP_ECN_create_request(req, tcp_hdr(skb)); | 1255 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c3d58ee3e16f..493553c71d32 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1932,8 +1932,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1932 | /* Collapse two adjacent packets if worthwhile and we can. */ | 1932 | /* Collapse two adjacent packets if worthwhile and we can. */ |
1933 | if (!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) && | 1933 | if (!(TCP_SKB_CB(skb)->flags & TCPCB_FLAG_SYN) && |
1934 | (skb->len < (cur_mss >> 1)) && | 1934 | (skb->len < (cur_mss >> 1)) && |
1935 | (tcp_write_queue_next(sk, skb) != tcp_send_head(sk)) && | ||
1936 | (!tcp_skb_is_last(sk, skb)) && | 1935 | (!tcp_skb_is_last(sk, skb)) && |
1936 | (tcp_write_queue_next(sk, skb) != tcp_send_head(sk)) && | ||
1937 | (skb_shinfo(skb)->nr_frags == 0 && | 1937 | (skb_shinfo(skb)->nr_frags == 0 && |
1938 | skb_shinfo(tcp_write_queue_next(sk, skb))->nr_frags == 0) && | 1938 | skb_shinfo(tcp_write_queue_next(sk, skb))->nr_frags == 0) && |
1939 | (tcp_skb_pcount(skb) == 1 && | 1939 | (tcp_skb_pcount(skb) == 1 && |
@@ -2275,7 +2275,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2275 | th->syn = 1; | 2275 | th->syn = 1; |
2276 | th->ack = 1; | 2276 | th->ack = 1; |
2277 | TCP_ECN_make_synack(req, th); | 2277 | TCP_ECN_make_synack(req, th); |
2278 | th->source = inet_sk(sk)->sport; | 2278 | th->source = ireq->loc_port; |
2279 | th->dest = ireq->rmt_port; | 2279 | th->dest = ireq->rmt_port; |
2280 | /* Setting of flags are superfluous here for callers (and ECE is | 2280 | /* Setting of flags are superfluous here for callers (and ECE is |
2281 | * not even correctly set) | 2281 | * not even correctly set) |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8e42fbbd5761..c83d0ef469c9 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -302,6 +302,13 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
302 | return result; | 302 | return result; |
303 | } | 303 | } |
304 | 304 | ||
305 | struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, | ||
306 | __be32 daddr, __be16 dport, int dif) | ||
307 | { | ||
308 | return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(udp4_lib_lookup); | ||
311 | |||
305 | static inline struct sock *udp_v4_mcast_next(struct sock *sk, | 312 | static inline struct sock *udp_v4_mcast_next(struct sock *sk, |
306 | __be16 loc_port, __be32 loc_addr, | 313 | __be16 loc_port, __be32 loc_addr, |
307 | __be16 rmt_port, __be32 rmt_addr, | 314 | __be16 rmt_port, __be32 rmt_addr, |
@@ -951,6 +958,27 @@ int udp_disconnect(struct sock *sk, int flags) | |||
951 | return 0; | 958 | return 0; |
952 | } | 959 | } |
953 | 960 | ||
961 | static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
962 | { | ||
963 | int is_udplite = IS_UDPLITE(sk); | ||
964 | int rc; | ||
965 | |||
966 | if ((rc = sock_queue_rcv_skb(sk, skb)) < 0) { | ||
967 | /* Note that an ENOMEM error is charged twice */ | ||
968 | if (rc == -ENOMEM) | ||
969 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | ||
970 | is_udplite); | ||
971 | goto drop; | ||
972 | } | ||
973 | |||
974 | return 0; | ||
975 | |||
976 | drop: | ||
977 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | ||
978 | kfree_skb(skb); | ||
979 | return -1; | ||
980 | } | ||
981 | |||
954 | /* returns: | 982 | /* returns: |
955 | * -1: error | 983 | * -1: error |
956 | * 0: success | 984 | * 0: success |
@@ -989,9 +1017,7 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
989 | up->encap_rcv != NULL) { | 1017 | up->encap_rcv != NULL) { |
990 | int ret; | 1018 | int ret; |
991 | 1019 | ||
992 | bh_unlock_sock(sk); | ||
993 | ret = (*up->encap_rcv)(sk, skb); | 1020 | ret = (*up->encap_rcv)(sk, skb); |
994 | bh_lock_sock(sk); | ||
995 | if (ret <= 0) { | 1021 | if (ret <= 0) { |
996 | UDP_INC_STATS_BH(sock_net(sk), | 1022 | UDP_INC_STATS_BH(sock_net(sk), |
997 | UDP_MIB_INDATAGRAMS, | 1023 | UDP_MIB_INDATAGRAMS, |
@@ -1044,17 +1070,16 @@ int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
1044 | goto drop; | 1070 | goto drop; |
1045 | } | 1071 | } |
1046 | 1072 | ||
1047 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { | 1073 | rc = 0; |
1048 | /* Note that an ENOMEM error is charged twice */ | ||
1049 | if (rc == -ENOMEM) { | ||
1050 | UDP_INC_STATS_BH(sock_net(sk), | ||
1051 | UDP_MIB_RCVBUFERRORS, is_udplite); | ||
1052 | atomic_inc(&sk->sk_drops); | ||
1053 | } | ||
1054 | goto drop; | ||
1055 | } | ||
1056 | 1074 | ||
1057 | return 0; | 1075 | bh_lock_sock(sk); |
1076 | if (!sock_owned_by_user(sk)) | ||
1077 | rc = __udp_queue_rcv_skb(sk, skb); | ||
1078 | else | ||
1079 | sk_add_backlog(sk, skb); | ||
1080 | bh_unlock_sock(sk); | ||
1081 | |||
1082 | return rc; | ||
1058 | 1083 | ||
1059 | drop: | 1084 | drop: |
1060 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 1085 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
@@ -1092,15 +1117,7 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
1092 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1117 | skb1 = skb_clone(skb, GFP_ATOMIC); |
1093 | 1118 | ||
1094 | if (skb1) { | 1119 | if (skb1) { |
1095 | int ret = 0; | 1120 | int ret = udp_queue_rcv_skb(sk, skb1); |
1096 | |||
1097 | bh_lock_sock(sk); | ||
1098 | if (!sock_owned_by_user(sk)) | ||
1099 | ret = udp_queue_rcv_skb(sk, skb1); | ||
1100 | else | ||
1101 | sk_add_backlog(sk, skb1); | ||
1102 | bh_unlock_sock(sk); | ||
1103 | |||
1104 | if (ret > 0) | 1121 | if (ret > 0) |
1105 | /* we should probably re-process instead | 1122 | /* we should probably re-process instead |
1106 | * of dropping packets here. */ | 1123 | * of dropping packets here. */ |
@@ -1195,13 +1212,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[], | |||
1195 | uh->dest, inet_iif(skb), udptable); | 1212 | uh->dest, inet_iif(skb), udptable); |
1196 | 1213 | ||
1197 | if (sk != NULL) { | 1214 | if (sk != NULL) { |
1198 | int ret = 0; | 1215 | int ret = udp_queue_rcv_skb(sk, skb); |
1199 | bh_lock_sock(sk); | ||
1200 | if (!sock_owned_by_user(sk)) | ||
1201 | ret = udp_queue_rcv_skb(sk, skb); | ||
1202 | else | ||
1203 | sk_add_backlog(sk, skb); | ||
1204 | bh_unlock_sock(sk); | ||
1205 | sock_put(sk); | 1216 | sock_put(sk); |
1206 | 1217 | ||
1207 | /* a return value > 0 means to resubmit the input, but | 1218 | /* a return value > 0 means to resubmit the input, but |
@@ -1494,7 +1505,7 @@ struct proto udp_prot = { | |||
1494 | .sendmsg = udp_sendmsg, | 1505 | .sendmsg = udp_sendmsg, |
1495 | .recvmsg = udp_recvmsg, | 1506 | .recvmsg = udp_recvmsg, |
1496 | .sendpage = udp_sendpage, | 1507 | .sendpage = udp_sendpage, |
1497 | .backlog_rcv = udp_queue_rcv_skb, | 1508 | .backlog_rcv = __udp_queue_rcv_skb, |
1498 | .hash = udp_lib_hash, | 1509 | .hash = udp_lib_hash, |
1499 | .unhash = udp_lib_unhash, | 1510 | .unhash = udp_lib_unhash, |
1500 | .get_port = udp_v4_get_port, | 1511 | .get_port = udp_v4_get_port, |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 95055f8c3f35..f018704ecb86 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <net/ipip.h> | 50 | #include <net/ipip.h> |
51 | #include <net/protocol.h> | 51 | #include <net/protocol.h> |
52 | #include <net/inet_common.h> | 52 | #include <net/inet_common.h> |
53 | #include <net/route.h> | ||
53 | #include <net/transp_v6.h> | 54 | #include <net/transp_v6.h> |
54 | #include <net/ip6_route.h> | 55 | #include <net/ip6_route.h> |
55 | #include <net/addrconf.h> | 56 | #include <net/addrconf.h> |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 62e39ace0588..26654b26d7fa 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -97,8 +97,6 @@ hbh_mt6(const struct sk_buff *skb, const struct net_device *in, | |||
97 | hdrlen -= 2; | 97 | hdrlen -= 2; |
98 | if (!(optinfo->flags & IP6T_OPTS_OPTS)) { | 98 | if (!(optinfo->flags & IP6T_OPTS_OPTS)) { |
99 | return ret; | 99 | return ret; |
100 | } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { | ||
101 | pr_debug("Not strict - not implemented"); | ||
102 | } else { | 100 | } else { |
103 | pr_debug("Strict "); | 101 | pr_debug("Strict "); |
104 | pr_debug("#%d ", optinfo->optsnr); | 102 | pr_debug("#%d ", optinfo->optsnr); |
@@ -177,6 +175,12 @@ hbh_mt6_check(const char *tablename, const void *entry, | |||
177 | pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); | 175 | pr_debug("ip6t_opts: unknown flags %X\n", optsinfo->invflags); |
178 | return false; | 176 | return false; |
179 | } | 177 | } |
178 | |||
179 | if (optsinfo->flags & IP6T_OPTS_NSTRICT) { | ||
180 | pr_debug("ip6t_opts: Not strict - not implemented"); | ||
181 | return false; | ||
182 | } | ||
183 | |||
180 | return true; | 184 | return true; |
181 | } | 185 | } |
182 | 186 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 52d06dd4b817..9967ac7a01a8 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/ipv6.h> | 27 | #include <linux/ipv6.h> |
28 | #include <linux/icmpv6.h> | 28 | #include <linux/icmpv6.h> |
29 | #include <linux/random.h> | 29 | #include <linux/random.h> |
30 | #include <linux/jhash.h> | ||
31 | 30 | ||
32 | #include <net/sock.h> | 31 | #include <net/sock.h> |
33 | #include <net/snmp.h> | 32 | #include <net/snmp.h> |
@@ -103,39 +102,12 @@ struct ctl_table nf_ct_ipv6_sysctl_table[] = { | |||
103 | }; | 102 | }; |
104 | #endif | 103 | #endif |
105 | 104 | ||
106 | static unsigned int ip6qhashfn(__be32 id, const struct in6_addr *saddr, | ||
107 | const struct in6_addr *daddr) | ||
108 | { | ||
109 | u32 a, b, c; | ||
110 | |||
111 | a = (__force u32)saddr->s6_addr32[0]; | ||
112 | b = (__force u32)saddr->s6_addr32[1]; | ||
113 | c = (__force u32)saddr->s6_addr32[2]; | ||
114 | |||
115 | a += JHASH_GOLDEN_RATIO; | ||
116 | b += JHASH_GOLDEN_RATIO; | ||
117 | c += nf_frags.rnd; | ||
118 | __jhash_mix(a, b, c); | ||
119 | |||
120 | a += (__force u32)saddr->s6_addr32[3]; | ||
121 | b += (__force u32)daddr->s6_addr32[0]; | ||
122 | c += (__force u32)daddr->s6_addr32[1]; | ||
123 | __jhash_mix(a, b, c); | ||
124 | |||
125 | a += (__force u32)daddr->s6_addr32[2]; | ||
126 | b += (__force u32)daddr->s6_addr32[3]; | ||
127 | c += (__force u32)id; | ||
128 | __jhash_mix(a, b, c); | ||
129 | |||
130 | return c & (INETFRAGS_HASHSZ - 1); | ||
131 | } | ||
132 | |||
133 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 105 | static unsigned int nf_hashfn(struct inet_frag_queue *q) |
134 | { | 106 | { |
135 | const struct nf_ct_frag6_queue *nq; | 107 | const struct nf_ct_frag6_queue *nq; |
136 | 108 | ||
137 | nq = container_of(q, struct nf_ct_frag6_queue, q); | 109 | nq = container_of(q, struct nf_ct_frag6_queue, q); |
138 | return ip6qhashfn(nq->id, &nq->saddr, &nq->daddr); | 110 | return inet6_hash_frag(nq->id, &nq->saddr, &nq->daddr, nf_frags.rnd); |
139 | } | 111 | } |
140 | 112 | ||
141 | static void nf_skb_free(struct sk_buff *skb) | 113 | static void nf_skb_free(struct sk_buff *skb) |
@@ -209,7 +181,7 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) | |||
209 | arg.dst = dst; | 181 | arg.dst = dst; |
210 | 182 | ||
211 | read_lock_bh(&nf_frags.lock); | 183 | read_lock_bh(&nf_frags.lock); |
212 | hash = ip6qhashfn(id, src, dst); | 184 | hash = inet6_hash_frag(id, src, dst, nf_frags.rnd); |
213 | 185 | ||
214 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); | 186 | q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); |
215 | local_bh_enable(); | 187 | local_bh_enable(); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 89184b576e23..2eeadfa039cb 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -99,8 +99,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
99 | * callers should be careful not to use the hash value outside the ipfrag_lock | 99 | * callers should be careful not to use the hash value outside the ipfrag_lock |
100 | * as doing so could race with ipfrag_hash_rnd being recalculated. | 100 | * as doing so could race with ipfrag_hash_rnd being recalculated. |
101 | */ | 101 | */ |
102 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | 102 | unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, |
103 | struct in6_addr *daddr) | 103 | const struct in6_addr *daddr, u32 rnd) |
104 | { | 104 | { |
105 | u32 a, b, c; | 105 | u32 a, b, c; |
106 | 106 | ||
@@ -110,7 +110,7 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
110 | 110 | ||
111 | a += JHASH_GOLDEN_RATIO; | 111 | a += JHASH_GOLDEN_RATIO; |
112 | b += JHASH_GOLDEN_RATIO; | 112 | b += JHASH_GOLDEN_RATIO; |
113 | c += ip6_frags.rnd; | 113 | c += rnd; |
114 | __jhash_mix(a, b, c); | 114 | __jhash_mix(a, b, c); |
115 | 115 | ||
116 | a += (__force u32)saddr->s6_addr32[3]; | 116 | a += (__force u32)saddr->s6_addr32[3]; |
@@ -125,13 +125,14 @@ static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, | |||
125 | 125 | ||
126 | return c & (INETFRAGS_HASHSZ - 1); | 126 | return c & (INETFRAGS_HASHSZ - 1); |
127 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(inet6_hash_frag); | ||
128 | 129 | ||
129 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) | 130 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) |
130 | { | 131 | { |
131 | struct frag_queue *fq; | 132 | struct frag_queue *fq; |
132 | 133 | ||
133 | fq = container_of(q, struct frag_queue, q); | 134 | fq = container_of(q, struct frag_queue, q); |
134 | return ip6qhashfn(fq->id, &fq->saddr, &fq->daddr); | 135 | return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr, ip6_frags.rnd); |
135 | } | 136 | } |
136 | 137 | ||
137 | int ip6_frag_match(struct inet_frag_queue *q, void *a) | 138 | int ip6_frag_match(struct inet_frag_queue *q, void *a) |
@@ -247,7 +248,7 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, | |||
247 | arg.dst = dst; | 248 | arg.dst = dst; |
248 | 249 | ||
249 | read_lock(&ip6_frags.lock); | 250 | read_lock(&ip6_frags.lock); |
250 | hash = ip6qhashfn(id, src, dst); | 251 | hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); |
251 | 252 | ||
252 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 253 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
253 | if (q == NULL) | 254 | if (q == NULL) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 776871ee2288..f4385a6569c2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2708,6 +2708,8 @@ int __init ip6_route_init(void) | |||
2708 | if (ret) | 2708 | if (ret) |
2709 | goto out_kmem_cache; | 2709 | goto out_kmem_cache; |
2710 | 2710 | ||
2711 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | ||
2712 | |||
2711 | /* Registering of the loopback is done before this portion of code, | 2713 | /* Registering of the loopback is done before this portion of code, |
2712 | * the loopback reference in rt6_info will not be taken, do it | 2714 | * the loopback reference in rt6_info will not be taken, do it |
2713 | * manually for init_net */ | 2715 | * manually for init_net */ |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index e85f377a8f82..df16b68644e7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1050 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1050 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1051 | struct sk_buff *buff; | 1051 | struct sk_buff *buff; |
1052 | struct flowi fl; | 1052 | struct flowi fl; |
1053 | struct net *net = dev_net(skb->dev); | 1053 | struct net *net = dev_net(skb->dst->dev); |
1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1055 | unsigned int tot_len = sizeof(struct tcphdr); | 1055 | unsigned int tot_len = sizeof(struct tcphdr); |
1056 | __be32 *topt; | 1056 | __be32 *topt; |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 705959b31e24..d7b54b5bfa69 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -524,7 +524,6 @@ static int iucv_enable(void) | |||
524 | get_online_cpus(); | 524 | get_online_cpus(); |
525 | for_each_online_cpu(cpu) | 525 | for_each_online_cpu(cpu) |
526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | 526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
527 | preempt_enable(); | ||
528 | if (cpus_empty(iucv_buffer_cpumask)) | 527 | if (cpus_empty(iucv_buffer_cpumask)) |
529 | /* No cpu could declare an iucv buffer. */ | 528 | /* No cpu could declare an iucv buffer. */ |
530 | goto out_path; | 529 | goto out_path; |
@@ -547,7 +546,9 @@ out: | |||
547 | */ | 546 | */ |
548 | static void iucv_disable(void) | 547 | static void iucv_disable(void) |
549 | { | 548 | { |
549 | get_online_cpus(); | ||
550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); | 550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); |
551 | put_online_cpus(); | ||
551 | kfree(iucv_path_table); | 552 | kfree(iucv_path_table); |
552 | } | 553 | } |
553 | 554 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index d628df97e02e..362fe317e1f3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -58,6 +58,7 @@ struct pfkey_sock { | |||
58 | struct xfrm_policy_walk policy; | 58 | struct xfrm_policy_walk policy; |
59 | struct xfrm_state_walk state; | 59 | struct xfrm_state_walk state; |
60 | } u; | 60 | } u; |
61 | struct sk_buff *skb; | ||
61 | } dump; | 62 | } dump; |
62 | }; | 63 | }; |
63 | 64 | ||
@@ -73,22 +74,22 @@ static int pfkey_can_dump(struct sock *sk) | |||
73 | return 0; | 74 | return 0; |
74 | } | 75 | } |
75 | 76 | ||
76 | static int pfkey_do_dump(struct pfkey_sock *pfk) | 77 | static void pfkey_terminate_dump(struct pfkey_sock *pfk) |
77 | { | 78 | { |
78 | int rc; | 79 | if (pfk->dump.dump) { |
79 | 80 | if (pfk->dump.skb) { | |
80 | rc = pfk->dump.dump(pfk); | 81 | kfree_skb(pfk->dump.skb); |
81 | if (rc == -ENOBUFS) | 82 | pfk->dump.skb = NULL; |
82 | return 0; | 83 | } |
83 | 84 | pfk->dump.done(pfk); | |
84 | pfk->dump.done(pfk); | 85 | pfk->dump.dump = NULL; |
85 | pfk->dump.dump = NULL; | 86 | pfk->dump.done = NULL; |
86 | pfk->dump.done = NULL; | 87 | } |
87 | return rc; | ||
88 | } | 88 | } |
89 | 89 | ||
90 | static void pfkey_sock_destruct(struct sock *sk) | 90 | static void pfkey_sock_destruct(struct sock *sk) |
91 | { | 91 | { |
92 | pfkey_terminate_dump(pfkey_sk(sk)); | ||
92 | skb_queue_purge(&sk->sk_receive_queue); | 93 | skb_queue_purge(&sk->sk_receive_queue); |
93 | 94 | ||
94 | if (!sock_flag(sk, SOCK_DEAD)) { | 95 | if (!sock_flag(sk, SOCK_DEAD)) { |
@@ -310,6 +311,31 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, | |||
310 | return err; | 311 | return err; |
311 | } | 312 | } |
312 | 313 | ||
314 | static int pfkey_do_dump(struct pfkey_sock *pfk) | ||
315 | { | ||
316 | struct sadb_msg *hdr; | ||
317 | int rc; | ||
318 | |||
319 | rc = pfk->dump.dump(pfk); | ||
320 | if (rc == -ENOBUFS) | ||
321 | return 0; | ||
322 | |||
323 | if (pfk->dump.skb) { | ||
324 | if (!pfkey_can_dump(&pfk->sk)) | ||
325 | return 0; | ||
326 | |||
327 | hdr = (struct sadb_msg *) pfk->dump.skb->data; | ||
328 | hdr->sadb_msg_seq = 0; | ||
329 | hdr->sadb_msg_errno = rc; | ||
330 | pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, | ||
331 | &pfk->sk); | ||
332 | pfk->dump.skb = NULL; | ||
333 | } | ||
334 | |||
335 | pfkey_terminate_dump(pfk); | ||
336 | return rc; | ||
337 | } | ||
338 | |||
313 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) | 339 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) |
314 | { | 340 | { |
315 | *new = *orig; | 341 | *new = *orig; |
@@ -372,6 +398,7 @@ static u8 sadb_ext_min_len[] = { | |||
372 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), | 398 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), |
373 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), | 399 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), |
374 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), | 400 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), |
401 | [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), | ||
375 | }; | 402 | }; |
376 | 403 | ||
377 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ | 404 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ |
@@ -1736,9 +1763,14 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr) | |||
1736 | out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); | 1763 | out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); |
1737 | out_hdr->sadb_msg_errno = 0; | 1764 | out_hdr->sadb_msg_errno = 0; |
1738 | out_hdr->sadb_msg_reserved = 0; | 1765 | out_hdr->sadb_msg_reserved = 0; |
1739 | out_hdr->sadb_msg_seq = count; | 1766 | out_hdr->sadb_msg_seq = count + 1; |
1740 | out_hdr->sadb_msg_pid = pfk->dump.msg_pid; | 1767 | out_hdr->sadb_msg_pid = pfk->dump.msg_pid; |
1741 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); | 1768 | |
1769 | if (pfk->dump.skb) | ||
1770 | pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, | ||
1771 | &pfk->sk); | ||
1772 | pfk->dump.skb = out_skb; | ||
1773 | |||
1742 | return 0; | 1774 | return 0; |
1743 | } | 1775 | } |
1744 | 1776 | ||
@@ -2237,7 +2269,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
2237 | return 0; | 2269 | return 0; |
2238 | 2270 | ||
2239 | out: | 2271 | out: |
2240 | xp->dead = 1; | 2272 | xp->walk.dead = 1; |
2241 | xfrm_policy_destroy(xp); | 2273 | xfrm_policy_destroy(xp); |
2242 | return err; | 2274 | return err; |
2243 | } | 2275 | } |
@@ -2353,24 +2385,21 @@ static int pfkey_sockaddr_pair_size(sa_family_t family) | |||
2353 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); | 2385 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); |
2354 | } | 2386 | } |
2355 | 2387 | ||
2356 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | 2388 | static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, |
2357 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2389 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
2358 | u16 *family) | 2390 | u16 *family) |
2359 | { | 2391 | { |
2360 | u8 *sa = (u8 *) (rq + 1); | ||
2361 | int af, socklen; | 2392 | int af, socklen; |
2362 | 2393 | ||
2363 | if (rq->sadb_x_ipsecrequest_len < | 2394 | if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) |
2364 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) | ||
2365 | return -EINVAL; | 2395 | return -EINVAL; |
2366 | 2396 | ||
2367 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, | 2397 | af = pfkey_sockaddr_extract(sa, saddr); |
2368 | saddr); | ||
2369 | if (!af) | 2398 | if (!af) |
2370 | return -EINVAL; | 2399 | return -EINVAL; |
2371 | 2400 | ||
2372 | socklen = pfkey_sockaddr_len(af); | 2401 | socklen = pfkey_sockaddr_len(af); |
2373 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), | 2402 | if (pfkey_sockaddr_extract((struct sockaddr *) (((u8 *)sa) + socklen), |
2374 | daddr) != af) | 2403 | daddr) != af) |
2375 | return -EINVAL; | 2404 | return -EINVAL; |
2376 | 2405 | ||
@@ -2390,7 +2419,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
2390 | return -EINVAL; | 2419 | return -EINVAL; |
2391 | 2420 | ||
2392 | /* old endoints */ | 2421 | /* old endoints */ |
2393 | err = parse_sockaddr_pair(rq1, &m->old_saddr, &m->old_daddr, | 2422 | err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), |
2423 | rq1->sadb_x_ipsecrequest_len, | ||
2424 | &m->old_saddr, &m->old_daddr, | ||
2394 | &m->old_family); | 2425 | &m->old_family); |
2395 | if (err) | 2426 | if (err) |
2396 | return err; | 2427 | return err; |
@@ -2403,7 +2434,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
2403 | return -EINVAL; | 2434 | return -EINVAL; |
2404 | 2435 | ||
2405 | /* new endpoints */ | 2436 | /* new endpoints */ |
2406 | err = parse_sockaddr_pair(rq2, &m->new_saddr, &m->new_daddr, | 2437 | err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), |
2438 | rq2->sadb_x_ipsecrequest_len, | ||
2439 | &m->new_saddr, &m->new_daddr, | ||
2407 | &m->new_family); | 2440 | &m->new_family); |
2408 | if (err) | 2441 | if (err) |
2409 | return err; | 2442 | return err; |
@@ -2429,29 +2462,40 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
2429 | int i, len, ret, err = -EINVAL; | 2462 | int i, len, ret, err = -EINVAL; |
2430 | u8 dir; | 2463 | u8 dir; |
2431 | struct sadb_address *sa; | 2464 | struct sadb_address *sa; |
2465 | struct sadb_x_kmaddress *kma; | ||
2432 | struct sadb_x_policy *pol; | 2466 | struct sadb_x_policy *pol; |
2433 | struct sadb_x_ipsecrequest *rq; | 2467 | struct sadb_x_ipsecrequest *rq; |
2434 | struct xfrm_selector sel; | 2468 | struct xfrm_selector sel; |
2435 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 2469 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
2470 | struct xfrm_kmaddress k; | ||
2436 | 2471 | ||
2437 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1], | 2472 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1], |
2438 | ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || | 2473 | ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || |
2439 | !ext_hdrs[SADB_X_EXT_POLICY - 1]) { | 2474 | !ext_hdrs[SADB_X_EXT_POLICY - 1]) { |
2440 | err = -EINVAL; | 2475 | err = -EINVAL; |
2441 | goto out; | 2476 | goto out; |
2442 | } | 2477 | } |
2443 | 2478 | ||
2479 | kma = ext_hdrs[SADB_X_EXT_KMADDRESS - 1]; | ||
2444 | pol = ext_hdrs[SADB_X_EXT_POLICY - 1]; | 2480 | pol = ext_hdrs[SADB_X_EXT_POLICY - 1]; |
2445 | if (!pol) { | ||
2446 | err = -EINVAL; | ||
2447 | goto out; | ||
2448 | } | ||
2449 | 2481 | ||
2450 | if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) { | 2482 | if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) { |
2451 | err = -EINVAL; | 2483 | err = -EINVAL; |
2452 | goto out; | 2484 | goto out; |
2453 | } | 2485 | } |
2454 | 2486 | ||
2487 | if (kma) { | ||
2488 | /* convert sadb_x_kmaddress to xfrm_kmaddress */ | ||
2489 | k.reserved = kma->sadb_x_kmaddress_reserved; | ||
2490 | ret = parse_sockaddr_pair((struct sockaddr *)(kma + 1), | ||
2491 | 8*(kma->sadb_x_kmaddress_len) - sizeof(*kma), | ||
2492 | &k.local, &k.remote, &k.family); | ||
2493 | if (ret < 0) { | ||
2494 | err = ret; | ||
2495 | goto out; | ||
2496 | } | ||
2497 | } | ||
2498 | |||
2455 | dir = pol->sadb_x_policy_dir - 1; | 2499 | dir = pol->sadb_x_policy_dir - 1; |
2456 | memset(&sel, 0, sizeof(sel)); | 2500 | memset(&sel, 0, sizeof(sel)); |
2457 | 2501 | ||
@@ -2496,7 +2540,8 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
2496 | goto out; | 2540 | goto out; |
2497 | } | 2541 | } |
2498 | 2542 | ||
2499 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i); | 2543 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, |
2544 | kma ? &k : NULL); | ||
2500 | 2545 | ||
2501 | out: | 2546 | out: |
2502 | return err; | 2547 | return err; |
@@ -2575,9 +2620,14 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) | |||
2575 | out_hdr->sadb_msg_type = SADB_X_SPDDUMP; | 2620 | out_hdr->sadb_msg_type = SADB_X_SPDDUMP; |
2576 | out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; | 2621 | out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; |
2577 | out_hdr->sadb_msg_errno = 0; | 2622 | out_hdr->sadb_msg_errno = 0; |
2578 | out_hdr->sadb_msg_seq = count; | 2623 | out_hdr->sadb_msg_seq = count + 1; |
2579 | out_hdr->sadb_msg_pid = pfk->dump.msg_pid; | 2624 | out_hdr->sadb_msg_pid = pfk->dump.msg_pid; |
2580 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk); | 2625 | |
2626 | if (pfk->dump.skb) | ||
2627 | pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, | ||
2628 | &pfk->sk); | ||
2629 | pfk->dump.skb = out_skb; | ||
2630 | |||
2581 | return 0; | 2631 | return 0; |
2582 | } | 2632 | } |
2583 | 2633 | ||
@@ -3283,6 +3333,32 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
3283 | return 0; | 3333 | return 0; |
3284 | } | 3334 | } |
3285 | 3335 | ||
3336 | |||
3337 | static int set_sadb_kmaddress(struct sk_buff *skb, struct xfrm_kmaddress *k) | ||
3338 | { | ||
3339 | struct sadb_x_kmaddress *kma; | ||
3340 | u8 *sa; | ||
3341 | int family = k->family; | ||
3342 | int socklen = pfkey_sockaddr_len(family); | ||
3343 | int size_req; | ||
3344 | |||
3345 | size_req = (sizeof(struct sadb_x_kmaddress) + | ||
3346 | pfkey_sockaddr_pair_size(family)); | ||
3347 | |||
3348 | kma = (struct sadb_x_kmaddress *)skb_put(skb, size_req); | ||
3349 | memset(kma, 0, size_req); | ||
3350 | kma->sadb_x_kmaddress_len = size_req / 8; | ||
3351 | kma->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS; | ||
3352 | kma->sadb_x_kmaddress_reserved = k->reserved; | ||
3353 | |||
3354 | sa = (u8 *)(kma + 1); | ||
3355 | if (!pfkey_sockaddr_fill(&k->local, 0, (struct sockaddr *)sa, family) || | ||
3356 | !pfkey_sockaddr_fill(&k->remote, 0, (struct sockaddr *)(sa+socklen), family)) | ||
3357 | return -EINVAL; | ||
3358 | |||
3359 | return 0; | ||
3360 | } | ||
3361 | |||
3286 | static int set_ipsecrequest(struct sk_buff *skb, | 3362 | static int set_ipsecrequest(struct sk_buff *skb, |
3287 | uint8_t proto, uint8_t mode, int level, | 3363 | uint8_t proto, uint8_t mode, int level, |
3288 | uint32_t reqid, uint8_t family, | 3364 | uint32_t reqid, uint8_t family, |
@@ -3315,7 +3391,8 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3315 | 3391 | ||
3316 | #ifdef CONFIG_NET_KEY_MIGRATE | 3392 | #ifdef CONFIG_NET_KEY_MIGRATE |
3317 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 3393 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
3318 | struct xfrm_migrate *m, int num_bundles) | 3394 | struct xfrm_migrate *m, int num_bundles, |
3395 | struct xfrm_kmaddress *k) | ||
3319 | { | 3396 | { |
3320 | int i; | 3397 | int i; |
3321 | int sasize_sel; | 3398 | int sasize_sel; |
@@ -3332,6 +3409,12 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
3332 | if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH) | 3409 | if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH) |
3333 | return -EINVAL; | 3410 | return -EINVAL; |
3334 | 3411 | ||
3412 | if (k != NULL) { | ||
3413 | /* addresses for KM */ | ||
3414 | size += PFKEY_ALIGN8(sizeof(struct sadb_x_kmaddress) + | ||
3415 | pfkey_sockaddr_pair_size(k->family)); | ||
3416 | } | ||
3417 | |||
3335 | /* selector */ | 3418 | /* selector */ |
3336 | sasize_sel = pfkey_sockaddr_size(sel->family); | 3419 | sasize_sel = pfkey_sockaddr_size(sel->family); |
3337 | if (!sasize_sel) | 3420 | if (!sasize_sel) |
@@ -3368,6 +3451,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
3368 | hdr->sadb_msg_seq = 0; | 3451 | hdr->sadb_msg_seq = 0; |
3369 | hdr->sadb_msg_pid = 0; | 3452 | hdr->sadb_msg_pid = 0; |
3370 | 3453 | ||
3454 | /* Addresses to be used by KM for negotiation, if ext is available */ | ||
3455 | if (k != NULL && (set_sadb_kmaddress(skb, k) < 0)) | ||
3456 | return -EINVAL; | ||
3457 | |||
3371 | /* selector src */ | 3458 | /* selector src */ |
3372 | set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); | 3459 | set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); |
3373 | 3460 | ||
@@ -3413,7 +3500,8 @@ err: | |||
3413 | } | 3500 | } |
3414 | #else | 3501 | #else |
3415 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 3502 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
3416 | struct xfrm_migrate *m, int num_bundles) | 3503 | struct xfrm_migrate *m, int num_bundles, |
3504 | struct xfrm_kmaddress *k) | ||
3417 | { | 3505 | { |
3418 | return -ENOPROTOOPT; | 3506 | return -ENOPROTOOPT; |
3419 | } | 3507 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e2574885db4a..855126a3039d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -82,7 +82,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
82 | enum nl80211_iftype type, u32 *flags, | 82 | enum nl80211_iftype type, u32 *flags, |
83 | struct vif_params *params) | 83 | struct vif_params *params) |
84 | { | 84 | { |
85 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
86 | struct net_device *dev; | 85 | struct net_device *dev; |
87 | struct ieee80211_sub_if_data *sdata; | 86 | struct ieee80211_sub_if_data *sdata; |
88 | int ret; | 87 | int ret; |
@@ -95,15 +94,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
95 | if (!nl80211_type_check(type)) | 94 | if (!nl80211_type_check(type)) |
96 | return -EINVAL; | 95 | return -EINVAL; |
97 | 96 | ||
98 | if (dev == local->mdev) | ||
99 | return -EOPNOTSUPP; | ||
100 | |||
101 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 97 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
102 | 98 | ||
103 | ret = ieee80211_if_change_type(sdata, type); | 99 | ret = ieee80211_if_change_type(sdata, type); |
104 | if (ret) | 100 | if (ret) |
105 | return ret; | 101 | return ret; |
106 | 102 | ||
103 | if (netif_running(sdata->dev)) | ||
104 | return -EBUSY; | ||
105 | |||
107 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 106 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
108 | ieee80211_sdata_set_mesh_id(sdata, | 107 | ieee80211_sdata_set_mesh_id(sdata, |
109 | params->mesh_id_len, | 108 | params->mesh_id_len, |
@@ -120,16 +119,12 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
120 | u8 key_idx, u8 *mac_addr, | 119 | u8 key_idx, u8 *mac_addr, |
121 | struct key_params *params) | 120 | struct key_params *params) |
122 | { | 121 | { |
123 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
124 | struct ieee80211_sub_if_data *sdata; | 122 | struct ieee80211_sub_if_data *sdata; |
125 | struct sta_info *sta = NULL; | 123 | struct sta_info *sta = NULL; |
126 | enum ieee80211_key_alg alg; | 124 | enum ieee80211_key_alg alg; |
127 | struct ieee80211_key *key; | 125 | struct ieee80211_key *key; |
128 | int err; | 126 | int err; |
129 | 127 | ||
130 | if (dev == local->mdev) | ||
131 | return -EOPNOTSUPP; | ||
132 | |||
133 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 128 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
134 | 129 | ||
135 | switch (params->cipher) { | 130 | switch (params->cipher) { |
@@ -174,14 +169,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
174 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 169 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
175 | u8 key_idx, u8 *mac_addr) | 170 | u8 key_idx, u8 *mac_addr) |
176 | { | 171 | { |
177 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
178 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
179 | struct sta_info *sta; | 173 | struct sta_info *sta; |
180 | int ret; | 174 | int ret; |
181 | 175 | ||
182 | if (dev == local->mdev) | ||
183 | return -EOPNOTSUPP; | ||
184 | |||
185 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 176 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
186 | 177 | ||
187 | rcu_read_lock(); | 178 | rcu_read_lock(); |
@@ -222,7 +213,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
222 | void (*callback)(void *cookie, | 213 | void (*callback)(void *cookie, |
223 | struct key_params *params)) | 214 | struct key_params *params)) |
224 | { | 215 | { |
225 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
226 | struct ieee80211_sub_if_data *sdata; | 216 | struct ieee80211_sub_if_data *sdata; |
227 | struct sta_info *sta = NULL; | 217 | struct sta_info *sta = NULL; |
228 | u8 seq[6] = {0}; | 218 | u8 seq[6] = {0}; |
@@ -232,9 +222,6 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
232 | u16 iv16; | 222 | u16 iv16; |
233 | int err = -ENOENT; | 223 | int err = -ENOENT; |
234 | 224 | ||
235 | if (dev == local->mdev) | ||
236 | return -EOPNOTSUPP; | ||
237 | |||
238 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 225 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
239 | 226 | ||
240 | rcu_read_lock(); | 227 | rcu_read_lock(); |
@@ -310,12 +297,8 @@ static int ieee80211_config_default_key(struct wiphy *wiphy, | |||
310 | struct net_device *dev, | 297 | struct net_device *dev, |
311 | u8 key_idx) | 298 | u8 key_idx) |
312 | { | 299 | { |
313 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
314 | struct ieee80211_sub_if_data *sdata; | 300 | struct ieee80211_sub_if_data *sdata; |
315 | 301 | ||
316 | if (dev == local->mdev) | ||
317 | return -EOPNOTSUPP; | ||
318 | |||
319 | rcu_read_lock(); | 302 | rcu_read_lock(); |
320 | 303 | ||
321 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 304 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -496,13 +479,9 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
496 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 479 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
497 | struct beacon_parameters *params) | 480 | struct beacon_parameters *params) |
498 | { | 481 | { |
499 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
500 | struct ieee80211_sub_if_data *sdata; | 482 | struct ieee80211_sub_if_data *sdata; |
501 | struct beacon_data *old; | 483 | struct beacon_data *old; |
502 | 484 | ||
503 | if (dev == local->mdev) | ||
504 | return -EOPNOTSUPP; | ||
505 | |||
506 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 485 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
507 | 486 | ||
508 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 487 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -519,13 +498,9 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
519 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | 498 | static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, |
520 | struct beacon_parameters *params) | 499 | struct beacon_parameters *params) |
521 | { | 500 | { |
522 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
523 | struct ieee80211_sub_if_data *sdata; | 501 | struct ieee80211_sub_if_data *sdata; |
524 | struct beacon_data *old; | 502 | struct beacon_data *old; |
525 | 503 | ||
526 | if (dev == local->mdev) | ||
527 | return -EOPNOTSUPP; | ||
528 | |||
529 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 504 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
530 | 505 | ||
531 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 506 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -541,13 +516,9 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
541 | 516 | ||
542 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | 517 | static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) |
543 | { | 518 | { |
544 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
545 | struct ieee80211_sub_if_data *sdata; | 519 | struct ieee80211_sub_if_data *sdata; |
546 | struct beacon_data *old; | 520 | struct beacon_data *old; |
547 | 521 | ||
548 | if (dev == local->mdev) | ||
549 | return -EOPNOTSUPP; | ||
550 | |||
551 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 522 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
552 | 523 | ||
553 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 524 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
@@ -695,9 +666,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
695 | struct ieee80211_sub_if_data *sdata; | 666 | struct ieee80211_sub_if_data *sdata; |
696 | int err; | 667 | int err; |
697 | 668 | ||
698 | if (dev == local->mdev || params->vlan == local->mdev) | ||
699 | return -EOPNOTSUPP; | ||
700 | |||
701 | /* Prevent a race with changing the rate control algorithm */ | 669 | /* Prevent a race with changing the rate control algorithm */ |
702 | if (!netif_running(dev)) | 670 | if (!netif_running(dev)) |
703 | return -ENETDOWN; | 671 | return -ENETDOWN; |
@@ -725,7 +693,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
725 | 693 | ||
726 | sta_apply_parameters(local, sta, params); | 694 | sta_apply_parameters(local, sta, params); |
727 | 695 | ||
728 | rate_control_rate_init(sta, local); | 696 | rate_control_rate_init(sta); |
729 | 697 | ||
730 | rcu_read_lock(); | 698 | rcu_read_lock(); |
731 | 699 | ||
@@ -752,9 +720,6 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
752 | struct ieee80211_sub_if_data *sdata; | 720 | struct ieee80211_sub_if_data *sdata; |
753 | struct sta_info *sta; | 721 | struct sta_info *sta; |
754 | 722 | ||
755 | if (dev == local->mdev) | ||
756 | return -EOPNOTSUPP; | ||
757 | |||
758 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 723 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
759 | 724 | ||
760 | if (mac) { | 725 | if (mac) { |
@@ -786,9 +751,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
786 | struct sta_info *sta; | 751 | struct sta_info *sta; |
787 | struct ieee80211_sub_if_data *vlansdata; | 752 | struct ieee80211_sub_if_data *vlansdata; |
788 | 753 | ||
789 | if (dev == local->mdev || params->vlan == local->mdev) | ||
790 | return -EOPNOTSUPP; | ||
791 | |||
792 | rcu_read_lock(); | 754 | rcu_read_lock(); |
793 | 755 | ||
794 | /* XXX: get sta belonging to dev */ | 756 | /* XXX: get sta belonging to dev */ |
@@ -828,9 +790,6 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
828 | struct sta_info *sta; | 790 | struct sta_info *sta; |
829 | int err; | 791 | int err; |
830 | 792 | ||
831 | if (dev == local->mdev) | ||
832 | return -EOPNOTSUPP; | ||
833 | |||
834 | if (!netif_running(dev)) | 793 | if (!netif_running(dev)) |
835 | return -ENETDOWN; | 794 | return -ENETDOWN; |
836 | 795 | ||
@@ -884,9 +843,6 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
884 | struct mesh_path *mpath; | 843 | struct mesh_path *mpath; |
885 | struct sta_info *sta; | 844 | struct sta_info *sta; |
886 | 845 | ||
887 | if (dev == local->mdev) | ||
888 | return -EOPNOTSUPP; | ||
889 | |||
890 | if (!netif_running(dev)) | 846 | if (!netif_running(dev)) |
891 | return -ENETDOWN; | 847 | return -ENETDOWN; |
892 | 848 | ||
@@ -958,13 +914,9 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
958 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) | 914 | u8 *dst, u8 *next_hop, struct mpath_info *pinfo) |
959 | 915 | ||
960 | { | 916 | { |
961 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
962 | struct ieee80211_sub_if_data *sdata; | 917 | struct ieee80211_sub_if_data *sdata; |
963 | struct mesh_path *mpath; | 918 | struct mesh_path *mpath; |
964 | 919 | ||
965 | if (dev == local->mdev) | ||
966 | return -EOPNOTSUPP; | ||
967 | |||
968 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 920 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
969 | 921 | ||
970 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 922 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -986,13 +938,9 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
986 | int idx, u8 *dst, u8 *next_hop, | 938 | int idx, u8 *dst, u8 *next_hop, |
987 | struct mpath_info *pinfo) | 939 | struct mpath_info *pinfo) |
988 | { | 940 | { |
989 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
990 | struct ieee80211_sub_if_data *sdata; | 941 | struct ieee80211_sub_if_data *sdata; |
991 | struct mesh_path *mpath; | 942 | struct mesh_path *mpath; |
992 | 943 | ||
993 | if (dev == local->mdev) | ||
994 | return -EOPNOTSUPP; | ||
995 | |||
996 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 944 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
997 | 945 | ||
998 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | 946 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
@@ -1015,13 +963,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1015 | struct net_device *dev, | 963 | struct net_device *dev, |
1016 | struct bss_parameters *params) | 964 | struct bss_parameters *params) |
1017 | { | 965 | { |
1018 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1019 | struct ieee80211_sub_if_data *sdata; | 966 | struct ieee80211_sub_if_data *sdata; |
1020 | u32 changed = 0; | 967 | u32 changed = 0; |
1021 | 968 | ||
1022 | if (dev == local->mdev) | ||
1023 | return -EOPNOTSUPP; | ||
1024 | |||
1025 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 969 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1026 | 970 | ||
1027 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 971 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 81f350eaf8a3..b9902e425f09 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -173,8 +173,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
173 | const char __user *user_buf, size_t count, loff_t *ppos) | 173 | const char __user *user_buf, size_t count, loff_t *ppos) |
174 | { | 174 | { |
175 | struct sta_info *sta = file->private_data; | 175 | struct sta_info *sta = file->private_data; |
176 | struct net_device *dev = sta->sdata->dev; | 176 | struct ieee80211_local *local = sta->sdata->local; |
177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
178 | struct ieee80211_hw *hw = &local->hw; | 177 | struct ieee80211_hw *hw = &local->hw; |
179 | u8 *da = sta->sta.addr; | 178 | u8 *da = sta->sta.addr; |
180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, | 179 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3912fba6d3d0..8025b294588b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -573,6 +573,10 @@ enum { | |||
573 | /* maximum number of hardware queues we support. */ | 573 | /* maximum number of hardware queues we support. */ |
574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 574 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
575 | 575 | ||
576 | struct ieee80211_master_priv { | ||
577 | struct ieee80211_local *local; | ||
578 | }; | ||
579 | |||
576 | struct ieee80211_local { | 580 | struct ieee80211_local { |
577 | /* embed the driver visible part. | 581 | /* embed the driver visible part. |
578 | * don't cast (use the static inlines below), but we keep | 582 | * don't cast (use the static inlines below), but we keep |
@@ -720,6 +724,8 @@ struct ieee80211_local { | |||
720 | 724 | ||
721 | #ifdef CONFIG_MAC80211_DEBUGFS | 725 | #ifdef CONFIG_MAC80211_DEBUGFS |
722 | struct local_debugfsdentries { | 726 | struct local_debugfsdentries { |
727 | struct dentry *rcdir; | ||
728 | struct dentry *rcname; | ||
723 | struct dentry *frequency; | 729 | struct dentry *frequency; |
724 | struct dentry *antenna_sel_tx; | 730 | struct dentry *antenna_sel_tx; |
725 | struct dentry *antenna_sel_rx; | 731 | struct dentry *antenna_sel_rx; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a72fbebb8ea2..8336fee68d3e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -58,8 +58,9 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
58 | 58 | ||
59 | static int ieee80211_open(struct net_device *dev) | 59 | static int ieee80211_open(struct net_device *dev) |
60 | { | 60 | { |
61 | struct ieee80211_sub_if_data *sdata, *nsdata; | 61 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
62 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 62 | struct ieee80211_sub_if_data *nsdata; |
63 | struct ieee80211_local *local = sdata->local; | ||
63 | struct sta_info *sta; | 64 | struct sta_info *sta; |
64 | struct ieee80211_if_init_conf conf; | 65 | struct ieee80211_if_init_conf conf; |
65 | u32 changed = 0; | 66 | u32 changed = 0; |
@@ -67,8 +68,6 @@ static int ieee80211_open(struct net_device *dev) | |||
67 | bool need_hw_reconfig = 0; | 68 | bool need_hw_reconfig = 0; |
68 | u8 null_addr[ETH_ALEN] = {0}; | 69 | u8 null_addr[ETH_ALEN] = {0}; |
69 | 70 | ||
70 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
71 | |||
72 | /* fail early if user set an invalid address */ | 71 | /* fail early if user set an invalid address */ |
73 | if (compare_ether_addr(dev->dev_addr, null_addr) && | 72 | if (compare_ether_addr(dev->dev_addr, null_addr) && |
74 | !is_valid_ether_addr(dev->dev_addr)) | 73 | !is_valid_ether_addr(dev->dev_addr)) |
@@ -512,8 +511,8 @@ static int ieee80211_stop(struct net_device *dev) | |||
512 | 511 | ||
513 | static void ieee80211_set_multicast_list(struct net_device *dev) | 512 | static void ieee80211_set_multicast_list(struct net_device *dev) |
514 | { | 513 | { |
515 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
516 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 514 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
515 | struct ieee80211_local *local = sdata->local; | ||
517 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | 516 | int allmulti, promisc, sdata_allmulti, sdata_promisc; |
518 | 517 | ||
519 | allmulti = !!(dev->flags & IFF_ALLMULTI); | 518 | allmulti = !!(dev->flags & IFF_ALLMULTI); |
@@ -625,6 +624,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
625 | /* and set some type-dependent values */ | 624 | /* and set some type-dependent values */ |
626 | sdata->vif.type = type; | 625 | sdata->vif.type = type; |
627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | 626 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; |
627 | sdata->wdev.iftype = type; | ||
628 | 628 | ||
629 | /* only monitor differs */ | 629 | /* only monitor differs */ |
630 | sdata->dev->type = ARPHRD_ETHER; | 630 | sdata->dev->type = ARPHRD_ETHER; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c307dba7ec03..d608c44047c0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -106,7 +106,8 @@ static const struct header_ops ieee80211_header_ops = { | |||
106 | 106 | ||
107 | static int ieee80211_master_open(struct net_device *dev) | 107 | static int ieee80211_master_open(struct net_device *dev) |
108 | { | 108 | { |
109 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 109 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
110 | struct ieee80211_local *local = mpriv->local; | ||
110 | struct ieee80211_sub_if_data *sdata; | 111 | struct ieee80211_sub_if_data *sdata; |
111 | int res = -EOPNOTSUPP; | 112 | int res = -EOPNOTSUPP; |
112 | 113 | ||
@@ -128,7 +129,8 @@ static int ieee80211_master_open(struct net_device *dev) | |||
128 | 129 | ||
129 | static int ieee80211_master_stop(struct net_device *dev) | 130 | static int ieee80211_master_stop(struct net_device *dev) |
130 | { | 131 | { |
131 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 132 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
133 | struct ieee80211_local *local = mpriv->local; | ||
132 | struct ieee80211_sub_if_data *sdata; | 134 | struct ieee80211_sub_if_data *sdata; |
133 | 135 | ||
134 | /* we hold the RTNL here so can safely walk the list */ | 136 | /* we hold the RTNL here so can safely walk the list */ |
@@ -141,7 +143,8 @@ static int ieee80211_master_stop(struct net_device *dev) | |||
141 | 143 | ||
142 | static void ieee80211_master_set_multicast_list(struct net_device *dev) | 144 | static void ieee80211_master_set_multicast_list(struct net_device *dev) |
143 | { | 145 | { |
144 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 146 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
147 | struct ieee80211_local *local = mpriv->local; | ||
145 | 148 | ||
146 | ieee80211_configure_filter(local); | 149 | ieee80211_configure_filter(local); |
147 | } | 150 | } |
@@ -539,6 +542,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
539 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 542 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
540 | u16 frag, type; | 543 | u16 frag, type; |
541 | __le16 fc; | 544 | __le16 fc; |
545 | struct ieee80211_supported_band *sband; | ||
542 | struct ieee80211_tx_status_rtap_hdr *rthdr; | 546 | struct ieee80211_tx_status_rtap_hdr *rthdr; |
543 | struct ieee80211_sub_if_data *sdata; | 547 | struct ieee80211_sub_if_data *sdata; |
544 | struct net_device *prev_dev = NULL; | 548 | struct net_device *prev_dev = NULL; |
@@ -585,7 +589,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
585 | sta->tx_retry_count += info->status.retry_count; | 589 | sta->tx_retry_count += info->status.retry_count; |
586 | } | 590 | } |
587 | 591 | ||
588 | rate_control_tx_status(local->mdev, skb); | 592 | sband = local->hw.wiphy->bands[info->band]; |
593 | rate_control_tx_status(local, sband, sta, skb); | ||
589 | } | 594 | } |
590 | 595 | ||
591 | rcu_read_unlock(); | 596 | rcu_read_unlock(); |
@@ -787,7 +792,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
787 | int result; | 792 | int result; |
788 | enum ieee80211_band band; | 793 | enum ieee80211_band band; |
789 | struct net_device *mdev; | 794 | struct net_device *mdev; |
790 | struct wireless_dev *mwdev; | 795 | struct ieee80211_master_priv *mpriv; |
791 | 796 | ||
792 | /* | 797 | /* |
793 | * generic code guarantees at least one band, | 798 | * generic code guarantees at least one band, |
@@ -829,16 +834,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
829 | if (hw->queues < 4) | 834 | if (hw->queues < 4) |
830 | hw->ampdu_queues = 0; | 835 | hw->ampdu_queues = 0; |
831 | 836 | ||
832 | mdev = alloc_netdev_mq(sizeof(struct wireless_dev), | 837 | mdev = alloc_netdev_mq(sizeof(struct ieee80211_master_priv), |
833 | "wmaster%d", ether_setup, | 838 | "wmaster%d", ether_setup, |
834 | ieee80211_num_queues(hw)); | 839 | ieee80211_num_queues(hw)); |
835 | if (!mdev) | 840 | if (!mdev) |
836 | goto fail_mdev_alloc; | 841 | goto fail_mdev_alloc; |
837 | 842 | ||
838 | mwdev = netdev_priv(mdev); | 843 | mpriv = netdev_priv(mdev); |
839 | mdev->ieee80211_ptr = mwdev; | 844 | mpriv->local = local; |
840 | mwdev->wiphy = local->hw.wiphy; | ||
841 | |||
842 | local->mdev = mdev; | 845 | local->mdev = mdev; |
843 | 846 | ||
844 | ieee80211_rx_bss_list_init(local); | 847 | ieee80211_rx_bss_list_init(local); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 30cf891fd3a8..8013277924f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -351,7 +351,7 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
351 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
352 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
354 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = sdata->local; |
355 | 355 | ||
356 | queue_work(local->hw.workqueue, &ifmsh->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
357 | } | 357 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8ee414a0447c..e10471c6ba42 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -71,6 +71,7 @@ enum mesh_path_flags { | |||
71 | */ | 71 | */ |
72 | struct mesh_path { | 72 | struct mesh_path { |
73 | u8 dst[ETH_ALEN]; | 73 | u8 dst[ETH_ALEN]; |
74 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ | ||
74 | struct ieee80211_sub_if_data *sdata; | 75 | struct ieee80211_sub_if_data *sdata; |
75 | struct sta_info *next_hop; | 76 | struct sta_info *next_hop; |
76 | struct timer_list timer; | 77 | struct timer_list timer; |
@@ -226,6 +227,9 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
226 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 227 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
227 | struct mesh_path *mesh_path_lookup(u8 *dst, | 228 | struct mesh_path *mesh_path_lookup(u8 *dst, |
228 | struct ieee80211_sub_if_data *sdata); | 229 | struct ieee80211_sub_if_data *sdata); |
230 | struct mesh_path *mpp_path_lookup(u8 *dst, | ||
231 | struct ieee80211_sub_if_data *sdata); | ||
232 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | ||
229 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | 233 | struct mesh_path *mesh_path_lookup_by_idx(int idx, |
230 | struct ieee80211_sub_if_data *sdata); | 234 | struct ieee80211_sub_if_data *sdata); |
231 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 235 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index e4fa2905fadc..3c72557df45a 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -36,6 +36,7 @@ struct mpath_node { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct mesh_table *mesh_paths; | 38 | static struct mesh_table *mesh_paths; |
39 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ | ||
39 | 40 | ||
40 | /* This lock will have the grow table function as writer and add / delete nodes | 41 | /* This lock will have the grow table function as writer and add / delete nodes |
41 | * as readers. When reading the table (i.e. doing lookups) we are well protected | 42 | * as readers. When reading the table (i.e. doing lookups) we are well protected |
@@ -94,6 +95,34 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
94 | return NULL; | 95 | return NULL; |
95 | } | 96 | } |
96 | 97 | ||
98 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | ||
99 | { | ||
100 | struct mesh_path *mpath; | ||
101 | struct hlist_node *n; | ||
102 | struct hlist_head *bucket; | ||
103 | struct mesh_table *tbl; | ||
104 | struct mpath_node *node; | ||
105 | |||
106 | tbl = rcu_dereference(mpp_paths); | ||
107 | |||
108 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; | ||
109 | hlist_for_each_entry_rcu(node, n, bucket, list) { | ||
110 | mpath = node->mpath; | ||
111 | if (mpath->sdata == sdata && | ||
112 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | ||
113 | if (MPATH_EXPIRED(mpath)) { | ||
114 | spin_lock_bh(&mpath->state_lock); | ||
115 | if (MPATH_EXPIRED(mpath)) | ||
116 | mpath->flags &= ~MESH_PATH_ACTIVE; | ||
117 | spin_unlock_bh(&mpath->state_lock); | ||
118 | } | ||
119 | return mpath; | ||
120 | } | ||
121 | } | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | |||
97 | /** | 126 | /** |
98 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 127 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
99 | * @idx: index | 128 | * @idx: index |
@@ -226,6 +255,91 @@ err_path_alloc: | |||
226 | } | 255 | } |
227 | 256 | ||
228 | 257 | ||
258 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | ||
259 | { | ||
260 | struct mesh_path *mpath, *new_mpath; | ||
261 | struct mpath_node *node, *new_node; | ||
262 | struct hlist_head *bucket; | ||
263 | struct hlist_node *n; | ||
264 | int grow = 0; | ||
265 | int err = 0; | ||
266 | u32 hash_idx; | ||
267 | |||
268 | |||
269 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | ||
270 | /* never add ourselves as neighbours */ | ||
271 | return -ENOTSUPP; | ||
272 | |||
273 | if (is_multicast_ether_addr(dst)) | ||
274 | return -ENOTSUPP; | ||
275 | |||
276 | err = -ENOMEM; | ||
277 | new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); | ||
278 | if (!new_mpath) | ||
279 | goto err_path_alloc; | ||
280 | |||
281 | new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); | ||
282 | if (!new_node) | ||
283 | goto err_node_alloc; | ||
284 | |||
285 | read_lock(&pathtbl_resize_lock); | ||
286 | memcpy(new_mpath->dst, dst, ETH_ALEN); | ||
287 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); | ||
288 | new_mpath->sdata = sdata; | ||
289 | new_mpath->flags = 0; | ||
290 | skb_queue_head_init(&new_mpath->frame_queue); | ||
291 | new_node->mpath = new_mpath; | ||
292 | new_mpath->exp_time = jiffies; | ||
293 | spin_lock_init(&new_mpath->state_lock); | ||
294 | |||
295 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); | ||
296 | bucket = &mpp_paths->hash_buckets[hash_idx]; | ||
297 | |||
298 | spin_lock(&mpp_paths->hashwlock[hash_idx]); | ||
299 | |||
300 | err = -EEXIST; | ||
301 | hlist_for_each_entry(node, n, bucket, list) { | ||
302 | mpath = node->mpath; | ||
303 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | ||
304 | goto err_exists; | ||
305 | } | ||
306 | |||
307 | hlist_add_head_rcu(&new_node->list, bucket); | ||
308 | if (atomic_inc_return(&mpp_paths->entries) >= | ||
309 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) | ||
310 | grow = 1; | ||
311 | |||
312 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
313 | read_unlock(&pathtbl_resize_lock); | ||
314 | if (grow) { | ||
315 | struct mesh_table *oldtbl, *newtbl; | ||
316 | |||
317 | write_lock(&pathtbl_resize_lock); | ||
318 | oldtbl = mpp_paths; | ||
319 | newtbl = mesh_table_grow(mpp_paths); | ||
320 | if (!newtbl) { | ||
321 | write_unlock(&pathtbl_resize_lock); | ||
322 | return 0; | ||
323 | } | ||
324 | rcu_assign_pointer(mpp_paths, newtbl); | ||
325 | write_unlock(&pathtbl_resize_lock); | ||
326 | |||
327 | synchronize_rcu(); | ||
328 | mesh_table_free(oldtbl, false); | ||
329 | } | ||
330 | return 0; | ||
331 | |||
332 | err_exists: | ||
333 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | ||
334 | read_unlock(&pathtbl_resize_lock); | ||
335 | kfree(new_node); | ||
336 | err_node_alloc: | ||
337 | kfree(new_mpath); | ||
338 | err_path_alloc: | ||
339 | return err; | ||
340 | } | ||
341 | |||
342 | |||
229 | /** | 343 | /** |
230 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks | 344 | * mesh_plink_broken - deactivates paths and sends perr when a link breaks |
231 | * | 345 | * |
@@ -475,11 +589,21 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
475 | int mesh_pathtbl_init(void) | 589 | int mesh_pathtbl_init(void) |
476 | { | 590 | { |
477 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | 591 | mesh_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); |
592 | if (!mesh_paths) | ||
593 | return -ENOMEM; | ||
478 | mesh_paths->free_node = &mesh_path_node_free; | 594 | mesh_paths->free_node = &mesh_path_node_free; |
479 | mesh_paths->copy_node = &mesh_path_node_copy; | 595 | mesh_paths->copy_node = &mesh_path_node_copy; |
480 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; | 596 | mesh_paths->mean_chain_len = MEAN_CHAIN_LEN; |
481 | if (!mesh_paths) | 597 | |
598 | mpp_paths = mesh_table_alloc(INIT_PATHS_SIZE_ORDER); | ||
599 | if (!mpp_paths) { | ||
600 | mesh_table_free(mesh_paths, true); | ||
482 | return -ENOMEM; | 601 | return -ENOMEM; |
602 | } | ||
603 | mpp_paths->free_node = &mesh_path_node_free; | ||
604 | mpp_paths->copy_node = &mesh_path_node_copy; | ||
605 | mpp_paths->mean_chain_len = MEAN_CHAIN_LEN; | ||
606 | |||
483 | return 0; | 607 | return 0; |
484 | } | 608 | } |
485 | 609 | ||
@@ -511,4 +635,5 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
511 | void mesh_pathtbl_unregister(void) | 635 | void mesh_pathtbl_unregister(void) |
512 | { | 636 | { |
513 | mesh_table_free(mesh_paths, true); | 637 | mesh_table_free(mesh_paths, true); |
638 | mesh_table_free(mpp_paths, true); | ||
514 | } | 639 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8611a8318c9c..e859a0ab6162 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -942,8 +942,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
942 | disassoc = 1; | 942 | disassoc = 1; |
943 | } else | 943 | } else |
944 | ieee80211_send_probe_req(sdata, ifsta->bssid, | 944 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
945 | local->scan_ssid, | 945 | ifsta->ssid, |
946 | local->scan_ssid_len); | 946 | ifsta->ssid_len); |
947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | 947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; |
948 | } else { | 948 | } else { |
949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | 949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; |
@@ -1323,7 +1323,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); | 1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); |
1324 | } | 1324 | } |
1325 | 1325 | ||
1326 | rate_control_rate_init(sta, local); | 1326 | rate_control_rate_init(sta); |
1327 | 1327 | ||
1328 | if (elems.wmm_param) { | 1328 | if (elems.wmm_param) { |
1329 | set_sta_flags(sta, WLAN_STA_WME); | 1329 | set_sta_flags(sta, WLAN_STA_WME); |
@@ -1452,6 +1452,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; | 1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
1454 | 1454 | ||
1455 | ieee80211_led_assoc(local, true); | ||
1456 | |||
1455 | memset(&wrqu, 0, sizeof(wrqu)); | 1457 | memset(&wrqu, 0, sizeof(wrqu)); |
1456 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1458 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
1457 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | 1459 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
@@ -2342,7 +2344,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
2342 | sta->sta.supp_rates[band] = supp_rates | | 2344 | sta->sta.supp_rates[band] = supp_rates | |
2343 | ieee80211_mandatory_rates(local, band); | 2345 | ieee80211_mandatory_rates(local, band); |
2344 | 2346 | ||
2345 | rate_control_rate_init(sta, local); | 2347 | rate_control_rate_init(sta); |
2346 | 2348 | ||
2347 | if (sta_info_insert(sta)) | 2349 | if (sta_info_insert(sta)) |
2348 | return NULL; | 2350 | return NULL; |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0388c090dfe9..5d786720d935 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
13 | #include "rate.h" | 13 | #include "rate.h" |
14 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
15 | #include "debugfs.h" | ||
15 | 16 | ||
16 | struct rate_control_alg { | 17 | struct rate_control_alg { |
17 | struct list_head list; | 18 | struct list_head list; |
@@ -127,19 +128,46 @@ static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | |||
127 | module_put(ops->module); | 128 | module_put(ops->module); |
128 | } | 129 | } |
129 | 130 | ||
131 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
132 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | ||
133 | size_t count, loff_t *ppos) | ||
134 | { | ||
135 | struct rate_control_ref *ref = file->private_data; | ||
136 | int len = strlen(ref->ops->name); | ||
137 | |||
138 | return simple_read_from_buffer(userbuf, count, ppos, | ||
139 | ref->ops->name, len); | ||
140 | } | ||
141 | |||
142 | static const struct file_operations rcname_ops = { | ||
143 | .read = rcname_read, | ||
144 | .open = mac80211_open_file_generic, | ||
145 | }; | ||
146 | #endif | ||
147 | |||
130 | struct rate_control_ref *rate_control_alloc(const char *name, | 148 | struct rate_control_ref *rate_control_alloc(const char *name, |
131 | struct ieee80211_local *local) | 149 | struct ieee80211_local *local) |
132 | { | 150 | { |
151 | struct dentry *debugfsdir = NULL; | ||
133 | struct rate_control_ref *ref; | 152 | struct rate_control_ref *ref; |
134 | 153 | ||
135 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 154 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
136 | if (!ref) | 155 | if (!ref) |
137 | goto fail_ref; | 156 | goto fail_ref; |
138 | kref_init(&ref->kref); | 157 | kref_init(&ref->kref); |
158 | ref->local = local; | ||
139 | ref->ops = ieee80211_rate_control_ops_get(name); | 159 | ref->ops = ieee80211_rate_control_ops_get(name); |
140 | if (!ref->ops) | 160 | if (!ref->ops) |
141 | goto fail_ops; | 161 | goto fail_ops; |
142 | ref->priv = ref->ops->alloc(local); | 162 | |
163 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
164 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | ||
165 | local->debugfs.rcdir = debugfsdir; | ||
166 | local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir, | ||
167 | ref, &rcname_ops); | ||
168 | #endif | ||
169 | |||
170 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | ||
143 | if (!ref->priv) | 171 | if (!ref->priv) |
144 | goto fail_priv; | 172 | goto fail_priv; |
145 | return ref; | 173 | return ref; |
@@ -158,29 +186,46 @@ static void rate_control_release(struct kref *kref) | |||
158 | 186 | ||
159 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); | 187 | ctrl_ref = container_of(kref, struct rate_control_ref, kref); |
160 | ctrl_ref->ops->free(ctrl_ref->priv); | 188 | ctrl_ref->ops->free(ctrl_ref->priv); |
189 | |||
190 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
191 | debugfs_remove(ctrl_ref->local->debugfs.rcname); | ||
192 | ctrl_ref->local->debugfs.rcname = NULL; | ||
193 | debugfs_remove(ctrl_ref->local->debugfs.rcdir); | ||
194 | ctrl_ref->local->debugfs.rcdir = NULL; | ||
195 | #endif | ||
196 | |||
161 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | 197 | ieee80211_rate_control_ops_put(ctrl_ref->ops); |
162 | kfree(ctrl_ref); | 198 | kfree(ctrl_ref); |
163 | } | 199 | } |
164 | 200 | ||
165 | void rate_control_get_rate(struct net_device *dev, | 201 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
166 | struct ieee80211_supported_band *sband, | 202 | struct ieee80211_supported_band *sband, |
167 | struct sk_buff *skb, | 203 | struct sta_info *sta, struct sk_buff *skb, |
168 | struct rate_selection *sel) | 204 | struct rate_selection *sel) |
169 | { | 205 | { |
170 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct rate_control_ref *ref = sdata->local->rate_ctrl; |
171 | struct rate_control_ref *ref = local->rate_ctrl; | 207 | void *priv_sta = NULL; |
172 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 208 | struct ieee80211_sta *ista = NULL; |
173 | struct sta_info *sta; | ||
174 | int i; | 209 | int i; |
175 | 210 | ||
176 | rcu_read_lock(); | ||
177 | sta = sta_info_get(local, hdr->addr1); | ||
178 | |||
179 | sel->rate_idx = -1; | 211 | sel->rate_idx = -1; |
180 | sel->nonerp_idx = -1; | 212 | sel->nonerp_idx = -1; |
181 | sel->probe_idx = -1; | 213 | sel->probe_idx = -1; |
214 | sel->max_rate_idx = sdata->max_ratectrl_rateidx; | ||
215 | |||
216 | if (sta) { | ||
217 | ista = &sta->sta; | ||
218 | priv_sta = sta->rate_ctrl_priv; | ||
219 | } | ||
220 | |||
221 | if (sta && sdata->force_unicast_rateidx > -1) | ||
222 | sel->rate_idx = sdata->force_unicast_rateidx; | ||
223 | else | ||
224 | ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); | ||
182 | 225 | ||
183 | ref->ops->get_rate(ref->priv, dev, sband, skb, sel); | 226 | if (sdata->max_ratectrl_rateidx > -1 && |
227 | sel->rate_idx > sdata->max_ratectrl_rateidx) | ||
228 | sel->rate_idx = sdata->max_ratectrl_rateidx; | ||
184 | 229 | ||
185 | BUG_ON(sel->rate_idx < 0); | 230 | BUG_ON(sel->rate_idx < 0); |
186 | 231 | ||
@@ -191,13 +236,11 @@ void rate_control_get_rate(struct net_device *dev, | |||
191 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) | 236 | if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) |
192 | break; | 237 | break; |
193 | 238 | ||
194 | if (rate_supported(sta, sband->band, i) && | 239 | if (rate_supported(ista, sband->band, i) && |
195 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 240 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
196 | sel->nonerp_idx = i; | 241 | sel->nonerp_idx = i; |
197 | } | 242 | } |
198 | } | 243 | } |
199 | |||
200 | rcu_read_unlock(); | ||
201 | } | 244 | } |
202 | 245 | ||
203 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) | 246 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 5f18c27eb900..eb94e584d24e 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -19,77 +19,48 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "sta_info.h" | 20 | #include "sta_info.h" |
21 | 21 | ||
22 | /** | ||
23 | * struct rate_selection - rate selection for rate control algos | ||
24 | * @rate: selected transmission rate index | ||
25 | * @nonerp: Non-ERP rate to use instead if ERP cannot be used | ||
26 | * @probe: rate for probing (or -1) | ||
27 | * | ||
28 | */ | ||
29 | struct rate_selection { | ||
30 | s8 rate_idx, nonerp_idx, probe_idx; | ||
31 | }; | ||
32 | |||
33 | struct rate_control_ops { | ||
34 | struct module *module; | ||
35 | const char *name; | ||
36 | void (*tx_status)(void *priv, struct net_device *dev, | ||
37 | struct sk_buff *skb); | ||
38 | void (*get_rate)(void *priv, struct net_device *dev, | ||
39 | struct ieee80211_supported_band *band, | ||
40 | struct sk_buff *skb, | ||
41 | struct rate_selection *sel); | ||
42 | void (*rate_init)(void *priv, void *priv_sta, | ||
43 | struct ieee80211_local *local, struct sta_info *sta); | ||
44 | void (*clear)(void *priv); | ||
45 | |||
46 | void *(*alloc)(struct ieee80211_local *local); | ||
47 | void (*free)(void *priv); | ||
48 | void *(*alloc_sta)(void *priv, gfp_t gfp); | ||
49 | void (*free_sta)(void *priv, void *priv_sta); | ||
50 | |||
51 | int (*add_attrs)(void *priv, struct kobject *kobj); | ||
52 | void (*remove_attrs)(void *priv, struct kobject *kobj); | ||
53 | void (*add_sta_debugfs)(void *priv, void *priv_sta, | ||
54 | struct dentry *dir); | ||
55 | void (*remove_sta_debugfs)(void *priv, void *priv_sta); | ||
56 | }; | ||
57 | |||
58 | struct rate_control_ref { | 22 | struct rate_control_ref { |
23 | struct ieee80211_local *local; | ||
59 | struct rate_control_ops *ops; | 24 | struct rate_control_ops *ops; |
60 | void *priv; | 25 | void *priv; |
61 | struct kref kref; | 26 | struct kref kref; |
62 | }; | 27 | }; |
63 | 28 | ||
64 | int ieee80211_rate_control_register(struct rate_control_ops *ops); | ||
65 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops); | ||
66 | |||
67 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 29 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
68 | * first available algorithm. */ | 30 | * first available algorithm. */ |
69 | struct rate_control_ref *rate_control_alloc(const char *name, | 31 | struct rate_control_ref *rate_control_alloc(const char *name, |
70 | struct ieee80211_local *local); | 32 | struct ieee80211_local *local); |
71 | void rate_control_get_rate(struct net_device *dev, | 33 | void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, |
72 | struct ieee80211_supported_band *sband, | 34 | struct ieee80211_supported_band *sband, |
73 | struct sk_buff *skb, | 35 | struct sta_info *sta, struct sk_buff *skb, |
74 | struct rate_selection *sel); | 36 | struct rate_selection *sel); |
75 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); | 37 | struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); |
76 | void rate_control_put(struct rate_control_ref *ref); | 38 | void rate_control_put(struct rate_control_ref *ref); |
77 | 39 | ||
78 | static inline void rate_control_tx_status(struct net_device *dev, | 40 | static inline void rate_control_tx_status(struct ieee80211_local *local, |
41 | struct ieee80211_supported_band *sband, | ||
42 | struct sta_info *sta, | ||
79 | struct sk_buff *skb) | 43 | struct sk_buff *skb) |
80 | { | 44 | { |
81 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
82 | struct rate_control_ref *ref = local->rate_ctrl; | 45 | struct rate_control_ref *ref = local->rate_ctrl; |
46 | struct ieee80211_sta *ista = &sta->sta; | ||
47 | void *priv_sta = sta->rate_ctrl_priv; | ||
83 | 48 | ||
84 | ref->ops->tx_status(ref->priv, dev, skb); | 49 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); |
85 | } | 50 | } |
86 | 51 | ||
87 | 52 | ||
88 | static inline void rate_control_rate_init(struct sta_info *sta, | 53 | static inline void rate_control_rate_init(struct sta_info *sta) |
89 | struct ieee80211_local *local) | ||
90 | { | 54 | { |
55 | struct ieee80211_local *local = sta->sdata->local; | ||
91 | struct rate_control_ref *ref = sta->rate_ctrl; | 56 | struct rate_control_ref *ref = sta->rate_ctrl; |
92 | ref->ops->rate_init(ref->priv, sta->rate_ctrl_priv, local, sta); | 57 | struct ieee80211_sta *ista = &sta->sta; |
58 | void *priv_sta = sta->rate_ctrl_priv; | ||
59 | struct ieee80211_supported_band *sband; | ||
60 | |||
61 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
62 | |||
63 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | ||
93 | } | 64 | } |
94 | 65 | ||
95 | 66 | ||
@@ -100,15 +71,19 @@ static inline void rate_control_clear(struct ieee80211_local *local) | |||
100 | } | 71 | } |
101 | 72 | ||
102 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 73 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
74 | struct ieee80211_sta *sta, | ||
103 | gfp_t gfp) | 75 | gfp_t gfp) |
104 | { | 76 | { |
105 | return ref->ops->alloc_sta(ref->priv, gfp); | 77 | return ref->ops->alloc_sta(ref->priv, sta, gfp); |
106 | } | 78 | } |
107 | 79 | ||
108 | static inline void rate_control_free_sta(struct rate_control_ref *ref, | 80 | static inline void rate_control_free_sta(struct sta_info *sta) |
109 | void *priv) | ||
110 | { | 81 | { |
111 | ref->ops->free_sta(ref->priv, priv); | 82 | struct rate_control_ref *ref = sta->rate_ctrl; |
83 | struct ieee80211_sta *ista = &sta->sta; | ||
84 | void *priv_sta = sta->rate_ctrl_priv; | ||
85 | |||
86 | ref->ops->free_sta(ref->priv, ista, priv_sta); | ||
112 | } | 87 | } |
113 | 88 | ||
114 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | 89 | static inline void rate_control_add_sta_debugfs(struct sta_info *sta) |
@@ -130,31 +105,6 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
130 | #endif | 105 | #endif |
131 | } | 106 | } |
132 | 107 | ||
133 | static inline int rate_supported(struct sta_info *sta, | ||
134 | enum ieee80211_band band, | ||
135 | int index) | ||
136 | { | ||
137 | return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); | ||
138 | } | ||
139 | |||
140 | static inline s8 | ||
141 | rate_lowest_index(struct ieee80211_local *local, | ||
142 | struct ieee80211_supported_band *sband, | ||
143 | struct sta_info *sta) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < sband->n_bitrates; i++) | ||
148 | if (rate_supported(sta, sband->band, i)) | ||
149 | return i; | ||
150 | |||
151 | /* warn when we cannot find a rate. */ | ||
152 | WARN_ON(1); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | /* functions for rate control related to a device */ | 108 | /* functions for rate control related to a device */ |
159 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 109 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
160 | const char *name); | 110 | const char *name); |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index ffafc5da572e..01d64d53f3b9 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -124,7 +124,6 @@ struct rc_pid_events_file_info { | |||
124 | * struct rc_pid_debugfs_entries - tunable parameters | 124 | * struct rc_pid_debugfs_entries - tunable parameters |
125 | * | 125 | * |
126 | * Algorithm parameters, tunable via debugfs. | 126 | * Algorithm parameters, tunable via debugfs. |
127 | * @dir: the debugfs directory for a specific phy | ||
128 | * @target: target percentage for failed frames | 127 | * @target: target percentage for failed frames |
129 | * @sampling_period: error sampling interval in milliseconds | 128 | * @sampling_period: error sampling interval in milliseconds |
130 | * @coeff_p: absolute value of the proportional coefficient | 129 | * @coeff_p: absolute value of the proportional coefficient |
@@ -143,7 +142,6 @@ struct rc_pid_events_file_info { | |||
143 | * ordering of rates) | 142 | * ordering of rates) |
144 | */ | 143 | */ |
145 | struct rc_pid_debugfs_entries { | 144 | struct rc_pid_debugfs_entries { |
146 | struct dentry *dir; | ||
147 | struct dentry *target; | 145 | struct dentry *target; |
148 | struct dentry *sampling_period; | 146 | struct dentry *sampling_period; |
149 | struct dentry *coeff_p; | 147 | struct dentry *coeff_p; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index bc1c4569caa1..86eb374e3b87 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -68,18 +68,14 @@ | |||
68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | 68 | * exhibited a worse failed frames behaviour and we'll choose the highest rate |
69 | * whose failed frames behaviour is not worse than the one of the original rate | 69 | * whose failed frames behaviour is not worse than the one of the original rate |
70 | * target. While at it, check that the new rate is valid. */ | 70 | * target. While at it, check that the new rate is valid. */ |
71 | static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | 71 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, |
72 | struct sta_info *sta, int adj, | 72 | struct ieee80211_sta *sta, |
73 | struct rc_pid_sta_info *spinfo, int adj, | ||
73 | struct rc_pid_rateinfo *rinfo) | 74 | struct rc_pid_rateinfo *rinfo) |
74 | { | 75 | { |
75 | struct ieee80211_sub_if_data *sdata; | ||
76 | struct ieee80211_supported_band *sband; | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 76 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
79 | int cur = spinfo->txrate_idx; | 77 | int cur = spinfo->txrate_idx; |
80 | 78 | ||
81 | sdata = sta->sdata; | ||
82 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
83 | band = sband->band; | 79 | band = sband->band; |
84 | n_bitrates = sband->n_bitrates; | 80 | n_bitrates = sband->n_bitrates; |
85 | 81 | ||
@@ -146,13 +142,11 @@ static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | |||
146 | } | 142 | } |
147 | 143 | ||
148 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | 144 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, |
149 | struct ieee80211_local *local, | 145 | struct ieee80211_supported_band *sband, |
150 | struct sta_info *sta) | 146 | struct ieee80211_sta *sta, |
147 | struct rc_pid_sta_info *spinfo) | ||
151 | { | 148 | { |
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
153 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | ||
154 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 149 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
155 | struct ieee80211_supported_band *sband; | ||
156 | u32 pf; | 150 | u32 pf; |
157 | s32 err_avg; | 151 | s32 err_avg; |
158 | u32 err_prop; | 152 | u32 err_prop; |
@@ -161,9 +155,6 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
161 | int adj, i, j, tmp; | 155 | int adj, i, j, tmp; |
162 | unsigned long period; | 156 | unsigned long period; |
163 | 157 | ||
164 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
165 | spinfo = sta->rate_ctrl_priv; | ||
166 | |||
167 | /* In case nothing happened during the previous control interval, turn | 158 | /* In case nothing happened during the previous control interval, turn |
168 | * the sharpening factor on. */ | 159 | * the sharpening factor on. */ |
169 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 160 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
@@ -179,11 +170,15 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
179 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
180 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
181 | else { | 172 | else { |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
182 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
183 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) | 177 | |
184 | mesh_plink_broken(sta); | 178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) |
179 | mesh_plink_broken(si); | ||
185 | pf <<= RC_PID_ARITH_SHIFT; | 180 | pf <<= RC_PID_ARITH_SHIFT; |
186 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
187 | >> RC_PID_ARITH_SHIFT; | 182 | >> RC_PID_ARITH_SHIFT; |
188 | } | 183 | } |
189 | 184 | ||
@@ -229,43 +224,25 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
229 | 224 | ||
230 | /* Change rate. */ | 225 | /* Change rate. */ |
231 | if (adj) | 226 | if (adj) |
232 | rate_control_pid_adjust_rate(local, sta, adj, rinfo); | 227 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); |
233 | } | 228 | } |
234 | 229 | ||
235 | static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | 230 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, |
231 | struct ieee80211_sta *sta, void *priv_sta, | ||
236 | struct sk_buff *skb) | 232 | struct sk_buff *skb) |
237 | { | 233 | { |
238 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
239 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
240 | struct ieee80211_sub_if_data *sdata; | ||
241 | struct rc_pid_info *pinfo = priv; | 234 | struct rc_pid_info *pinfo = priv; |
242 | struct sta_info *sta; | 235 | struct rc_pid_sta_info *spinfo = priv_sta; |
243 | struct rc_pid_sta_info *spinfo; | ||
244 | unsigned long period; | 236 | unsigned long period; |
245 | struct ieee80211_supported_band *sband; | ||
246 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
247 | 238 | ||
248 | rcu_read_lock(); | 239 | if (!spinfo) |
249 | 240 | return; | |
250 | sta = sta_info_get(local, hdr->addr1); | ||
251 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
252 | |||
253 | if (!sta) | ||
254 | goto unlock; | ||
255 | |||
256 | spinfo = sta->rate_ctrl_priv; | ||
257 | |||
258 | /* Don't update the state if we're not controlling the rate. */ | ||
259 | sdata = sta->sdata; | ||
260 | if (sdata->force_unicast_rateidx > -1) { | ||
261 | spinfo->txrate_idx = sdata->max_ratectrl_rateidx; | ||
262 | goto unlock; | ||
263 | } | ||
264 | 241 | ||
265 | /* Ignore all frames that were sent with a different rate than the rate | 242 | /* Ignore all frames that were sent with a different rate than the rate |
266 | * we currently advise mac80211 to use. */ | 243 | * we currently advise mac80211 to use. */ |
267 | if (info->tx_rate_idx != spinfo->txrate_idx) | 244 | if (info->tx_rate_idx != spinfo->txrate_idx) |
268 | goto unlock; | 245 | return; |
269 | 246 | ||
270 | spinfo->tx_num_xmit++; | 247 | spinfo->tx_num_xmit++; |
271 | 248 | ||
@@ -289,78 +266,63 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
289 | if (!period) | 266 | if (!period) |
290 | period = 1; | 267 | period = 1; |
291 | if (time_after(jiffies, spinfo->last_sample + period)) | 268 | if (time_after(jiffies, spinfo->last_sample + period)) |
292 | rate_control_pid_sample(pinfo, local, sta); | 269 | rate_control_pid_sample(pinfo, sband, sta, spinfo); |
293 | |||
294 | unlock: | ||
295 | rcu_read_unlock(); | ||
296 | } | 270 | } |
297 | 271 | ||
298 | static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | 272 | static void |
299 | struct ieee80211_supported_band *sband, | 273 | rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, |
300 | struct sk_buff *skb, | 274 | struct ieee80211_sta *sta, void *priv_sta, |
301 | struct rate_selection *sel) | 275 | struct sk_buff *skb, |
276 | struct rate_selection *sel) | ||
302 | { | 277 | { |
303 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
305 | struct ieee80211_sub_if_data *sdata; | 279 | struct rc_pid_sta_info *spinfo = priv_sta; |
306 | struct rc_pid_sta_info *spinfo; | ||
307 | struct sta_info *sta; | ||
308 | int rateidx; | 280 | int rateidx; |
309 | u16 fc; | 281 | u16 fc; |
310 | 282 | ||
311 | rcu_read_lock(); | ||
312 | |||
313 | sta = sta_info_get(local, hdr->addr1); | ||
314 | |||
315 | /* Send management frames and broadcast/multicast data using lowest | 283 | /* Send management frames and broadcast/multicast data using lowest |
316 | * rate. */ | 284 | * rate. */ |
317 | fc = le16_to_cpu(hdr->frame_control); | 285 | fc = le16_to_cpu(hdr->frame_control); |
318 | if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | 286 | if (!sta || !spinfo || |
319 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 287 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || |
320 | sel->rate_idx = rate_lowest_index(local, sband, sta); | 288 | is_multicast_ether_addr(hdr->addr1)) { |
321 | rcu_read_unlock(); | 289 | sel->rate_idx = rate_lowest_index(sband, sta); |
322 | return; | 290 | return; |
323 | } | 291 | } |
324 | 292 | ||
325 | /* If a forced rate is in effect, select it. */ | ||
326 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
327 | spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; | ||
328 | if (sdata->force_unicast_rateidx > -1) | ||
329 | spinfo->txrate_idx = sdata->force_unicast_rateidx; | ||
330 | |||
331 | rateidx = spinfo->txrate_idx; | 293 | rateidx = spinfo->txrate_idx; |
332 | 294 | ||
333 | if (rateidx >= sband->n_bitrates) | 295 | if (rateidx >= sband->n_bitrates) |
334 | rateidx = sband->n_bitrates - 1; | 296 | rateidx = sband->n_bitrates - 1; |
335 | 297 | ||
336 | rcu_read_unlock(); | ||
337 | |||
338 | sel->rate_idx = rateidx; | 298 | sel->rate_idx = rateidx; |
339 | 299 | ||
340 | #ifdef CONFIG_MAC80211_DEBUGFS | 300 | #ifdef CONFIG_MAC80211_DEBUGFS |
341 | rate_control_pid_event_tx_rate( | 301 | rate_control_pid_event_tx_rate(&spinfo->events, |
342 | &((struct rc_pid_sta_info *) sta->rate_ctrl_priv)->events, | ||
343 | rateidx, sband->bitrates[rateidx].bitrate); | 302 | rateidx, sband->bitrates[rateidx].bitrate); |
344 | #endif | 303 | #endif |
345 | } | 304 | } |
346 | 305 | ||
347 | static void rate_control_pid_rate_init(void *priv, void *priv_sta, | 306 | static void |
348 | struct ieee80211_local *local, | 307 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
349 | struct sta_info *sta) | 308 | struct ieee80211_sta *sta, void *priv_sta) |
350 | { | 309 | { |
310 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
311 | struct sta_info *si; | ||
312 | |||
351 | /* TODO: This routine should consider using RSSI from previous packets | 313 | /* TODO: This routine should consider using RSSI from previous packets |
352 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | 314 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. |
353 | * Until that method is implemented, we will use the lowest supported | 315 | * Until that method is implemented, we will use the lowest supported |
354 | * rate as a workaround. */ | 316 | * rate as a workaround. */ |
355 | struct ieee80211_supported_band *sband; | ||
356 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
357 | 317 | ||
358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 318 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
359 | spinfo->txrate_idx = rate_lowest_index(local, sband, sta); | 319 | /* HACK */ |
360 | sta->fail_avg = 0; | 320 | si = container_of(sta, struct sta_info, sta); |
321 | si->fail_avg = 0; | ||
361 | } | 322 | } |
362 | 323 | ||
363 | static void *rate_control_pid_alloc(struct ieee80211_local *local) | 324 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
325 | struct dentry *debugfsdir) | ||
364 | { | 326 | { |
365 | struct rc_pid_info *pinfo; | 327 | struct rc_pid_info *pinfo; |
366 | struct rc_pid_rateinfo *rinfo; | 328 | struct rc_pid_rateinfo *rinfo; |
@@ -371,7 +333,7 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
371 | struct rc_pid_debugfs_entries *de; | 333 | struct rc_pid_debugfs_entries *de; |
372 | #endif | 334 | #endif |
373 | 335 | ||
374 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 336 | sband = hw->wiphy->bands[hw->conf.channel->band]; |
375 | 337 | ||
376 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | 338 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); |
377 | if (!pinfo) | 339 | if (!pinfo) |
@@ -426,30 +388,28 @@ static void *rate_control_pid_alloc(struct ieee80211_local *local) | |||
426 | 388 | ||
427 | #ifdef CONFIG_MAC80211_DEBUGFS | 389 | #ifdef CONFIG_MAC80211_DEBUGFS |
428 | de = &pinfo->dentries; | 390 | de = &pinfo->dentries; |
429 | de->dir = debugfs_create_dir("rc80211_pid", | ||
430 | local->hw.wiphy->debugfsdir); | ||
431 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | 391 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, |
432 | de->dir, &pinfo->target); | 392 | debugfsdir, &pinfo->target); |
433 | de->sampling_period = debugfs_create_u32("sampling_period", | 393 | de->sampling_period = debugfs_create_u32("sampling_period", |
434 | S_IRUSR | S_IWUSR, de->dir, | 394 | S_IRUSR | S_IWUSR, debugfsdir, |
435 | &pinfo->sampling_period); | 395 | &pinfo->sampling_period); |
436 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | 396 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, |
437 | de->dir, &pinfo->coeff_p); | 397 | debugfsdir, &pinfo->coeff_p); |
438 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | 398 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, |
439 | de->dir, &pinfo->coeff_i); | 399 | debugfsdir, &pinfo->coeff_i); |
440 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | 400 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, |
441 | de->dir, &pinfo->coeff_d); | 401 | debugfsdir, &pinfo->coeff_d); |
442 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | 402 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", |
443 | S_IRUSR | S_IWUSR, de->dir, | 403 | S_IRUSR | S_IWUSR, debugfsdir, |
444 | &pinfo->smoothing_shift); | 404 | &pinfo->smoothing_shift); |
445 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | 405 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", |
446 | S_IRUSR | S_IWUSR, de->dir, | 406 | S_IRUSR | S_IWUSR, debugfsdir, |
447 | &pinfo->sharpen_factor); | 407 | &pinfo->sharpen_factor); |
448 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | 408 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", |
449 | S_IRUSR | S_IWUSR, de->dir, | 409 | S_IRUSR | S_IWUSR, debugfsdir, |
450 | &pinfo->sharpen_duration); | 410 | &pinfo->sharpen_duration); |
451 | de->norm_offset = debugfs_create_u32("norm_offset", | 411 | de->norm_offset = debugfs_create_u32("norm_offset", |
452 | S_IRUSR | S_IWUSR, de->dir, | 412 | S_IRUSR | S_IWUSR, debugfsdir, |
453 | &pinfo->norm_offset); | 413 | &pinfo->norm_offset); |
454 | #endif | 414 | #endif |
455 | 415 | ||
@@ -471,7 +431,6 @@ static void rate_control_pid_free(void *priv) | |||
471 | debugfs_remove(de->coeff_p); | 431 | debugfs_remove(de->coeff_p); |
472 | debugfs_remove(de->sampling_period); | 432 | debugfs_remove(de->sampling_period); |
473 | debugfs_remove(de->target); | 433 | debugfs_remove(de->target); |
474 | debugfs_remove(de->dir); | ||
475 | #endif | 434 | #endif |
476 | 435 | ||
477 | kfree(pinfo->rinfo); | 436 | kfree(pinfo->rinfo); |
@@ -482,7 +441,8 @@ static void rate_control_pid_clear(void *priv) | |||
482 | { | 441 | { |
483 | } | 442 | } |
484 | 443 | ||
485 | static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | 444 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, |
445 | gfp_t gfp) | ||
486 | { | 446 | { |
487 | struct rc_pid_sta_info *spinfo; | 447 | struct rc_pid_sta_info *spinfo; |
488 | 448 | ||
@@ -500,10 +460,10 @@ static void *rate_control_pid_alloc_sta(void *priv, gfp_t gfp) | |||
500 | return spinfo; | 460 | return spinfo; |
501 | } | 461 | } |
502 | 462 | ||
503 | static void rate_control_pid_free_sta(void *priv, void *priv_sta) | 463 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, |
464 | void *priv_sta) | ||
504 | { | 465 | { |
505 | struct rc_pid_sta_info *spinfo = priv_sta; | 466 | kfree(priv_sta); |
506 | kfree(spinfo); | ||
507 | } | 467 | } |
508 | 468 | ||
509 | static struct rate_control_ops mac80211_rcpid = { | 469 | static struct rate_control_ops mac80211_rcpid = { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 92d898b901e9..77e7b014872b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -650,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
650 | return result; | 650 | return result; |
651 | } | 651 | } |
652 | 652 | ||
653 | static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | 653 | static void ap_sta_ps_start(struct sta_info *sta) |
654 | { | 654 | { |
655 | struct ieee80211_sub_if_data *sdata; | 655 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
656 | DECLARE_MAC_BUF(mac); | 656 | DECLARE_MAC_BUF(mac); |
657 | 657 | ||
658 | sdata = sta->sdata; | ||
659 | |||
660 | atomic_inc(&sdata->bss->num_sta_ps); | 658 | atomic_inc(&sdata->bss->num_sta_ps); |
661 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 659 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
662 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 660 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
663 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 661 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
664 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 662 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
665 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 663 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
666 | } | 664 | } |
667 | 665 | ||
668 | static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | 666 | static int ap_sta_ps_end(struct sta_info *sta) |
669 | { | 667 | { |
670 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 668 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
669 | struct ieee80211_local *local = sdata->local; | ||
671 | struct sk_buff *skb; | 670 | struct sk_buff *skb; |
672 | int sent = 0; | 671 | int sent = 0; |
673 | struct ieee80211_sub_if_data *sdata; | ||
674 | struct ieee80211_tx_info *info; | 672 | struct ieee80211_tx_info *info; |
675 | DECLARE_MAC_BUF(mac); | 673 | DECLARE_MAC_BUF(mac); |
676 | 674 | ||
677 | sdata = sta->sdata; | ||
678 | |||
679 | atomic_dec(&sdata->bss->num_sta_ps); | 675 | atomic_dec(&sdata->bss->num_sta_ps); |
680 | 676 | ||
681 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); | 677 | clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); |
@@ -685,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
685 | 681 | ||
686 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 682 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
687 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 683 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
688 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); | 684 | sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
689 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 685 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
690 | 686 | ||
691 | /* Send all buffered frames to the station */ | 687 | /* Send all buffered frames to the station */ |
@@ -701,7 +697,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
701 | sent++; | 697 | sent++; |
702 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
703 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " | 699 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " |
704 | "since STA not sleeping anymore\n", dev->name, | 700 | "since STA not sleeping anymore\n", sdata->dev->name, |
705 | print_mac(mac, sta->sta.addr), sta->sta.aid); | 701 | print_mac(mac, sta->sta.addr), sta->sta.aid); |
706 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 702 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
707 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 703 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
@@ -715,7 +711,6 @@ static ieee80211_rx_result debug_noinline | |||
715 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 711 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
716 | { | 712 | { |
717 | struct sta_info *sta = rx->sta; | 713 | struct sta_info *sta = rx->sta; |
718 | struct net_device *dev = rx->dev; | ||
719 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 714 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
720 | 715 | ||
721 | if (!sta) | 716 | if (!sta) |
@@ -757,10 +752,10 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
757 | * exchange sequence */ | 752 | * exchange sequence */ |
758 | if (test_sta_flags(sta, WLAN_STA_PS) && | 753 | if (test_sta_flags(sta, WLAN_STA_PS) && |
759 | !ieee80211_has_pm(hdr->frame_control)) | 754 | !ieee80211_has_pm(hdr->frame_control)) |
760 | rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); | 755 | rx->sent_ps_buffered += ap_sta_ps_end(sta); |
761 | else if (!test_sta_flags(sta, WLAN_STA_PS) && | 756 | else if (!test_sta_flags(sta, WLAN_STA_PS) && |
762 | ieee80211_has_pm(hdr->frame_control)) | 757 | ieee80211_has_pm(hdr->frame_control)) |
763 | ap_sta_ps_start(dev, sta); | 758 | ap_sta_ps_start(sta); |
764 | } | 759 | } |
765 | 760 | ||
766 | /* Drop data::nullfunc frames silently, since they are used only to | 761 | /* Drop data::nullfunc frames silently, since they are used only to |
@@ -1112,10 +1107,6 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1112 | 1107 | ||
1113 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1108 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1114 | 1109 | ||
1115 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
1116 | hdrlen += ieee80211_get_mesh_hdrlen( | ||
1117 | (struct ieee80211s_hdr *) (skb->data + hdrlen)); | ||
1118 | |||
1119 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet | 1110 | /* convert IEEE 802.11 header + possible LLC headers into Ethernet |
1120 | * header | 1111 | * header |
1121 | * IEEE 802.11 address fields: | 1112 | * IEEE 802.11 address fields: |
@@ -1139,6 +1130,15 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1139 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && | 1130 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1140 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) | 1131 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1141 | return -1; | 1132 | return -1; |
1133 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1134 | struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *) | ||
1135 | (skb->data + hdrlen); | ||
1136 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
1137 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | ||
1138 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | ||
1139 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | ||
1140 | } | ||
1141 | } | ||
1142 | break; | 1142 | break; |
1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
@@ -1379,7 +1379,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1379 | return RX_QUEUED; | 1379 | return RX_QUEUED; |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | static ieee80211_rx_result debug_noinline | 1382 | static ieee80211_rx_result |
1383 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | 1383 | ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) |
1384 | { | 1384 | { |
1385 | struct ieee80211_hdr *hdr; | 1385 | struct ieee80211_hdr *hdr; |
@@ -1398,6 +1398,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1398 | /* illegal frame */ | 1398 | /* illegal frame */ |
1399 | return RX_DROP_MONITOR; | 1399 | return RX_DROP_MONITOR; |
1400 | 1400 | ||
1401 | if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ | ||
1402 | struct ieee80211_sub_if_data *sdata; | ||
1403 | struct mesh_path *mppath; | ||
1404 | |||
1405 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1406 | rcu_read_lock(); | ||
1407 | mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata); | ||
1408 | if (!mppath) { | ||
1409 | mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata); | ||
1410 | } else { | ||
1411 | spin_lock_bh(&mppath->state_lock); | ||
1412 | mppath->exp_time = jiffies; | ||
1413 | if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0) | ||
1414 | memcpy(mppath->mpp, hdr->addr4, ETH_ALEN); | ||
1415 | spin_unlock_bh(&mppath->state_lock); | ||
1416 | } | ||
1417 | rcu_read_unlock(); | ||
1418 | } | ||
1419 | |||
1401 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1420 | if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) |
1402 | return RX_CONTINUE; | 1421 | return RX_CONTINUE; |
1403 | 1422 | ||
@@ -1538,7 +1557,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1538 | */ | 1557 | */ |
1539 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1558 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1540 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1559 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1541 | return RX_DROP_MONITOR; | 1560 | return RX_CONTINUE; |
1542 | 1561 | ||
1543 | switch (mgmt->u.action.category) { | 1562 | switch (mgmt->u.action.category) { |
1544 | case WLAN_CATEGORY_BACK: | 1563 | case WLAN_CATEGORY_BACK: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9774ac2e0f7..9b72d15bc8dc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -93,8 +93,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) |
97 | const u8 *addr) | ||
98 | { | 97 | { |
99 | struct sta_info *sta; | 98 | struct sta_info *sta; |
100 | 99 | ||
@@ -107,12 +106,6 @@ static struct sta_info *__sta_info_find(struct ieee80211_local *local, | |||
107 | return sta; | 106 | return sta; |
108 | } | 107 | } |
109 | 108 | ||
110 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr) | ||
111 | { | ||
112 | return __sta_info_find(local, addr); | ||
113 | } | ||
114 | EXPORT_SYMBOL(sta_info_get); | ||
115 | |||
116 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 109 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, |
117 | struct net_device *dev) | 110 | struct net_device *dev) |
118 | { | 111 | { |
@@ -146,7 +139,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
146 | { | 139 | { |
147 | DECLARE_MAC_BUF(mbuf); | 140 | DECLARE_MAC_BUF(mbuf); |
148 | 141 | ||
149 | rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv); | 142 | rate_control_free_sta(sta); |
150 | rate_control_put(sta->rate_ctrl); | 143 | rate_control_put(sta->rate_ctrl); |
151 | 144 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 145 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -244,7 +237,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
244 | 237 | ||
245 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 238 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); |
246 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | 239 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, |
247 | gfp); | 240 | &sta->sta, gfp); |
248 | if (!sta->rate_ctrl_priv) { | 241 | if (!sta->rate_ctrl_priv) { |
249 | rate_control_put(sta->rate_ctrl); | 242 | rate_control_put(sta->rate_ctrl); |
250 | kfree(sta); | 243 | kfree(sta); |
@@ -308,7 +301,7 @@ int sta_info_insert(struct sta_info *sta) | |||
308 | 301 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 302 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 303 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->sta.addr)) { | 304 | if (sta_info_get(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 305 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 306 | err = -EEXIST; |
314 | goto out_free; | 307 | goto out_free; |
@@ -834,7 +827,7 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
834 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | 827 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, |
835 | const u8 *addr) | 828 | const u8 *addr) |
836 | { | 829 | { |
837 | struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); | 830 | struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); |
838 | 831 | ||
839 | if (!sta) | 832 | if (!sta) |
840 | return NULL; | 833 | return NULL; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index daedfa9e1c63..a6b51862a89d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -189,7 +189,6 @@ struct sta_ampdu_mlme { | |||
189 | * @last_qual: qual of last received frame from this STA | 189 | * @last_qual: qual of last received frame from this STA |
190 | * @last_noise: noise of last received frame from this STA | 190 | * @last_noise: noise of last received frame from this STA |
191 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) | 191 | * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) |
192 | * @wme_rx_queue: TBD | ||
193 | * @tx_filtered_count: TBD | 192 | * @tx_filtered_count: TBD |
194 | * @tx_retry_failed: TBD | 193 | * @tx_retry_failed: TBD |
195 | * @tx_retry_count: TBD | 194 | * @tx_retry_count: TBD |
@@ -199,7 +198,6 @@ struct sta_ampdu_mlme { | |||
199 | * @tx_fragments: number of transmitted MPDUs | 198 | * @tx_fragments: number of transmitted MPDUs |
200 | * @last_txrate_idx: Index of the last used transmit rate | 199 | * @last_txrate_idx: Index of the last used transmit rate |
201 | * @tid_seq: TBD | 200 | * @tid_seq: TBD |
202 | * @wme_tx_queue: TBD | ||
203 | * @ampdu_mlme: TBD | 201 | * @ampdu_mlme: TBD |
204 | * @timer_to_tid: identity mapping to ID timers | 202 | * @timer_to_tid: identity mapping to ID timers |
205 | * @tid_to_tx_q: map tid to tx queue | 203 | * @tid_to_tx_q: map tid to tx queue |
@@ -258,9 +256,6 @@ struct sta_info { | |||
258 | int last_qual; | 256 | int last_qual; |
259 | int last_noise; | 257 | int last_noise; |
260 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; | 258 | __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; |
261 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
262 | unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; | ||
263 | #endif | ||
264 | 259 | ||
265 | /* Updated from TX status path only, no locking requirements */ | 260 | /* Updated from TX status path only, no locking requirements */ |
266 | unsigned long tx_filtered_count; | 261 | unsigned long tx_filtered_count; |
@@ -274,9 +269,6 @@ struct sta_info { | |||
274 | unsigned long tx_fragments; | 269 | unsigned long tx_fragments; |
275 | unsigned int last_txrate_idx; | 270 | unsigned int last_txrate_idx; |
276 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 271 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
277 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
278 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | ||
279 | #endif | ||
280 | 272 | ||
281 | /* | 273 | /* |
282 | * Aggregation information, locked with lock. | 274 | * Aggregation information, locked with lock. |
@@ -307,10 +299,6 @@ struct sta_info { | |||
307 | struct dentry *num_ps_buf_frames; | 299 | struct dentry *num_ps_buf_frames; |
308 | struct dentry *inactive_ms; | 300 | struct dentry *inactive_ms; |
309 | struct dentry *last_seq_ctrl; | 301 | struct dentry *last_seq_ctrl; |
310 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | ||
311 | struct dentry *wme_rx_queue; | ||
312 | struct dentry *wme_tx_queue; | ||
313 | #endif | ||
314 | struct dentry *agg_status; | 302 | struct dentry *agg_status; |
315 | } debugfs; | 303 | } debugfs; |
316 | #endif | 304 | #endif |
@@ -416,7 +404,7 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
416 | /* | 404 | /* |
417 | * Get a STA info, must have be under RCU read lock. | 405 | * Get a STA info, must have be under RCU read lock. |
418 | */ | 406 | */ |
419 | struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr); | 407 | struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); |
420 | /* | 408 | /* |
421 | * Get STA info by index, BROKEN! | 409 | * Get STA info by index, BROKEN! |
422 | */ | 410 | */ |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 20d683641b42..0cc2e23f082c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -165,11 +165,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
165 | return cpu_to_le16(dur); | 165 | return cpu_to_le16(dur); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int inline is_ieee80211_device(struct net_device *dev, | 168 | static int inline is_ieee80211_device(struct ieee80211_local *local, |
169 | struct net_device *master) | 169 | struct net_device *dev) |
170 | { | 170 | { |
171 | return (wdev_priv(dev->ieee80211_ptr) == | 171 | return local == wdev_priv(dev->ieee80211_ptr); |
172 | wdev_priv(master->ieee80211_ptr)); | ||
173 | } | 172 | } |
174 | 173 | ||
175 | /* tx handlers */ | 174 | /* tx handlers */ |
@@ -447,7 +446,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
447 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 446 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
448 | 447 | ||
449 | if (likely(tx->rate_idx < 0)) { | 448 | if (likely(tx->rate_idx < 0)) { |
450 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 449 | rate_control_get_rate(tx->sdata, sband, tx->sta, |
450 | tx->skb, &rsel); | ||
451 | if (tx->sta) | 451 | if (tx->sta) |
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | 452 | tx->sta->last_txrate_idx = rsel.rate_idx; |
453 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
@@ -1001,14 +1001,14 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1001 | /* | 1001 | /* |
1002 | * NB: @tx is uninitialised when passed in here | 1002 | * NB: @tx is uninitialised when passed in here |
1003 | */ | 1003 | */ |
1004 | static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | 1004 | static int ieee80211_tx_prepare(struct ieee80211_local *local, |
1005 | struct sk_buff *skb, | 1005 | struct ieee80211_tx_data *tx, |
1006 | struct net_device *mdev) | 1006 | struct sk_buff *skb) |
1007 | { | 1007 | { |
1008 | struct net_device *dev; | 1008 | struct net_device *dev; |
1009 | 1009 | ||
1010 | dev = dev_get_by_index(&init_net, skb->iif); | 1010 | dev = dev_get_by_index(&init_net, skb->iif); |
1011 | if (unlikely(dev && !is_ieee80211_device(dev, mdev))) { | 1011 | if (unlikely(dev && !is_ieee80211_device(local, dev))) { |
1012 | dev_put(dev); | 1012 | dev_put(dev); |
1013 | dev = NULL; | 1013 | dev = NULL; |
1014 | } | 1014 | } |
@@ -1258,6 +1258,8 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, |
1259 | struct net_device *dev) | 1259 | struct net_device *dev) |
1260 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
1262 | struct ieee80211_local *local = mpriv->local; | ||
1261 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1263 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1262 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1264 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1263 | struct net_device *odev = NULL; | 1265 | struct net_device *odev = NULL; |
@@ -1273,7 +1275,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1273 | 1275 | ||
1274 | if (skb->iif) | 1276 | if (skb->iif) |
1275 | odev = dev_get_by_index(&init_net, skb->iif); | 1277 | odev = dev_get_by_index(&init_net, skb->iif); |
1276 | if (unlikely(odev && !is_ieee80211_device(odev, dev))) { | 1278 | if (unlikely(odev && !is_ieee80211_device(local, odev))) { |
1277 | dev_put(odev); | 1279 | dev_put(odev); |
1278 | odev = NULL; | 1280 | odev = NULL; |
1279 | } | 1281 | } |
@@ -1449,8 +1451,8 @@ fail: | |||
1449 | int ieee80211_subif_start_xmit(struct sk_buff *skb, | 1451 | int ieee80211_subif_start_xmit(struct sk_buff *skb, |
1450 | struct net_device *dev) | 1452 | struct net_device *dev) |
1451 | { | 1453 | { |
1452 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1454 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1453 | struct ieee80211_sub_if_data *sdata; | 1455 | struct ieee80211_local *local = sdata->local; |
1454 | int ret = 1, head_need; | 1456 | int ret = 1, head_need; |
1455 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1457 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1456 | __le16 fc; | 1458 | __le16 fc; |
@@ -1462,7 +1464,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1462 | struct sta_info *sta; | 1464 | struct sta_info *sta; |
1463 | u32 sta_flags = 0; | 1465 | u32 sta_flags = 0; |
1464 | 1466 | ||
1465 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1466 | if (unlikely(skb->len < ETH_HLEN)) { | 1467 | if (unlikely(skb->len < ETH_HLEN)) { |
1467 | ret = 0; | 1468 | ret = 0; |
1468 | goto fail; | 1469 | goto fail; |
@@ -1498,18 +1499,50 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1498 | #ifdef CONFIG_MAC80211_MESH | 1499 | #ifdef CONFIG_MAC80211_MESH |
1499 | case NL80211_IFTYPE_MESH_POINT: | 1500 | case NL80211_IFTYPE_MESH_POINT: |
1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1501 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1501 | /* RA TA DA SA */ | ||
1502 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1502 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1507 | /* Do not send frames with mesh_ttl == 0 */ | 1503 | /* Do not send frames with mesh_ttl == 0 */ |
1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1504 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1509 | ret = 0; | 1505 | ret = 0; |
1510 | goto fail; | 1506 | goto fail; |
1511 | } | 1507 | } |
1512 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | 1508 | memset(&mesh_hdr, 0, sizeof(mesh_hdr)); |
1509 | |||
1510 | if (compare_ether_addr(dev->dev_addr, | ||
1511 | skb->data + ETH_ALEN) == 0) { | ||
1512 | /* RA TA DA SA */ | ||
1513 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1514 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1515 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1516 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | ||
1517 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata); | ||
1518 | } else { | ||
1519 | /* packet from other interface */ | ||
1520 | struct mesh_path *mppath; | ||
1521 | |||
1522 | memset(hdr.addr1, 0, ETH_ALEN); | ||
1523 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | ||
1524 | memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN); | ||
1525 | |||
1526 | if (is_multicast_ether_addr(skb->data)) | ||
1527 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | ||
1528 | else { | ||
1529 | rcu_read_lock(); | ||
1530 | mppath = mpp_path_lookup(skb->data, sdata); | ||
1531 | if (mppath) | ||
1532 | memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); | ||
1533 | else | ||
1534 | memset(hdr.addr3, 0xff, ETH_ALEN); | ||
1535 | rcu_read_unlock(); | ||
1536 | } | ||
1537 | |||
1538 | mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6; | ||
1539 | mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | ||
1540 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum); | ||
1541 | memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN); | ||
1542 | memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN); | ||
1543 | sdata->u.mesh.mesh_seqnum++; | ||
1544 | meshhdrlen = 18; | ||
1545 | } | ||
1513 | hdrlen = 30; | 1546 | hdrlen = 30; |
1514 | break; | 1547 | break; |
1515 | #endif | 1548 | #endif |
@@ -1923,7 +1956,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1923 | skb->do_not_encrypt = 1; | 1956 | skb->do_not_encrypt = 1; |
1924 | 1957 | ||
1925 | info->band = band; | 1958 | info->band = band; |
1926 | rate_control_get_rate(local->mdev, sband, skb, &rsel); | 1959 | rate_control_get_rate(sdata, sband, NULL, skb, &rsel); |
1927 | 1960 | ||
1928 | if (unlikely(rsel.rate_idx < 0)) { | 1961 | if (unlikely(rsel.rate_idx < 0)) { |
1929 | if (net_ratelimit()) { | 1962 | if (net_ratelimit()) { |
@@ -2032,7 +2065,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2032 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2065 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
2033 | } | 2066 | } |
2034 | 2067 | ||
2035 | if (!ieee80211_tx_prepare(&tx, skb, local->mdev)) | 2068 | if (!ieee80211_tx_prepare(local, &tx, skb)) |
2036 | break; | 2069 | break; |
2037 | dev_kfree_skb_any(skb); | 2070 | dev_kfree_skb_any(skb); |
2038 | } | 2071 | } |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index c703f8b44e92..139b5f267b34 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -73,9 +73,8 @@ static int wme_downgrade_ac(struct sk_buff *skb) | |||
73 | 73 | ||
74 | 74 | ||
75 | /* Indicate which queue to use. */ | 75 | /* Indicate which queue to use. */ |
76 | static u16 classify80211(struct sk_buff *skb, struct net_device *dev) | 76 | static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb) |
77 | { | 77 | { |
78 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
79 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 78 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
80 | 79 | ||
81 | if (!ieee80211_is_data(hdr->frame_control)) { | 80 | if (!ieee80211_is_data(hdr->frame_control)) { |
@@ -113,14 +112,15 @@ static u16 classify80211(struct sk_buff *skb, struct net_device *dev) | |||
113 | 112 | ||
114 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) | 113 | u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb) |
115 | { | 114 | { |
115 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | ||
116 | struct ieee80211_local *local = mpriv->local; | ||
116 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 117 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
117 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
118 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 118 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
119 | struct sta_info *sta; | 119 | struct sta_info *sta; |
120 | u16 queue; | 120 | u16 queue; |
121 | u8 tid; | 121 | u8 tid; |
122 | 122 | ||
123 | queue = classify80211(skb, dev); | 123 | queue = classify80211(local, skb); |
124 | if (unlikely(queue >= local->hw.queues)) | 124 | if (unlikely(queue >= local->hw.queues)) |
125 | queue = local->hw.queues - 1; | 125 | queue = local->hw.queues - 1; |
126 | 126 | ||
diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index 9f328593287e..307a2c3c2df4 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c | |||
@@ -136,17 +136,19 @@ static void localtime_3(struct xtm *r, time_t time) | |||
136 | * from w repeatedly while counting.) | 136 | * from w repeatedly while counting.) |
137 | */ | 137 | */ |
138 | if (is_leap(year)) { | 138 | if (is_leap(year)) { |
139 | /* use days_since_leapyear[] in a leap year */ | ||
139 | for (i = ARRAY_SIZE(days_since_leapyear) - 1; | 140 | for (i = ARRAY_SIZE(days_since_leapyear) - 1; |
140 | i > 0 && days_since_year[i] > w; --i) | 141 | i > 0 && days_since_leapyear[i] > w; --i) |
141 | /* just loop */; | 142 | /* just loop */; |
143 | r->monthday = w - days_since_leapyear[i] + 1; | ||
142 | } else { | 144 | } else { |
143 | for (i = ARRAY_SIZE(days_since_year) - 1; | 145 | for (i = ARRAY_SIZE(days_since_year) - 1; |
144 | i > 0 && days_since_year[i] > w; --i) | 146 | i > 0 && days_since_year[i] > w; --i) |
145 | /* just loop */; | 147 | /* just loop */; |
148 | r->monthday = w - days_since_year[i] + 1; | ||
146 | } | 149 | } |
147 | 150 | ||
148 | r->month = i + 1; | 151 | r->month = i + 1; |
149 | r->monthday = w - days_since_year[i] + 1; | ||
150 | return; | 152 | return; |
151 | } | 153 | } |
152 | 154 | ||
diff --git a/net/phonet/Kconfig b/net/phonet/Kconfig new file mode 100644 index 000000000000..51a5669573f2 --- /dev/null +++ b/net/phonet/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | # | ||
2 | # Phonet protocol | ||
3 | # | ||
4 | |||
5 | config PHONET | ||
6 | tristate "Phonet protocols family" | ||
7 | help | ||
8 | The Phone Network protocol (PhoNet) is a packet-oriented | ||
9 | communication protocol developped by Nokia for use with its modems. | ||
10 | |||
11 | This is required for Maemo to use cellular data connectivity (if | ||
12 | supported). It can also be used to control Nokia phones | ||
13 | from a Linux computer, although AT commands may be easier to use. | ||
14 | |||
15 | To compile this driver as a module, choose M here: the module | ||
16 | will be called phonet. If unsure, say N. | ||
diff --git a/net/phonet/Makefile b/net/phonet/Makefile new file mode 100644 index 000000000000..d62bbba649b3 --- /dev/null +++ b/net/phonet/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | obj-$(CONFIG_PHONET) += phonet.o pn_pep.o | ||
2 | |||
3 | phonet-objs := \ | ||
4 | pn_dev.o \ | ||
5 | pn_netlink.o \ | ||
6 | socket.o \ | ||
7 | datagram.o \ | ||
8 | sysctl.o \ | ||
9 | af_phonet.o | ||
10 | |||
11 | pn_pep-objs := pep.o pep-gprs.o | ||
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c new file mode 100644 index 000000000000..9e9c6fce11aa --- /dev/null +++ b/net/phonet/af_phonet.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * File: af_phonet.c | ||
3 | * | ||
4 | * Phonet protocols family | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * Original author: Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <asm/unaligned.h> | ||
29 | #include <net/sock.h> | ||
30 | |||
31 | #include <linux/if_phonet.h> | ||
32 | #include <linux/phonet.h> | ||
33 | #include <net/phonet/phonet.h> | ||
34 | #include <net/phonet/pn_dev.h> | ||
35 | |||
36 | static struct net_proto_family phonet_proto_family; | ||
37 | static struct phonet_protocol *phonet_proto_get(int protocol); | ||
38 | static inline void phonet_proto_put(struct phonet_protocol *pp); | ||
39 | |||
40 | /* protocol family functions */ | ||
41 | |||
42 | static int pn_socket_create(struct net *net, struct socket *sock, int protocol) | ||
43 | { | ||
44 | struct sock *sk; | ||
45 | struct pn_sock *pn; | ||
46 | struct phonet_protocol *pnp; | ||
47 | int err; | ||
48 | |||
49 | if (net != &init_net) | ||
50 | return -EAFNOSUPPORT; | ||
51 | |||
52 | if (!capable(CAP_SYS_ADMIN)) | ||
53 | return -EPERM; | ||
54 | |||
55 | if (protocol == 0) { | ||
56 | /* Default protocol selection */ | ||
57 | switch (sock->type) { | ||
58 | case SOCK_DGRAM: | ||
59 | protocol = PN_PROTO_PHONET; | ||
60 | break; | ||
61 | case SOCK_SEQPACKET: | ||
62 | protocol = PN_PROTO_PIPE; | ||
63 | break; | ||
64 | default: | ||
65 | return -EPROTONOSUPPORT; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | pnp = phonet_proto_get(protocol); | ||
70 | #ifdef CONFIG_KMOD | ||
71 | if (pnp == NULL && | ||
72 | request_module("net-pf-%d-proto-%d", PF_PHONET, protocol) == 0) | ||
73 | pnp = phonet_proto_get(protocol); | ||
74 | #endif | ||
75 | if (pnp == NULL) | ||
76 | return -EPROTONOSUPPORT; | ||
77 | if (sock->type != pnp->sock_type) { | ||
78 | err = -EPROTONOSUPPORT; | ||
79 | goto out; | ||
80 | } | ||
81 | |||
82 | sk = sk_alloc(net, PF_PHONET, GFP_KERNEL, pnp->prot); | ||
83 | if (sk == NULL) { | ||
84 | err = -ENOMEM; | ||
85 | goto out; | ||
86 | } | ||
87 | |||
88 | sock_init_data(sock, sk); | ||
89 | sock->state = SS_UNCONNECTED; | ||
90 | sock->ops = pnp->ops; | ||
91 | sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
92 | sk->sk_protocol = protocol; | ||
93 | pn = pn_sk(sk); | ||
94 | pn->sobject = 0; | ||
95 | pn->resource = 0; | ||
96 | sk->sk_prot->init(sk); | ||
97 | err = 0; | ||
98 | |||
99 | out: | ||
100 | phonet_proto_put(pnp); | ||
101 | return err; | ||
102 | } | ||
103 | |||
104 | static struct net_proto_family phonet_proto_family = { | ||
105 | .family = PF_PHONET, | ||
106 | .create = pn_socket_create, | ||
107 | .owner = THIS_MODULE, | ||
108 | }; | ||
109 | |||
110 | /* Phonet device header operations */ | ||
111 | static int pn_header_create(struct sk_buff *skb, struct net_device *dev, | ||
112 | unsigned short type, const void *daddr, | ||
113 | const void *saddr, unsigned len) | ||
114 | { | ||
115 | u8 *media = skb_push(skb, 1); | ||
116 | |||
117 | if (type != ETH_P_PHONET) | ||
118 | return -1; | ||
119 | |||
120 | if (!saddr) | ||
121 | saddr = dev->dev_addr; | ||
122 | *media = *(const u8 *)saddr; | ||
123 | return 1; | ||
124 | } | ||
125 | |||
126 | static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr) | ||
127 | { | ||
128 | const u8 *media = skb_mac_header(skb); | ||
129 | *haddr = *media; | ||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | struct header_ops phonet_header_ops = { | ||
134 | .create = pn_header_create, | ||
135 | .parse = pn_header_parse, | ||
136 | }; | ||
137 | EXPORT_SYMBOL(phonet_header_ops); | ||
138 | |||
139 | /* | ||
140 | * Prepends an ISI header and sends a datagram. | ||
141 | */ | ||
142 | static int pn_send(struct sk_buff *skb, struct net_device *dev, | ||
143 | u16 dst, u16 src, u8 res, u8 irq) | ||
144 | { | ||
145 | struct phonethdr *ph; | ||
146 | int err; | ||
147 | |||
148 | if (skb->len + 2 > 0xffff) { | ||
149 | /* Phonet length field would overflow */ | ||
150 | err = -EMSGSIZE; | ||
151 | goto drop; | ||
152 | } | ||
153 | |||
154 | skb_reset_transport_header(skb); | ||
155 | WARN_ON(skb_headroom(skb) & 1); /* HW assumes word alignment */ | ||
156 | skb_push(skb, sizeof(struct phonethdr)); | ||
157 | skb_reset_network_header(skb); | ||
158 | ph = pn_hdr(skb); | ||
159 | ph->pn_rdev = pn_dev(dst); | ||
160 | ph->pn_sdev = pn_dev(src); | ||
161 | ph->pn_res = res; | ||
162 | ph->pn_length = __cpu_to_be16(skb->len + 2 - sizeof(*ph)); | ||
163 | ph->pn_robj = pn_obj(dst); | ||
164 | ph->pn_sobj = pn_obj(src); | ||
165 | |||
166 | skb->protocol = htons(ETH_P_PHONET); | ||
167 | skb->priority = 0; | ||
168 | skb->dev = dev; | ||
169 | |||
170 | if (pn_addr(src) == pn_addr(dst)) { | ||
171 | skb_reset_mac_header(skb); | ||
172 | skb->pkt_type = PACKET_LOOPBACK; | ||
173 | skb_orphan(skb); | ||
174 | if (irq) | ||
175 | netif_rx(skb); | ||
176 | else | ||
177 | netif_rx_ni(skb); | ||
178 | err = 0; | ||
179 | } else { | ||
180 | err = dev_hard_header(skb, dev, ntohs(skb->protocol), | ||
181 | NULL, NULL, skb->len); | ||
182 | if (err < 0) { | ||
183 | err = -EHOSTUNREACH; | ||
184 | goto drop; | ||
185 | } | ||
186 | err = dev_queue_xmit(skb); | ||
187 | } | ||
188 | |||
189 | return err; | ||
190 | drop: | ||
191 | kfree_skb(skb); | ||
192 | return err; | ||
193 | } | ||
194 | |||
195 | static int pn_raw_send(const void *data, int len, struct net_device *dev, | ||
196 | u16 dst, u16 src, u8 res) | ||
197 | { | ||
198 | struct sk_buff *skb = alloc_skb(MAX_PHONET_HEADER + len, GFP_ATOMIC); | ||
199 | if (skb == NULL) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | skb_reserve(skb, MAX_PHONET_HEADER); | ||
203 | __skb_put(skb, len); | ||
204 | skb_copy_to_linear_data(skb, data, len); | ||
205 | return pn_send(skb, dev, dst, src, res, 1); | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * Create a Phonet header for the skb and send it out. Returns | ||
210 | * non-zero error code if failed. The skb is freed then. | ||
211 | */ | ||
212 | int pn_skb_send(struct sock *sk, struct sk_buff *skb, | ||
213 | const struct sockaddr_pn *target) | ||
214 | { | ||
215 | struct net_device *dev; | ||
216 | struct pn_sock *pn = pn_sk(sk); | ||
217 | int err; | ||
218 | u16 src; | ||
219 | u8 daddr = pn_sockaddr_get_addr(target), saddr = PN_NO_ADDR; | ||
220 | |||
221 | err = -EHOSTUNREACH; | ||
222 | if (sk->sk_bound_dev_if) | ||
223 | dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); | ||
224 | else | ||
225 | dev = phonet_device_get(sock_net(sk)); | ||
226 | if (!dev || !(dev->flags & IFF_UP)) | ||
227 | goto drop; | ||
228 | |||
229 | saddr = phonet_address_get(dev, daddr); | ||
230 | if (saddr == PN_NO_ADDR) | ||
231 | goto drop; | ||
232 | |||
233 | src = pn->sobject; | ||
234 | if (!pn_addr(src)) | ||
235 | src = pn_object(saddr, pn_obj(src)); | ||
236 | |||
237 | err = pn_send(skb, dev, pn_sockaddr_get_object(target), | ||
238 | src, pn_sockaddr_get_resource(target), 0); | ||
239 | dev_put(dev); | ||
240 | return err; | ||
241 | |||
242 | drop: | ||
243 | kfree_skb(skb); | ||
244 | if (dev) | ||
245 | dev_put(dev); | ||
246 | return err; | ||
247 | } | ||
248 | EXPORT_SYMBOL(pn_skb_send); | ||
249 | |||
250 | /* Do not send an error message in response to an error message */ | ||
251 | static inline int can_respond(struct sk_buff *skb) | ||
252 | { | ||
253 | const struct phonethdr *ph; | ||
254 | const struct phonetmsg *pm; | ||
255 | u8 submsg_id; | ||
256 | |||
257 | if (!pskb_may_pull(skb, 3)) | ||
258 | return 0; | ||
259 | |||
260 | ph = pn_hdr(skb); | ||
261 | if (phonet_address_get(skb->dev, ph->pn_rdev) != ph->pn_rdev) | ||
262 | return 0; /* we are not the destination */ | ||
263 | if (ph->pn_res == PN_PREFIX && !pskb_may_pull(skb, 5)) | ||
264 | return 0; | ||
265 | |||
266 | ph = pn_hdr(skb); /* re-acquires the pointer */ | ||
267 | pm = pn_msg(skb); | ||
268 | if (pm->pn_msg_id != PN_COMMON_MESSAGE) | ||
269 | return 1; | ||
270 | submsg_id = (ph->pn_res == PN_PREFIX) | ||
271 | ? pm->pn_e_submsg_id : pm->pn_submsg_id; | ||
272 | if (submsg_id != PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP && | ||
273 | pm->pn_e_submsg_id != PN_COMM_SERVICE_NOT_IDENTIFIED_RESP) | ||
274 | return 1; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int send_obj_unreachable(struct sk_buff *rskb) | ||
279 | { | ||
280 | const struct phonethdr *oph = pn_hdr(rskb); | ||
281 | const struct phonetmsg *opm = pn_msg(rskb); | ||
282 | struct phonetmsg resp; | ||
283 | |||
284 | memset(&resp, 0, sizeof(resp)); | ||
285 | resp.pn_trans_id = opm->pn_trans_id; | ||
286 | resp.pn_msg_id = PN_COMMON_MESSAGE; | ||
287 | if (oph->pn_res == PN_PREFIX) { | ||
288 | resp.pn_e_res_id = opm->pn_e_res_id; | ||
289 | resp.pn_e_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP; | ||
290 | resp.pn_e_orig_msg_id = opm->pn_msg_id; | ||
291 | resp.pn_e_status = 0; | ||
292 | } else { | ||
293 | resp.pn_submsg_id = PN_COMM_ISA_ENTITY_NOT_REACHABLE_RESP; | ||
294 | resp.pn_orig_msg_id = opm->pn_msg_id; | ||
295 | resp.pn_status = 0; | ||
296 | } | ||
297 | return pn_raw_send(&resp, sizeof(resp), rskb->dev, | ||
298 | pn_object(oph->pn_sdev, oph->pn_sobj), | ||
299 | pn_object(oph->pn_rdev, oph->pn_robj), | ||
300 | oph->pn_res); | ||
301 | } | ||
302 | |||
303 | static int send_reset_indications(struct sk_buff *rskb) | ||
304 | { | ||
305 | struct phonethdr *oph = pn_hdr(rskb); | ||
306 | static const u8 data[4] = { | ||
307 | 0x00 /* trans ID */, 0x10 /* subscribe msg */, | ||
308 | 0x00 /* subscription count */, 0x00 /* dummy */ | ||
309 | }; | ||
310 | |||
311 | return pn_raw_send(data, sizeof(data), rskb->dev, | ||
312 | pn_object(oph->pn_sdev, 0x00), | ||
313 | pn_object(oph->pn_rdev, oph->pn_robj), 0x10); | ||
314 | } | ||
315 | |||
316 | |||
317 | /* packet type functions */ | ||
318 | |||
319 | /* | ||
320 | * Stuff received packets to associated sockets. | ||
321 | * On error, returns non-zero and releases the skb. | ||
322 | */ | ||
323 | static int phonet_rcv(struct sk_buff *skb, struct net_device *dev, | ||
324 | struct packet_type *pkttype, | ||
325 | struct net_device *orig_dev) | ||
326 | { | ||
327 | struct phonethdr *ph; | ||
328 | struct sock *sk; | ||
329 | struct sockaddr_pn sa; | ||
330 | u16 len; | ||
331 | |||
332 | if (dev_net(dev) != &init_net) | ||
333 | goto out; | ||
334 | |||
335 | /* check we have at least a full Phonet header */ | ||
336 | if (!pskb_pull(skb, sizeof(struct phonethdr))) | ||
337 | goto out; | ||
338 | |||
339 | /* check that the advertised length is correct */ | ||
340 | ph = pn_hdr(skb); | ||
341 | len = get_unaligned_be16(&ph->pn_length); | ||
342 | if (len < 2) | ||
343 | goto out; | ||
344 | len -= 2; | ||
345 | if ((len > skb->len) || pskb_trim(skb, len)) | ||
346 | goto out; | ||
347 | skb_reset_transport_header(skb); | ||
348 | |||
349 | pn_skb_get_dst_sockaddr(skb, &sa); | ||
350 | if (pn_sockaddr_get_addr(&sa) == 0) | ||
351 | goto out; /* currently, we cannot be device 0 */ | ||
352 | |||
353 | sk = pn_find_sock_by_sa(&sa); | ||
354 | if (sk == NULL) { | ||
355 | if (can_respond(skb)) { | ||
356 | send_obj_unreachable(skb); | ||
357 | send_reset_indications(skb); | ||
358 | } | ||
359 | goto out; | ||
360 | } | ||
361 | |||
362 | /* Push data to the socket (or other sockets connected to it). */ | ||
363 | return sk_receive_skb(sk, skb, 0); | ||
364 | |||
365 | out: | ||
366 | kfree_skb(skb); | ||
367 | return NET_RX_DROP; | ||
368 | } | ||
369 | |||
370 | static struct packet_type phonet_packet_type = { | ||
371 | .type = __constant_htons(ETH_P_PHONET), | ||
372 | .dev = NULL, | ||
373 | .func = phonet_rcv, | ||
374 | }; | ||
375 | |||
376 | /* Transport protocol registration */ | ||
377 | static struct phonet_protocol *proto_tab[PHONET_NPROTO] __read_mostly; | ||
378 | static DEFINE_SPINLOCK(proto_tab_lock); | ||
379 | |||
380 | int __init_or_module phonet_proto_register(int protocol, | ||
381 | struct phonet_protocol *pp) | ||
382 | { | ||
383 | int err = 0; | ||
384 | |||
385 | if (protocol >= PHONET_NPROTO) | ||
386 | return -EINVAL; | ||
387 | |||
388 | err = proto_register(pp->prot, 1); | ||
389 | if (err) | ||
390 | return err; | ||
391 | |||
392 | spin_lock(&proto_tab_lock); | ||
393 | if (proto_tab[protocol]) | ||
394 | err = -EBUSY; | ||
395 | else | ||
396 | proto_tab[protocol] = pp; | ||
397 | spin_unlock(&proto_tab_lock); | ||
398 | |||
399 | return err; | ||
400 | } | ||
401 | EXPORT_SYMBOL(phonet_proto_register); | ||
402 | |||
403 | void phonet_proto_unregister(int protocol, struct phonet_protocol *pp) | ||
404 | { | ||
405 | spin_lock(&proto_tab_lock); | ||
406 | BUG_ON(proto_tab[protocol] != pp); | ||
407 | proto_tab[protocol] = NULL; | ||
408 | spin_unlock(&proto_tab_lock); | ||
409 | proto_unregister(pp->prot); | ||
410 | } | ||
411 | EXPORT_SYMBOL(phonet_proto_unregister); | ||
412 | |||
413 | static struct phonet_protocol *phonet_proto_get(int protocol) | ||
414 | { | ||
415 | struct phonet_protocol *pp; | ||
416 | |||
417 | if (protocol >= PHONET_NPROTO) | ||
418 | return NULL; | ||
419 | |||
420 | spin_lock(&proto_tab_lock); | ||
421 | pp = proto_tab[protocol]; | ||
422 | if (pp && !try_module_get(pp->prot->owner)) | ||
423 | pp = NULL; | ||
424 | spin_unlock(&proto_tab_lock); | ||
425 | |||
426 | return pp; | ||
427 | } | ||
428 | |||
429 | static inline void phonet_proto_put(struct phonet_protocol *pp) | ||
430 | { | ||
431 | module_put(pp->prot->owner); | ||
432 | } | ||
433 | |||
434 | /* Module registration */ | ||
435 | static int __init phonet_init(void) | ||
436 | { | ||
437 | int err; | ||
438 | |||
439 | err = sock_register(&phonet_proto_family); | ||
440 | if (err) { | ||
441 | printk(KERN_ALERT | ||
442 | "phonet protocol family initialization failed\n"); | ||
443 | return err; | ||
444 | } | ||
445 | |||
446 | phonet_device_init(); | ||
447 | dev_add_pack(&phonet_packet_type); | ||
448 | phonet_netlink_register(); | ||
449 | phonet_sysctl_init(); | ||
450 | |||
451 | err = isi_register(); | ||
452 | if (err) | ||
453 | goto err; | ||
454 | return 0; | ||
455 | |||
456 | err: | ||
457 | phonet_sysctl_exit(); | ||
458 | sock_unregister(PF_PHONET); | ||
459 | dev_remove_pack(&phonet_packet_type); | ||
460 | phonet_device_exit(); | ||
461 | return err; | ||
462 | } | ||
463 | |||
464 | static void __exit phonet_exit(void) | ||
465 | { | ||
466 | isi_unregister(); | ||
467 | phonet_sysctl_exit(); | ||
468 | sock_unregister(PF_PHONET); | ||
469 | dev_remove_pack(&phonet_packet_type); | ||
470 | phonet_device_exit(); | ||
471 | } | ||
472 | |||
473 | module_init(phonet_init); | ||
474 | module_exit(phonet_exit); | ||
475 | MODULE_DESCRIPTION("Phonet protocol stack for Linux"); | ||
476 | MODULE_LICENSE("GPL"); | ||
477 | MODULE_ALIAS_NETPROTO(PF_PHONET); | ||
diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c new file mode 100644 index 000000000000..e087862ed7e4 --- /dev/null +++ b/net/phonet/datagram.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * File: datagram.c | ||
3 | * | ||
4 | * Datagram (ISI) Phonet sockets | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * Original author: Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/socket.h> | ||
28 | #include <asm/ioctls.h> | ||
29 | #include <net/sock.h> | ||
30 | |||
31 | #include <linux/phonet.h> | ||
32 | #include <net/phonet/phonet.h> | ||
33 | |||
34 | static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb); | ||
35 | |||
36 | /* associated socket ceases to exist */ | ||
37 | static void pn_sock_close(struct sock *sk, long timeout) | ||
38 | { | ||
39 | sk_common_release(sk); | ||
40 | } | ||
41 | |||
42 | static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg) | ||
43 | { | ||
44 | struct sk_buff *skb; | ||
45 | int answ; | ||
46 | |||
47 | switch (cmd) { | ||
48 | case SIOCINQ: | ||
49 | lock_sock(sk); | ||
50 | skb = skb_peek(&sk->sk_receive_queue); | ||
51 | answ = skb ? skb->len : 0; | ||
52 | release_sock(sk); | ||
53 | return put_user(answ, (int __user *)arg); | ||
54 | } | ||
55 | |||
56 | return -ENOIOCTLCMD; | ||
57 | } | ||
58 | |||
59 | /* Destroy socket. All references are gone. */ | ||
60 | static void pn_destruct(struct sock *sk) | ||
61 | { | ||
62 | skb_queue_purge(&sk->sk_receive_queue); | ||
63 | } | ||
64 | |||
65 | static int pn_init(struct sock *sk) | ||
66 | { | ||
67 | sk->sk_destruct = pn_destruct; | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int pn_sendmsg(struct kiocb *iocb, struct sock *sk, | ||
72 | struct msghdr *msg, size_t len) | ||
73 | { | ||
74 | struct sockaddr_pn *target; | ||
75 | struct sk_buff *skb; | ||
76 | int err; | ||
77 | |||
78 | if (msg->msg_flags & MSG_OOB) | ||
79 | return -EOPNOTSUPP; | ||
80 | |||
81 | if (msg->msg_name == NULL) | ||
82 | return -EDESTADDRREQ; | ||
83 | |||
84 | if (msg->msg_namelen < sizeof(struct sockaddr_pn)) | ||
85 | return -EINVAL; | ||
86 | |||
87 | target = (struct sockaddr_pn *)msg->msg_name; | ||
88 | if (target->spn_family != AF_PHONET) | ||
89 | return -EAFNOSUPPORT; | ||
90 | |||
91 | skb = sock_alloc_send_skb(sk, MAX_PHONET_HEADER + len, | ||
92 | msg->msg_flags & MSG_DONTWAIT, &err); | ||
93 | if (skb == NULL) | ||
94 | return err; | ||
95 | skb_reserve(skb, MAX_PHONET_HEADER); | ||
96 | |||
97 | err = memcpy_fromiovec((void *)skb_put(skb, len), msg->msg_iov, len); | ||
98 | if (err < 0) { | ||
99 | kfree_skb(skb); | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Fill in the Phonet header and | ||
105 | * finally pass the packet forwards. | ||
106 | */ | ||
107 | err = pn_skb_send(sk, skb, target); | ||
108 | |||
109 | /* If ok, return len. */ | ||
110 | return (err >= 0) ? len : err; | ||
111 | } | ||
112 | |||
113 | static int pn_recvmsg(struct kiocb *iocb, struct sock *sk, | ||
114 | struct msghdr *msg, size_t len, int noblock, | ||
115 | int flags, int *addr_len) | ||
116 | { | ||
117 | struct sk_buff *skb = NULL; | ||
118 | struct sockaddr_pn sa; | ||
119 | int rval = -EOPNOTSUPP; | ||
120 | int copylen; | ||
121 | |||
122 | if (flags & MSG_OOB) | ||
123 | goto out_nofree; | ||
124 | |||
125 | if (addr_len) | ||
126 | *addr_len = sizeof(sa); | ||
127 | |||
128 | skb = skb_recv_datagram(sk, flags, noblock, &rval); | ||
129 | if (skb == NULL) | ||
130 | goto out_nofree; | ||
131 | |||
132 | pn_skb_get_src_sockaddr(skb, &sa); | ||
133 | |||
134 | copylen = skb->len; | ||
135 | if (len < copylen) { | ||
136 | msg->msg_flags |= MSG_TRUNC; | ||
137 | copylen = len; | ||
138 | } | ||
139 | |||
140 | rval = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copylen); | ||
141 | if (rval) { | ||
142 | rval = -EFAULT; | ||
143 | goto out; | ||
144 | } | ||
145 | |||
146 | rval = (flags & MSG_TRUNC) ? skb->len : copylen; | ||
147 | |||
148 | if (msg->msg_name != NULL) | ||
149 | memcpy(msg->msg_name, &sa, sizeof(struct sockaddr_pn)); | ||
150 | |||
151 | out: | ||
152 | skb_free_datagram(sk, skb); | ||
153 | |||
154 | out_nofree: | ||
155 | return rval; | ||
156 | } | ||
157 | |||
158 | /* Queue an skb for a sock. */ | ||
159 | static int pn_backlog_rcv(struct sock *sk, struct sk_buff *skb) | ||
160 | { | ||
161 | int err = sock_queue_rcv_skb(sk, skb); | ||
162 | if (err < 0) | ||
163 | kfree_skb(skb); | ||
164 | return err ? NET_RX_DROP : NET_RX_SUCCESS; | ||
165 | } | ||
166 | |||
167 | /* Module registration */ | ||
168 | static struct proto pn_proto = { | ||
169 | .close = pn_sock_close, | ||
170 | .ioctl = pn_ioctl, | ||
171 | .init = pn_init, | ||
172 | .sendmsg = pn_sendmsg, | ||
173 | .recvmsg = pn_recvmsg, | ||
174 | .backlog_rcv = pn_backlog_rcv, | ||
175 | .hash = pn_sock_hash, | ||
176 | .unhash = pn_sock_unhash, | ||
177 | .get_port = pn_sock_get_port, | ||
178 | .obj_size = sizeof(struct pn_sock), | ||
179 | .owner = THIS_MODULE, | ||
180 | .name = "PHONET", | ||
181 | }; | ||
182 | |||
183 | static struct phonet_protocol pn_dgram_proto = { | ||
184 | .ops = &phonet_dgram_ops, | ||
185 | .prot = &pn_proto, | ||
186 | .sock_type = SOCK_DGRAM, | ||
187 | }; | ||
188 | |||
189 | int __init isi_register(void) | ||
190 | { | ||
191 | return phonet_proto_register(PN_PROTO_PHONET, &pn_dgram_proto); | ||
192 | } | ||
193 | |||
194 | void __exit isi_unregister(void) | ||
195 | { | ||
196 | phonet_proto_unregister(PN_PROTO_PHONET, &pn_dgram_proto); | ||
197 | } | ||
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c new file mode 100644 index 000000000000..9978afbd9f2a --- /dev/null +++ b/net/phonet/pep-gprs.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * File: pep-gprs.c | ||
3 | * | ||
4 | * GPRS over Phonet pipe end point socket | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
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 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/netdevice.h> | ||
27 | #include <linux/if_ether.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <net/sock.h> | ||
30 | |||
31 | #include <linux/if_phonet.h> | ||
32 | #include <net/tcp_states.h> | ||
33 | #include <net/phonet/gprs.h> | ||
34 | |||
35 | #define GPRS_DEFAULT_MTU 1400 | ||
36 | |||
37 | struct gprs_dev { | ||
38 | struct sock *sk; | ||
39 | void (*old_state_change)(struct sock *); | ||
40 | void (*old_data_ready)(struct sock *, int); | ||
41 | void (*old_write_space)(struct sock *); | ||
42 | |||
43 | struct net_device *net; | ||
44 | struct net_device_stats stats; | ||
45 | |||
46 | struct sk_buff_head tx_queue; | ||
47 | struct work_struct tx_work; | ||
48 | spinlock_t tx_lock; | ||
49 | unsigned tx_max; | ||
50 | }; | ||
51 | |||
52 | static int gprs_type_trans(struct sk_buff *skb) | ||
53 | { | ||
54 | const u8 *pvfc; | ||
55 | u8 buf; | ||
56 | |||
57 | pvfc = skb_header_pointer(skb, 0, 1, &buf); | ||
58 | if (!pvfc) | ||
59 | return 0; | ||
60 | /* Look at IP version field */ | ||
61 | switch (*pvfc >> 4) { | ||
62 | case 4: | ||
63 | return htons(ETH_P_IP); | ||
64 | case 6: | ||
65 | return htons(ETH_P_IPV6); | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Socket callbacks | ||
72 | */ | ||
73 | |||
74 | static void gprs_state_change(struct sock *sk) | ||
75 | { | ||
76 | struct gprs_dev *dev = sk->sk_user_data; | ||
77 | |||
78 | if (sk->sk_state == TCP_CLOSE_WAIT) { | ||
79 | netif_stop_queue(dev->net); | ||
80 | netif_carrier_off(dev->net); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static int gprs_recv(struct gprs_dev *dev, struct sk_buff *skb) | ||
85 | { | ||
86 | int err = 0; | ||
87 | u16 protocol = gprs_type_trans(skb); | ||
88 | |||
89 | if (!protocol) { | ||
90 | err = -EINVAL; | ||
91 | goto drop; | ||
92 | } | ||
93 | |||
94 | if (likely(skb_headroom(skb) & 3)) { | ||
95 | struct sk_buff *rskb, *fs; | ||
96 | int flen = 0; | ||
97 | |||
98 | /* Phonet Pipe data header is misaligned (3 bytes), | ||
99 | * so wrap the IP packet as a single fragment of an head-less | ||
100 | * socket buffer. The network stack will pull what it needs, | ||
101 | * but at least, the whole IP payload is not memcpy'd. */ | ||
102 | rskb = netdev_alloc_skb(dev->net, 0); | ||
103 | if (!rskb) { | ||
104 | err = -ENOBUFS; | ||
105 | goto drop; | ||
106 | } | ||
107 | skb_shinfo(rskb)->frag_list = skb; | ||
108 | rskb->len += skb->len; | ||
109 | rskb->data_len += rskb->len; | ||
110 | rskb->truesize += rskb->len; | ||
111 | |||
112 | /* Avoid nested fragments */ | ||
113 | for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) | ||
114 | flen += fs->len; | ||
115 | skb->next = skb_shinfo(skb)->frag_list; | ||
116 | skb_shinfo(skb)->frag_list = NULL; | ||
117 | skb->len -= flen; | ||
118 | skb->data_len -= flen; | ||
119 | skb->truesize -= flen; | ||
120 | |||
121 | skb = rskb; | ||
122 | } | ||
123 | |||
124 | skb->protocol = protocol; | ||
125 | skb_reset_mac_header(skb); | ||
126 | skb->dev = dev->net; | ||
127 | |||
128 | if (likely(dev->net->flags & IFF_UP)) { | ||
129 | dev->stats.rx_packets++; | ||
130 | dev->stats.rx_bytes += skb->len; | ||
131 | netif_rx(skb); | ||
132 | skb = NULL; | ||
133 | } else | ||
134 | err = -ENODEV; | ||
135 | |||
136 | drop: | ||
137 | if (skb) { | ||
138 | dev_kfree_skb(skb); | ||
139 | dev->stats.rx_dropped++; | ||
140 | } | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | static void gprs_data_ready(struct sock *sk, int len) | ||
145 | { | ||
146 | struct gprs_dev *dev = sk->sk_user_data; | ||
147 | struct sk_buff *skb; | ||
148 | |||
149 | while ((skb = pep_read(sk)) != NULL) { | ||
150 | skb_orphan(skb); | ||
151 | gprs_recv(dev, skb); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static void gprs_write_space(struct sock *sk) | ||
156 | { | ||
157 | struct gprs_dev *dev = sk->sk_user_data; | ||
158 | unsigned credits = pep_writeable(sk); | ||
159 | |||
160 | spin_lock_bh(&dev->tx_lock); | ||
161 | dev->tx_max = credits; | ||
162 | if (credits > skb_queue_len(&dev->tx_queue)) | ||
163 | netif_wake_queue(dev->net); | ||
164 | spin_unlock_bh(&dev->tx_lock); | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Network device callbacks | ||
169 | */ | ||
170 | |||
171 | static int gprs_xmit(struct sk_buff *skb, struct net_device *net) | ||
172 | { | ||
173 | struct gprs_dev *dev = netdev_priv(net); | ||
174 | |||
175 | switch (skb->protocol) { | ||
176 | case htons(ETH_P_IP): | ||
177 | case htons(ETH_P_IPV6): | ||
178 | break; | ||
179 | default: | ||
180 | dev_kfree_skb(skb); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | spin_lock(&dev->tx_lock); | ||
185 | if (likely(skb_queue_len(&dev->tx_queue) < dev->tx_max)) { | ||
186 | skb_queue_tail(&dev->tx_queue, skb); | ||
187 | skb = NULL; | ||
188 | } | ||
189 | if (skb_queue_len(&dev->tx_queue) >= dev->tx_max) | ||
190 | netif_stop_queue(net); | ||
191 | spin_unlock(&dev->tx_lock); | ||
192 | |||
193 | schedule_work(&dev->tx_work); | ||
194 | if (unlikely(skb)) | ||
195 | dev_kfree_skb(skb); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static void gprs_tx(struct work_struct *work) | ||
200 | { | ||
201 | struct gprs_dev *dev = container_of(work, struct gprs_dev, tx_work); | ||
202 | struct sock *sk = dev->sk; | ||
203 | struct sk_buff *skb; | ||
204 | |||
205 | while ((skb = skb_dequeue(&dev->tx_queue)) != NULL) { | ||
206 | int err; | ||
207 | |||
208 | dev->stats.tx_bytes += skb->len; | ||
209 | dev->stats.tx_packets++; | ||
210 | |||
211 | skb_orphan(skb); | ||
212 | skb_set_owner_w(skb, sk); | ||
213 | |||
214 | lock_sock(sk); | ||
215 | err = pep_write(sk, skb); | ||
216 | if (err) { | ||
217 | LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n", | ||
218 | dev->net->name, err); | ||
219 | dev->stats.tx_aborted_errors++; | ||
220 | dev->stats.tx_errors++; | ||
221 | } | ||
222 | release_sock(sk); | ||
223 | } | ||
224 | |||
225 | lock_sock(sk); | ||
226 | gprs_write_space(sk); | ||
227 | release_sock(sk); | ||
228 | } | ||
229 | |||
230 | static int gprs_set_mtu(struct net_device *net, int new_mtu) | ||
231 | { | ||
232 | if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11))) | ||
233 | return -EINVAL; | ||
234 | |||
235 | net->mtu = new_mtu; | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static struct net_device_stats *gprs_get_stats(struct net_device *net) | ||
240 | { | ||
241 | struct gprs_dev *dev = netdev_priv(net); | ||
242 | |||
243 | return &dev->stats; | ||
244 | } | ||
245 | |||
246 | static void gprs_setup(struct net_device *net) | ||
247 | { | ||
248 | net->features = NETIF_F_FRAGLIST; | ||
249 | net->type = ARPHRD_NONE; | ||
250 | net->flags = IFF_POINTOPOINT | IFF_NOARP; | ||
251 | net->mtu = GPRS_DEFAULT_MTU; | ||
252 | net->hard_header_len = 0; | ||
253 | net->addr_len = 0; | ||
254 | net->tx_queue_len = 10; | ||
255 | |||
256 | net->destructor = free_netdev; | ||
257 | net->hard_start_xmit = gprs_xmit; /* mandatory */ | ||
258 | net->change_mtu = gprs_set_mtu; | ||
259 | net->get_stats = gprs_get_stats; | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * External interface | ||
264 | */ | ||
265 | |||
266 | /* | ||
267 | * Attach a GPRS interface to a datagram socket. | ||
268 | * Returns the interface index on success, negative error code on error. | ||
269 | */ | ||
270 | int gprs_attach(struct sock *sk) | ||
271 | { | ||
272 | static const char ifname[] = "gprs%d"; | ||
273 | struct gprs_dev *dev; | ||
274 | struct net_device *net; | ||
275 | int err; | ||
276 | |||
277 | if (unlikely(sk->sk_type == SOCK_STREAM)) | ||
278 | return -EINVAL; /* need packet boundaries */ | ||
279 | |||
280 | /* Create net device */ | ||
281 | net = alloc_netdev(sizeof(*dev), ifname, gprs_setup); | ||
282 | if (!net) | ||
283 | return -ENOMEM; | ||
284 | dev = netdev_priv(net); | ||
285 | dev->net = net; | ||
286 | dev->tx_max = 0; | ||
287 | spin_lock_init(&dev->tx_lock); | ||
288 | skb_queue_head_init(&dev->tx_queue); | ||
289 | INIT_WORK(&dev->tx_work, gprs_tx); | ||
290 | |||
291 | netif_stop_queue(net); | ||
292 | err = register_netdev(net); | ||
293 | if (err) { | ||
294 | free_netdev(net); | ||
295 | return err; | ||
296 | } | ||
297 | |||
298 | lock_sock(sk); | ||
299 | if (unlikely(sk->sk_user_data)) { | ||
300 | err = -EBUSY; | ||
301 | goto out_rel; | ||
302 | } | ||
303 | if (unlikely((1 << sk->sk_state & (TCPF_CLOSE|TCPF_LISTEN)) || | ||
304 | sock_flag(sk, SOCK_DEAD))) { | ||
305 | err = -EINVAL; | ||
306 | goto out_rel; | ||
307 | } | ||
308 | sk->sk_user_data = dev; | ||
309 | dev->old_state_change = sk->sk_state_change; | ||
310 | dev->old_data_ready = sk->sk_data_ready; | ||
311 | dev->old_write_space = sk->sk_write_space; | ||
312 | sk->sk_state_change = gprs_state_change; | ||
313 | sk->sk_data_ready = gprs_data_ready; | ||
314 | sk->sk_write_space = gprs_write_space; | ||
315 | release_sock(sk); | ||
316 | |||
317 | sock_hold(sk); | ||
318 | dev->sk = sk; | ||
319 | |||
320 | printk(KERN_DEBUG"%s: attached\n", net->name); | ||
321 | gprs_write_space(sk); /* kick off TX */ | ||
322 | return net->ifindex; | ||
323 | |||
324 | out_rel: | ||
325 | release_sock(sk); | ||
326 | unregister_netdev(net); | ||
327 | return err; | ||
328 | } | ||
329 | |||
330 | void gprs_detach(struct sock *sk) | ||
331 | { | ||
332 | struct gprs_dev *dev = sk->sk_user_data; | ||
333 | struct net_device *net = dev->net; | ||
334 | |||
335 | lock_sock(sk); | ||
336 | sk->sk_user_data = NULL; | ||
337 | sk->sk_state_change = dev->old_state_change; | ||
338 | sk->sk_data_ready = dev->old_data_ready; | ||
339 | sk->sk_write_space = dev->old_write_space; | ||
340 | release_sock(sk); | ||
341 | |||
342 | printk(KERN_DEBUG"%s: detached\n", net->name); | ||
343 | unregister_netdev(net); | ||
344 | flush_scheduled_work(); | ||
345 | sock_put(sk); | ||
346 | skb_queue_purge(&dev->tx_queue); | ||
347 | } | ||
diff --git a/net/phonet/pep.c b/net/phonet/pep.c new file mode 100644 index 000000000000..bc6d50f83249 --- /dev/null +++ b/net/phonet/pep.c | |||
@@ -0,0 +1,1076 @@ | |||
1 | /* | ||
2 | * File: pep.c | ||
3 | * | ||
4 | * Phonet pipe protocol end point socket | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
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 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/socket.h> | ||
27 | #include <net/sock.h> | ||
28 | #include <net/tcp_states.h> | ||
29 | #include <asm/ioctls.h> | ||
30 | |||
31 | #include <linux/phonet.h> | ||
32 | #include <net/phonet/phonet.h> | ||
33 | #include <net/phonet/pep.h> | ||
34 | #include <net/phonet/gprs.h> | ||
35 | |||
36 | /* sk_state values: | ||
37 | * TCP_CLOSE sock not in use yet | ||
38 | * TCP_CLOSE_WAIT disconnected pipe | ||
39 | * TCP_LISTEN listening pipe endpoint | ||
40 | * TCP_SYN_RECV connected pipe in disabled state | ||
41 | * TCP_ESTABLISHED connected pipe in enabled state | ||
42 | * | ||
43 | * pep_sock locking: | ||
44 | * - sk_state, ackq, hlist: sock lock needed | ||
45 | * - listener: read only | ||
46 | * - pipe_handle: read only | ||
47 | */ | ||
48 | |||
49 | #define CREDITS_MAX 10 | ||
50 | #define CREDITS_THR 7 | ||
51 | |||
52 | static const struct sockaddr_pn pipe_srv = { | ||
53 | .spn_family = AF_PHONET, | ||
54 | .spn_resource = 0xD9, /* pipe service */ | ||
55 | }; | ||
56 | |||
57 | #define pep_sb_size(s) (((s) + 5) & ~3) /* 2-bytes head, 32-bits aligned */ | ||
58 | |||
59 | /* Get the next TLV sub-block. */ | ||
60 | static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen, | ||
61 | void *buf) | ||
62 | { | ||
63 | void *data = NULL; | ||
64 | struct { | ||
65 | u8 sb_type; | ||
66 | u8 sb_len; | ||
67 | } *ph, h; | ||
68 | int buflen = *plen; | ||
69 | |||
70 | ph = skb_header_pointer(skb, 0, 2, &h); | ||
71 | if (ph == NULL || ph->sb_len < 2 || !pskb_may_pull(skb, ph->sb_len)) | ||
72 | return NULL; | ||
73 | ph->sb_len -= 2; | ||
74 | *ptype = ph->sb_type; | ||
75 | *plen = ph->sb_len; | ||
76 | |||
77 | if (buflen > ph->sb_len) | ||
78 | buflen = ph->sb_len; | ||
79 | data = skb_header_pointer(skb, 2, buflen, buf); | ||
80 | __skb_pull(skb, 2 + ph->sb_len); | ||
81 | return data; | ||
82 | } | ||
83 | |||
84 | static int pep_reply(struct sock *sk, struct sk_buff *oskb, | ||
85 | u8 code, const void *data, int len, gfp_t priority) | ||
86 | { | ||
87 | const struct pnpipehdr *oph = pnp_hdr(oskb); | ||
88 | struct pnpipehdr *ph; | ||
89 | struct sk_buff *skb; | ||
90 | |||
91 | skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority); | ||
92 | if (!skb) | ||
93 | return -ENOMEM; | ||
94 | skb_set_owner_w(skb, sk); | ||
95 | |||
96 | skb_reserve(skb, MAX_PNPIPE_HEADER); | ||
97 | __skb_put(skb, len); | ||
98 | skb_copy_to_linear_data(skb, data, len); | ||
99 | __skb_push(skb, sizeof(*ph)); | ||
100 | skb_reset_transport_header(skb); | ||
101 | ph = pnp_hdr(skb); | ||
102 | ph->utid = oph->utid; | ||
103 | ph->message_id = oph->message_id + 1; /* REQ -> RESP */ | ||
104 | ph->pipe_handle = oph->pipe_handle; | ||
105 | ph->error_code = code; | ||
106 | |||
107 | return pn_skb_send(sk, skb, &pipe_srv); | ||
108 | } | ||
109 | |||
110 | #define PAD 0x00 | ||
111 | static int pep_accept_conn(struct sock *sk, struct sk_buff *skb) | ||
112 | { | ||
113 | static const u8 data[20] = { | ||
114 | PAD, PAD, PAD, 2 /* sub-blocks */, | ||
115 | PN_PIPE_SB_REQUIRED_FC_TX, pep_sb_size(5), 3, PAD, | ||
116 | PN_MULTI_CREDIT_FLOW_CONTROL, | ||
117 | PN_ONE_CREDIT_FLOW_CONTROL, | ||
118 | PN_LEGACY_FLOW_CONTROL, | ||
119 | PAD, | ||
120 | PN_PIPE_SB_PREFERRED_FC_RX, pep_sb_size(5), 3, PAD, | ||
121 | PN_MULTI_CREDIT_FLOW_CONTROL, | ||
122 | PN_ONE_CREDIT_FLOW_CONTROL, | ||
123 | PN_LEGACY_FLOW_CONTROL, | ||
124 | PAD, | ||
125 | }; | ||
126 | |||
127 | might_sleep(); | ||
128 | return pep_reply(sk, skb, PN_PIPE_NO_ERROR, data, sizeof(data), | ||
129 | GFP_KERNEL); | ||
130 | } | ||
131 | |||
132 | static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code) | ||
133 | { | ||
134 | static const u8 data[4] = { PAD, PAD, PAD, 0 /* sub-blocks */ }; | ||
135 | WARN_ON(code == PN_PIPE_NO_ERROR); | ||
136 | return pep_reply(sk, skb, code, data, sizeof(data), GFP_ATOMIC); | ||
137 | } | ||
138 | |||
139 | /* Control requests are not sent by the pipe service and have a specific | ||
140 | * message format. */ | ||
141 | static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code, | ||
142 | gfp_t priority) | ||
143 | { | ||
144 | const struct pnpipehdr *oph = pnp_hdr(oskb); | ||
145 | struct sk_buff *skb; | ||
146 | struct pnpipehdr *ph; | ||
147 | struct sockaddr_pn dst; | ||
148 | |||
149 | skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); | ||
150 | if (!skb) | ||
151 | return -ENOMEM; | ||
152 | skb_set_owner_w(skb, sk); | ||
153 | |||
154 | skb_reserve(skb, MAX_PHONET_HEADER); | ||
155 | ph = (struct pnpipehdr *)skb_put(skb, sizeof(*ph) + 4); | ||
156 | |||
157 | ph->utid = oph->utid; | ||
158 | ph->message_id = PNS_PEP_CTRL_RESP; | ||
159 | ph->pipe_handle = oph->pipe_handle; | ||
160 | ph->data[0] = oph->data[1]; /* CTRL id */ | ||
161 | ph->data[1] = oph->data[0]; /* PEP type */ | ||
162 | ph->data[2] = code; /* error code, at an usual offset */ | ||
163 | ph->data[3] = PAD; | ||
164 | ph->data[4] = PAD; | ||
165 | |||
166 | pn_skb_get_src_sockaddr(oskb, &dst); | ||
167 | return pn_skb_send(sk, skb, &dst); | ||
168 | } | ||
169 | |||
170 | static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority) | ||
171 | { | ||
172 | struct pep_sock *pn = pep_sk(sk); | ||
173 | struct pnpipehdr *ph; | ||
174 | struct sk_buff *skb; | ||
175 | |||
176 | skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); | ||
177 | if (!skb) | ||
178 | return -ENOMEM; | ||
179 | skb_set_owner_w(skb, sk); | ||
180 | |||
181 | skb_reserve(skb, MAX_PNPIPE_HEADER + 4); | ||
182 | __skb_push(skb, sizeof(*ph) + 4); | ||
183 | skb_reset_transport_header(skb); | ||
184 | ph = pnp_hdr(skb); | ||
185 | ph->utid = 0; | ||
186 | ph->message_id = PNS_PEP_STATUS_IND; | ||
187 | ph->pipe_handle = pn->pipe_handle; | ||
188 | ph->pep_type = PN_PEP_TYPE_COMMON; | ||
189 | ph->data[1] = type; | ||
190 | ph->data[2] = PAD; | ||
191 | ph->data[3] = PAD; | ||
192 | ph->data[4] = status; | ||
193 | |||
194 | return pn_skb_send(sk, skb, &pipe_srv); | ||
195 | } | ||
196 | |||
197 | /* Send our RX flow control information to the sender. | ||
198 | * Socket must be locked. */ | ||
199 | static void pipe_grant_credits(struct sock *sk) | ||
200 | { | ||
201 | struct pep_sock *pn = pep_sk(sk); | ||
202 | |||
203 | BUG_ON(sk->sk_state != TCP_ESTABLISHED); | ||
204 | |||
205 | switch (pn->rx_fc) { | ||
206 | case PN_LEGACY_FLOW_CONTROL: /* TODO */ | ||
207 | break; | ||
208 | case PN_ONE_CREDIT_FLOW_CONTROL: | ||
209 | pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL, | ||
210 | PEP_IND_READY, GFP_ATOMIC); | ||
211 | pn->rx_credits = 1; | ||
212 | break; | ||
213 | case PN_MULTI_CREDIT_FLOW_CONTROL: | ||
214 | if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX) | ||
215 | break; | ||
216 | if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS, | ||
217 | CREDITS_MAX - pn->rx_credits, | ||
218 | GFP_ATOMIC) == 0) | ||
219 | pn->rx_credits = CREDITS_MAX; | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb) | ||
225 | { | ||
226 | struct pep_sock *pn = pep_sk(sk); | ||
227 | struct pnpipehdr *hdr = pnp_hdr(skb); | ||
228 | |||
229 | if (!pskb_may_pull(skb, sizeof(*hdr) + 4)) | ||
230 | return -EINVAL; | ||
231 | |||
232 | if (hdr->data[0] != PN_PEP_TYPE_COMMON) { | ||
233 | LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP type: %u\n", | ||
234 | (unsigned)hdr->data[0]); | ||
235 | return -EOPNOTSUPP; | ||
236 | } | ||
237 | |||
238 | switch (hdr->data[1]) { | ||
239 | case PN_PEP_IND_FLOW_CONTROL: | ||
240 | switch (pn->tx_fc) { | ||
241 | case PN_LEGACY_FLOW_CONTROL: | ||
242 | switch (hdr->data[4]) { | ||
243 | case PEP_IND_BUSY: | ||
244 | pn->tx_credits = 0; | ||
245 | break; | ||
246 | case PEP_IND_READY: | ||
247 | pn->tx_credits = 1; | ||
248 | break; | ||
249 | } | ||
250 | break; | ||
251 | case PN_ONE_CREDIT_FLOW_CONTROL: | ||
252 | if (hdr->data[4] == PEP_IND_READY) | ||
253 | pn->tx_credits = 1; | ||
254 | break; | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | case PN_PEP_IND_ID_MCFC_GRANT_CREDITS: | ||
259 | if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL) | ||
260 | break; | ||
261 | if (pn->tx_credits + hdr->data[4] > 0xff) | ||
262 | pn->tx_credits = 0xff; | ||
263 | else | ||
264 | pn->tx_credits += hdr->data[4]; | ||
265 | break; | ||
266 | |||
267 | default: | ||
268 | LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP indication: %u\n", | ||
269 | (unsigned)hdr->data[1]); | ||
270 | return -EOPNOTSUPP; | ||
271 | } | ||
272 | if (pn->tx_credits) | ||
273 | sk->sk_write_space(sk); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static int pipe_rcv_created(struct sock *sk, struct sk_buff *skb) | ||
278 | { | ||
279 | struct pep_sock *pn = pep_sk(sk); | ||
280 | struct pnpipehdr *hdr = pnp_hdr(skb); | ||
281 | u8 n_sb = hdr->data[0]; | ||
282 | |||
283 | pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL; | ||
284 | __skb_pull(skb, sizeof(*hdr)); | ||
285 | while (n_sb > 0) { | ||
286 | u8 type, buf[2], len = sizeof(buf); | ||
287 | u8 *data = pep_get_sb(skb, &type, &len, buf); | ||
288 | |||
289 | if (data == NULL) | ||
290 | return -EINVAL; | ||
291 | switch (type) { | ||
292 | case PN_PIPE_SB_NEGOTIATED_FC: | ||
293 | if (len < 2 || (data[0] | data[1]) > 3) | ||
294 | break; | ||
295 | pn->tx_fc = data[0] & 3; | ||
296 | pn->rx_fc = data[1] & 3; | ||
297 | break; | ||
298 | } | ||
299 | n_sb--; | ||
300 | } | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | /* Queue an skb to a connected sock. | ||
305 | * Socket lock must be held. */ | ||
306 | static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) | ||
307 | { | ||
308 | struct pep_sock *pn = pep_sk(sk); | ||
309 | struct pnpipehdr *hdr = pnp_hdr(skb); | ||
310 | struct sk_buff_head *queue; | ||
311 | int err = 0; | ||
312 | |||
313 | BUG_ON(sk->sk_state == TCP_CLOSE_WAIT); | ||
314 | |||
315 | switch (hdr->message_id) { | ||
316 | case PNS_PEP_CONNECT_REQ: | ||
317 | pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); | ||
318 | break; | ||
319 | |||
320 | case PNS_PEP_DISCONNECT_REQ: | ||
321 | pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); | ||
322 | sk->sk_state = TCP_CLOSE_WAIT; | ||
323 | if (!sock_flag(sk, SOCK_DEAD)) | ||
324 | sk->sk_state_change(sk); | ||
325 | break; | ||
326 | |||
327 | case PNS_PEP_ENABLE_REQ: | ||
328 | /* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */ | ||
329 | pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); | ||
330 | break; | ||
331 | |||
332 | case PNS_PEP_RESET_REQ: | ||
333 | switch (hdr->state_after_reset) { | ||
334 | case PN_PIPE_DISABLE: | ||
335 | pn->init_enable = 0; | ||
336 | break; | ||
337 | case PN_PIPE_ENABLE: | ||
338 | pn->init_enable = 1; | ||
339 | break; | ||
340 | default: /* not allowed to send an error here!? */ | ||
341 | err = -EINVAL; | ||
342 | goto out; | ||
343 | } | ||
344 | /* fall through */ | ||
345 | case PNS_PEP_DISABLE_REQ: | ||
346 | pn->tx_credits = 0; | ||
347 | pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); | ||
348 | break; | ||
349 | |||
350 | case PNS_PEP_CTRL_REQ: | ||
351 | if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) | ||
352 | break; | ||
353 | __skb_pull(skb, 4); | ||
354 | queue = &pn->ctrlreq_queue; | ||
355 | goto queue; | ||
356 | |||
357 | case PNS_PIPE_DATA: | ||
358 | __skb_pull(skb, 3); /* Pipe data header */ | ||
359 | if (!pn_flow_safe(pn->rx_fc)) { | ||
360 | err = sock_queue_rcv_skb(sk, skb); | ||
361 | if (!err) | ||
362 | return 0; | ||
363 | break; | ||
364 | } | ||
365 | |||
366 | if (pn->rx_credits == 0) { | ||
367 | err = -ENOBUFS; | ||
368 | break; | ||
369 | } | ||
370 | pn->rx_credits--; | ||
371 | queue = &sk->sk_receive_queue; | ||
372 | goto queue; | ||
373 | |||
374 | case PNS_PEP_STATUS_IND: | ||
375 | pipe_rcv_status(sk, skb); | ||
376 | break; | ||
377 | |||
378 | case PNS_PIPE_REDIRECTED_IND: | ||
379 | err = pipe_rcv_created(sk, skb); | ||
380 | break; | ||
381 | |||
382 | case PNS_PIPE_CREATED_IND: | ||
383 | err = pipe_rcv_created(sk, skb); | ||
384 | if (err) | ||
385 | break; | ||
386 | /* fall through */ | ||
387 | case PNS_PIPE_RESET_IND: | ||
388 | if (!pn->init_enable) | ||
389 | break; | ||
390 | /* fall through */ | ||
391 | case PNS_PIPE_ENABLED_IND: | ||
392 | if (!pn_flow_safe(pn->tx_fc)) { | ||
393 | pn->tx_credits = 1; | ||
394 | sk->sk_write_space(sk); | ||
395 | } | ||
396 | if (sk->sk_state == TCP_ESTABLISHED) | ||
397 | break; /* Nothing to do */ | ||
398 | sk->sk_state = TCP_ESTABLISHED; | ||
399 | pipe_grant_credits(sk); | ||
400 | break; | ||
401 | |||
402 | case PNS_PIPE_DISABLED_IND: | ||
403 | sk->sk_state = TCP_SYN_RECV; | ||
404 | pn->rx_credits = 0; | ||
405 | break; | ||
406 | |||
407 | default: | ||
408 | LIMIT_NETDEBUG(KERN_DEBUG"Phonet unknown PEP message: %u\n", | ||
409 | hdr->message_id); | ||
410 | err = -EINVAL; | ||
411 | } | ||
412 | out: | ||
413 | kfree_skb(skb); | ||
414 | return err; | ||
415 | |||
416 | queue: | ||
417 | skb->dev = NULL; | ||
418 | skb_set_owner_r(skb, sk); | ||
419 | err = skb->len; | ||
420 | skb_queue_tail(queue, skb); | ||
421 | if (!sock_flag(sk, SOCK_DEAD)) | ||
422 | sk->sk_data_ready(sk, err); | ||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | /* Destroy connected sock. */ | ||
427 | static void pipe_destruct(struct sock *sk) | ||
428 | { | ||
429 | struct pep_sock *pn = pep_sk(sk); | ||
430 | |||
431 | skb_queue_purge(&sk->sk_receive_queue); | ||
432 | skb_queue_purge(&pn->ctrlreq_queue); | ||
433 | } | ||
434 | |||
435 | static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb) | ||
436 | { | ||
437 | struct sock *newsk; | ||
438 | struct pep_sock *newpn, *pn = pep_sk(sk); | ||
439 | struct pnpipehdr *hdr; | ||
440 | struct sockaddr_pn dst; | ||
441 | u16 peer_type; | ||
442 | u8 pipe_handle, enabled, n_sb; | ||
443 | |||
444 | if (!pskb_pull(skb, sizeof(*hdr) + 4)) | ||
445 | return -EINVAL; | ||
446 | |||
447 | hdr = pnp_hdr(skb); | ||
448 | pipe_handle = hdr->pipe_handle; | ||
449 | switch (hdr->state_after_connect) { | ||
450 | case PN_PIPE_DISABLE: | ||
451 | enabled = 0; | ||
452 | break; | ||
453 | case PN_PIPE_ENABLE: | ||
454 | enabled = 1; | ||
455 | break; | ||
456 | default: | ||
457 | pep_reject_conn(sk, skb, PN_PIPE_ERR_INVALID_PARAM); | ||
458 | return -EINVAL; | ||
459 | } | ||
460 | peer_type = hdr->other_pep_type << 8; | ||
461 | |||
462 | if (unlikely(sk->sk_state != TCP_LISTEN) || sk_acceptq_is_full(sk)) { | ||
463 | pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE); | ||
464 | return -ENOBUFS; | ||
465 | } | ||
466 | |||
467 | /* Parse sub-blocks (options) */ | ||
468 | n_sb = hdr->data[4]; | ||
469 | while (n_sb > 0) { | ||
470 | u8 type, buf[1], len = sizeof(buf); | ||
471 | const u8 *data = pep_get_sb(skb, &type, &len, buf); | ||
472 | |||
473 | if (data == NULL) | ||
474 | return -EINVAL; | ||
475 | switch (type) { | ||
476 | case PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE: | ||
477 | if (len < 1) | ||
478 | return -EINVAL; | ||
479 | peer_type = (peer_type & 0xff00) | data[0]; | ||
480 | break; | ||
481 | } | ||
482 | n_sb--; | ||
483 | } | ||
484 | |||
485 | skb = skb_clone(skb, GFP_ATOMIC); | ||
486 | if (!skb) | ||
487 | return -ENOMEM; | ||
488 | |||
489 | /* Create a new to-be-accepted sock */ | ||
490 | newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_ATOMIC, sk->sk_prot); | ||
491 | if (!newsk) { | ||
492 | kfree_skb(skb); | ||
493 | return -ENOMEM; | ||
494 | } | ||
495 | sock_init_data(NULL, newsk); | ||
496 | newsk->sk_state = TCP_SYN_RECV; | ||
497 | newsk->sk_backlog_rcv = pipe_do_rcv; | ||
498 | newsk->sk_protocol = sk->sk_protocol; | ||
499 | newsk->sk_destruct = pipe_destruct; | ||
500 | |||
501 | newpn = pep_sk(newsk); | ||
502 | pn_skb_get_dst_sockaddr(skb, &dst); | ||
503 | newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst); | ||
504 | newpn->pn_sk.resource = pn->pn_sk.resource; | ||
505 | skb_queue_head_init(&newpn->ctrlreq_queue); | ||
506 | newpn->pipe_handle = pipe_handle; | ||
507 | newpn->peer_type = peer_type; | ||
508 | newpn->rx_credits = newpn->tx_credits = 0; | ||
509 | newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL; | ||
510 | newpn->init_enable = enabled; | ||
511 | |||
512 | BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue)); | ||
513 | skb_queue_head(&newsk->sk_receive_queue, skb); | ||
514 | if (!sock_flag(sk, SOCK_DEAD)) | ||
515 | sk->sk_data_ready(sk, 0); | ||
516 | |||
517 | sk_acceptq_added(sk); | ||
518 | sk_add_node(newsk, &pn->ackq); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | /* Listening sock must be locked */ | ||
523 | static struct sock *pep_find_pipe(const struct hlist_head *hlist, | ||
524 | const struct sockaddr_pn *dst, | ||
525 | u8 pipe_handle) | ||
526 | { | ||
527 | struct hlist_node *node; | ||
528 | struct sock *sknode; | ||
529 | u16 dobj = pn_sockaddr_get_object(dst); | ||
530 | |||
531 | sk_for_each(sknode, node, hlist) { | ||
532 | struct pep_sock *pnnode = pep_sk(sknode); | ||
533 | |||
534 | /* Ports match, but addresses might not: */ | ||
535 | if (pnnode->pn_sk.sobject != dobj) | ||
536 | continue; | ||
537 | if (pnnode->pipe_handle != pipe_handle) | ||
538 | continue; | ||
539 | if (sknode->sk_state == TCP_CLOSE_WAIT) | ||
540 | continue; | ||
541 | |||
542 | sock_hold(sknode); | ||
543 | return sknode; | ||
544 | } | ||
545 | return NULL; | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * Deliver an skb to a listening sock. | ||
550 | * Socket lock must be held. | ||
551 | * We then queue the skb to the right connected sock (if any). | ||
552 | */ | ||
553 | static int pep_do_rcv(struct sock *sk, struct sk_buff *skb) | ||
554 | { | ||
555 | struct pep_sock *pn = pep_sk(sk); | ||
556 | struct sock *sknode; | ||
557 | struct pnpipehdr *hdr = pnp_hdr(skb); | ||
558 | struct sockaddr_pn dst; | ||
559 | int err = NET_RX_SUCCESS; | ||
560 | u8 pipe_handle; | ||
561 | |||
562 | if (!pskb_may_pull(skb, sizeof(*hdr))) | ||
563 | goto drop; | ||
564 | |||
565 | hdr = pnp_hdr(skb); | ||
566 | pipe_handle = hdr->pipe_handle; | ||
567 | if (pipe_handle == PN_PIPE_INVALID_HANDLE) | ||
568 | goto drop; | ||
569 | |||
570 | pn_skb_get_dst_sockaddr(skb, &dst); | ||
571 | |||
572 | /* Look for an existing pipe handle */ | ||
573 | sknode = pep_find_pipe(&pn->hlist, &dst, pipe_handle); | ||
574 | if (sknode) | ||
575 | return sk_receive_skb(sknode, skb, 1); | ||
576 | |||
577 | /* Look for a pipe handle pending accept */ | ||
578 | sknode = pep_find_pipe(&pn->ackq, &dst, pipe_handle); | ||
579 | if (sknode) { | ||
580 | sock_put(sknode); | ||
581 | if (net_ratelimit()) | ||
582 | printk(KERN_WARNING"Phonet unconnected PEP ignored"); | ||
583 | err = NET_RX_DROP; | ||
584 | goto drop; | ||
585 | } | ||
586 | |||
587 | switch (hdr->message_id) { | ||
588 | case PNS_PEP_CONNECT_REQ: | ||
589 | err = pep_connreq_rcv(sk, skb); | ||
590 | break; | ||
591 | |||
592 | case PNS_PEP_DISCONNECT_REQ: | ||
593 | pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); | ||
594 | break; | ||
595 | |||
596 | case PNS_PEP_CTRL_REQ: | ||
597 | pep_ctrlreq_error(sk, skb, PN_PIPE_INVALID_HANDLE, GFP_ATOMIC); | ||
598 | break; | ||
599 | |||
600 | case PNS_PEP_RESET_REQ: | ||
601 | case PNS_PEP_ENABLE_REQ: | ||
602 | case PNS_PEP_DISABLE_REQ: | ||
603 | /* invalid handle is not even allowed here! */ | ||
604 | default: | ||
605 | err = NET_RX_DROP; | ||
606 | } | ||
607 | drop: | ||
608 | kfree_skb(skb); | ||
609 | return err; | ||
610 | } | ||
611 | |||
612 | /* associated socket ceases to exist */ | ||
613 | static void pep_sock_close(struct sock *sk, long timeout) | ||
614 | { | ||
615 | struct pep_sock *pn = pep_sk(sk); | ||
616 | int ifindex = 0; | ||
617 | |||
618 | sk_common_release(sk); | ||
619 | |||
620 | lock_sock(sk); | ||
621 | if (sk->sk_state == TCP_LISTEN) { | ||
622 | /* Destroy the listen queue */ | ||
623 | struct sock *sknode; | ||
624 | struct hlist_node *p, *n; | ||
625 | |||
626 | sk_for_each_safe(sknode, p, n, &pn->ackq) | ||
627 | sk_del_node_init(sknode); | ||
628 | sk->sk_state = TCP_CLOSE; | ||
629 | } | ||
630 | ifindex = pn->ifindex; | ||
631 | pn->ifindex = 0; | ||
632 | release_sock(sk); | ||
633 | |||
634 | if (ifindex) | ||
635 | gprs_detach(sk); | ||
636 | } | ||
637 | |||
638 | static int pep_wait_connreq(struct sock *sk, int noblock) | ||
639 | { | ||
640 | struct task_struct *tsk = current; | ||
641 | struct pep_sock *pn = pep_sk(sk); | ||
642 | long timeo = sock_rcvtimeo(sk, noblock); | ||
643 | |||
644 | for (;;) { | ||
645 | DEFINE_WAIT(wait); | ||
646 | |||
647 | if (sk->sk_state != TCP_LISTEN) | ||
648 | return -EINVAL; | ||
649 | if (!hlist_empty(&pn->ackq)) | ||
650 | break; | ||
651 | if (!timeo) | ||
652 | return -EWOULDBLOCK; | ||
653 | if (signal_pending(tsk)) | ||
654 | return sock_intr_errno(timeo); | ||
655 | |||
656 | prepare_to_wait_exclusive(&sk->sk_socket->wait, &wait, | ||
657 | TASK_INTERRUPTIBLE); | ||
658 | release_sock(sk); | ||
659 | timeo = schedule_timeout(timeo); | ||
660 | lock_sock(sk); | ||
661 | finish_wait(&sk->sk_socket->wait, &wait); | ||
662 | } | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp) | ||
668 | { | ||
669 | struct pep_sock *pn = pep_sk(sk); | ||
670 | struct sock *newsk = NULL; | ||
671 | struct sk_buff *oskb; | ||
672 | int err; | ||
673 | |||
674 | lock_sock(sk); | ||
675 | err = pep_wait_connreq(sk, flags & O_NONBLOCK); | ||
676 | if (err) | ||
677 | goto out; | ||
678 | |||
679 | newsk = __sk_head(&pn->ackq); | ||
680 | |||
681 | oskb = skb_dequeue(&newsk->sk_receive_queue); | ||
682 | err = pep_accept_conn(newsk, oskb); | ||
683 | if (err) { | ||
684 | skb_queue_head(&newsk->sk_receive_queue, oskb); | ||
685 | newsk = NULL; | ||
686 | goto out; | ||
687 | } | ||
688 | |||
689 | sock_hold(sk); | ||
690 | pep_sk(newsk)->listener = sk; | ||
691 | |||
692 | sock_hold(newsk); | ||
693 | sk_del_node_init(newsk); | ||
694 | sk_acceptq_removed(sk); | ||
695 | sk_add_node(newsk, &pn->hlist); | ||
696 | __sock_put(newsk); | ||
697 | |||
698 | out: | ||
699 | release_sock(sk); | ||
700 | *errp = err; | ||
701 | return newsk; | ||
702 | } | ||
703 | |||
704 | static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) | ||
705 | { | ||
706 | struct pep_sock *pn = pep_sk(sk); | ||
707 | int answ; | ||
708 | |||
709 | switch (cmd) { | ||
710 | case SIOCINQ: | ||
711 | if (sk->sk_state == TCP_LISTEN) | ||
712 | return -EINVAL; | ||
713 | |||
714 | lock_sock(sk); | ||
715 | if (sock_flag(sk, SOCK_URGINLINE) | ||
716 | && !skb_queue_empty(&pn->ctrlreq_queue)) | ||
717 | answ = skb_peek(&pn->ctrlreq_queue)->len; | ||
718 | else if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
719 | answ = skb_peek(&sk->sk_receive_queue)->len; | ||
720 | else | ||
721 | answ = 0; | ||
722 | release_sock(sk); | ||
723 | return put_user(answ, (int __user *)arg); | ||
724 | } | ||
725 | |||
726 | return -ENOIOCTLCMD; | ||
727 | } | ||
728 | |||
729 | static int pep_init(struct sock *sk) | ||
730 | { | ||
731 | struct pep_sock *pn = pep_sk(sk); | ||
732 | |||
733 | INIT_HLIST_HEAD(&pn->ackq); | ||
734 | INIT_HLIST_HEAD(&pn->hlist); | ||
735 | skb_queue_head_init(&pn->ctrlreq_queue); | ||
736 | pn->pipe_handle = PN_PIPE_INVALID_HANDLE; | ||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static int pep_setsockopt(struct sock *sk, int level, int optname, | ||
741 | char __user *optval, int optlen) | ||
742 | { | ||
743 | struct pep_sock *pn = pep_sk(sk); | ||
744 | int val = 0, err = 0; | ||
745 | |||
746 | if (level != SOL_PNPIPE) | ||
747 | return -ENOPROTOOPT; | ||
748 | if (optlen >= sizeof(int)) { | ||
749 | if (get_user(val, (int __user *) optval)) | ||
750 | return -EFAULT; | ||
751 | } | ||
752 | |||
753 | lock_sock(sk); | ||
754 | switch (optname) { | ||
755 | case PNPIPE_ENCAP: | ||
756 | if (val && val != PNPIPE_ENCAP_IP) { | ||
757 | err = -EINVAL; | ||
758 | break; | ||
759 | } | ||
760 | if (!pn->ifindex == !val) | ||
761 | break; /* Nothing to do! */ | ||
762 | if (!capable(CAP_NET_ADMIN)) { | ||
763 | err = -EPERM; | ||
764 | break; | ||
765 | } | ||
766 | if (val) { | ||
767 | release_sock(sk); | ||
768 | err = gprs_attach(sk); | ||
769 | if (err > 0) { | ||
770 | pn->ifindex = err; | ||
771 | err = 0; | ||
772 | } | ||
773 | } else { | ||
774 | pn->ifindex = 0; | ||
775 | release_sock(sk); | ||
776 | gprs_detach(sk); | ||
777 | err = 0; | ||
778 | } | ||
779 | goto out_norel; | ||
780 | default: | ||
781 | err = -ENOPROTOOPT; | ||
782 | } | ||
783 | release_sock(sk); | ||
784 | |||
785 | out_norel: | ||
786 | return err; | ||
787 | } | ||
788 | |||
789 | static int pep_getsockopt(struct sock *sk, int level, int optname, | ||
790 | char __user *optval, int __user *optlen) | ||
791 | { | ||
792 | struct pep_sock *pn = pep_sk(sk); | ||
793 | int len, val; | ||
794 | |||
795 | if (level != SOL_PNPIPE) | ||
796 | return -ENOPROTOOPT; | ||
797 | if (get_user(len, optlen)) | ||
798 | return -EFAULT; | ||
799 | |||
800 | switch (optname) { | ||
801 | case PNPIPE_ENCAP: | ||
802 | val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE; | ||
803 | break; | ||
804 | case PNPIPE_IFINDEX: | ||
805 | val = pn->ifindex; | ||
806 | break; | ||
807 | default: | ||
808 | return -ENOPROTOOPT; | ||
809 | } | ||
810 | |||
811 | len = min_t(unsigned int, sizeof(int), len); | ||
812 | if (put_user(len, optlen)) | ||
813 | return -EFAULT; | ||
814 | if (put_user(val, (int __user *) optval)) | ||
815 | return -EFAULT; | ||
816 | return 0; | ||
817 | } | ||
818 | |||
819 | static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) | ||
820 | { | ||
821 | struct pep_sock *pn = pep_sk(sk); | ||
822 | struct pnpipehdr *ph; | ||
823 | |||
824 | skb_push(skb, 3); | ||
825 | skb_reset_transport_header(skb); | ||
826 | ph = pnp_hdr(skb); | ||
827 | ph->utid = 0; | ||
828 | ph->message_id = PNS_PIPE_DATA; | ||
829 | ph->pipe_handle = pn->pipe_handle; | ||
830 | if (pn_flow_safe(pn->tx_fc) && pn->tx_credits) | ||
831 | pn->tx_credits--; | ||
832 | |||
833 | return pn_skb_send(sk, skb, &pipe_srv); | ||
834 | } | ||
835 | |||
836 | static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, | ||
837 | struct msghdr *msg, size_t len) | ||
838 | { | ||
839 | struct pep_sock *pn = pep_sk(sk); | ||
840 | struct sk_buff *skb = NULL; | ||
841 | long timeo; | ||
842 | int flags = msg->msg_flags; | ||
843 | int err, done; | ||
844 | |||
845 | if (msg->msg_flags & MSG_OOB || !(msg->msg_flags & MSG_EOR)) | ||
846 | return -EOPNOTSUPP; | ||
847 | |||
848 | lock_sock(sk); | ||
849 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | ||
850 | if ((1 << sk->sk_state) & (TCPF_LISTEN|TCPF_CLOSE)) { | ||
851 | err = -ENOTCONN; | ||
852 | goto out; | ||
853 | } | ||
854 | if (sk->sk_state != TCP_ESTABLISHED) { | ||
855 | /* Wait until the pipe gets to enabled state */ | ||
856 | disabled: | ||
857 | err = sk_stream_wait_connect(sk, &timeo); | ||
858 | if (err) | ||
859 | goto out; | ||
860 | |||
861 | if (sk->sk_state == TCP_CLOSE_WAIT) { | ||
862 | err = -ECONNRESET; | ||
863 | goto out; | ||
864 | } | ||
865 | } | ||
866 | BUG_ON(sk->sk_state != TCP_ESTABLISHED); | ||
867 | |||
868 | /* Wait until flow control allows TX */ | ||
869 | done = pn->tx_credits > 0; | ||
870 | while (!done) { | ||
871 | DEFINE_WAIT(wait); | ||
872 | |||
873 | if (!timeo) { | ||
874 | err = -EAGAIN; | ||
875 | goto out; | ||
876 | } | ||
877 | if (signal_pending(current)) { | ||
878 | err = sock_intr_errno(timeo); | ||
879 | goto out; | ||
880 | } | ||
881 | |||
882 | prepare_to_wait(&sk->sk_socket->wait, &wait, | ||
883 | TASK_INTERRUPTIBLE); | ||
884 | done = sk_wait_event(sk, &timeo, pn->tx_credits > 0); | ||
885 | finish_wait(&sk->sk_socket->wait, &wait); | ||
886 | |||
887 | if (sk->sk_state != TCP_ESTABLISHED) | ||
888 | goto disabled; | ||
889 | } | ||
890 | |||
891 | if (!skb) { | ||
892 | skb = sock_alloc_send_skb(sk, MAX_PNPIPE_HEADER + len, | ||
893 | flags & MSG_DONTWAIT, &err); | ||
894 | if (skb == NULL) | ||
895 | goto out; | ||
896 | skb_reserve(skb, MAX_PHONET_HEADER + 3); | ||
897 | |||
898 | if (sk->sk_state != TCP_ESTABLISHED || !pn->tx_credits) | ||
899 | goto disabled; /* sock_alloc_send_skb might sleep */ | ||
900 | } | ||
901 | |||
902 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
903 | if (err < 0) | ||
904 | goto out; | ||
905 | |||
906 | err = pipe_skb_send(sk, skb); | ||
907 | if (err >= 0) | ||
908 | err = len; /* success! */ | ||
909 | skb = NULL; | ||
910 | out: | ||
911 | release_sock(sk); | ||
912 | kfree_skb(skb); | ||
913 | return err; | ||
914 | } | ||
915 | |||
916 | int pep_writeable(struct sock *sk) | ||
917 | { | ||
918 | struct pep_sock *pn = pep_sk(sk); | ||
919 | |||
920 | return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0; | ||
921 | } | ||
922 | |||
923 | int pep_write(struct sock *sk, struct sk_buff *skb) | ||
924 | { | ||
925 | struct sk_buff *rskb, *fs; | ||
926 | int flen = 0; | ||
927 | |||
928 | rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); | ||
929 | if (!rskb) { | ||
930 | kfree_skb(skb); | ||
931 | return -ENOMEM; | ||
932 | } | ||
933 | skb_shinfo(rskb)->frag_list = skb; | ||
934 | rskb->len += skb->len; | ||
935 | rskb->data_len += rskb->len; | ||
936 | rskb->truesize += rskb->len; | ||
937 | |||
938 | /* Avoid nested fragments */ | ||
939 | for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) | ||
940 | flen += fs->len; | ||
941 | skb->next = skb_shinfo(skb)->frag_list; | ||
942 | skb_shinfo(skb)->frag_list = NULL; | ||
943 | skb->len -= flen; | ||
944 | skb->data_len -= flen; | ||
945 | skb->truesize -= flen; | ||
946 | |||
947 | skb_reserve(rskb, MAX_PHONET_HEADER + 3); | ||
948 | return pipe_skb_send(sk, rskb); | ||
949 | } | ||
950 | |||
951 | struct sk_buff *pep_read(struct sock *sk) | ||
952 | { | ||
953 | struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); | ||
954 | |||
955 | if (sk->sk_state == TCP_ESTABLISHED) | ||
956 | pipe_grant_credits(sk); | ||
957 | return skb; | ||
958 | } | ||
959 | |||
960 | static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, | ||
961 | struct msghdr *msg, size_t len, int noblock, | ||
962 | int flags, int *addr_len) | ||
963 | { | ||
964 | struct sk_buff *skb; | ||
965 | int err; | ||
966 | |||
967 | if (unlikely(1 << sk->sk_state & (TCPF_LISTEN | TCPF_CLOSE))) | ||
968 | return -ENOTCONN; | ||
969 | |||
970 | if ((flags & MSG_OOB) || sock_flag(sk, SOCK_URGINLINE)) { | ||
971 | /* Dequeue and acknowledge control request */ | ||
972 | struct pep_sock *pn = pep_sk(sk); | ||
973 | |||
974 | skb = skb_dequeue(&pn->ctrlreq_queue); | ||
975 | if (skb) { | ||
976 | pep_ctrlreq_error(sk, skb, PN_PIPE_NO_ERROR, | ||
977 | GFP_KERNEL); | ||
978 | msg->msg_flags |= MSG_OOB; | ||
979 | goto copy; | ||
980 | } | ||
981 | if (flags & MSG_OOB) | ||
982 | return -EINVAL; | ||
983 | } | ||
984 | |||
985 | skb = skb_recv_datagram(sk, flags, noblock, &err); | ||
986 | lock_sock(sk); | ||
987 | if (skb == NULL) { | ||
988 | if (err == -ENOTCONN && sk->sk_state == TCP_CLOSE_WAIT) | ||
989 | err = -ECONNRESET; | ||
990 | release_sock(sk); | ||
991 | return err; | ||
992 | } | ||
993 | |||
994 | if (sk->sk_state == TCP_ESTABLISHED) | ||
995 | pipe_grant_credits(sk); | ||
996 | release_sock(sk); | ||
997 | copy: | ||
998 | msg->msg_flags |= MSG_EOR; | ||
999 | if (skb->len > len) | ||
1000 | msg->msg_flags |= MSG_TRUNC; | ||
1001 | else | ||
1002 | len = skb->len; | ||
1003 | |||
1004 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); | ||
1005 | if (!err) | ||
1006 | err = (flags & MSG_TRUNC) ? skb->len : len; | ||
1007 | |||
1008 | skb_free_datagram(sk, skb); | ||
1009 | return err; | ||
1010 | } | ||
1011 | |||
1012 | static void pep_sock_unhash(struct sock *sk) | ||
1013 | { | ||
1014 | struct pep_sock *pn = pep_sk(sk); | ||
1015 | struct sock *skparent = NULL; | ||
1016 | |||
1017 | lock_sock(sk); | ||
1018 | if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) { | ||
1019 | skparent = pn->listener; | ||
1020 | sk_del_node_init(sk); | ||
1021 | release_sock(sk); | ||
1022 | |||
1023 | sk = skparent; | ||
1024 | pn = pep_sk(skparent); | ||
1025 | lock_sock(sk); | ||
1026 | } | ||
1027 | /* Unhash a listening sock only when it is closed | ||
1028 | * and all of its active connected pipes are closed. */ | ||
1029 | if (hlist_empty(&pn->hlist)) | ||
1030 | pn_sock_unhash(&pn->pn_sk.sk); | ||
1031 | release_sock(sk); | ||
1032 | |||
1033 | if (skparent) | ||
1034 | sock_put(skparent); | ||
1035 | } | ||
1036 | |||
1037 | static struct proto pep_proto = { | ||
1038 | .close = pep_sock_close, | ||
1039 | .accept = pep_sock_accept, | ||
1040 | .ioctl = pep_ioctl, | ||
1041 | .init = pep_init, | ||
1042 | .setsockopt = pep_setsockopt, | ||
1043 | .getsockopt = pep_getsockopt, | ||
1044 | .sendmsg = pep_sendmsg, | ||
1045 | .recvmsg = pep_recvmsg, | ||
1046 | .backlog_rcv = pep_do_rcv, | ||
1047 | .hash = pn_sock_hash, | ||
1048 | .unhash = pep_sock_unhash, | ||
1049 | .get_port = pn_sock_get_port, | ||
1050 | .obj_size = sizeof(struct pep_sock), | ||
1051 | .owner = THIS_MODULE, | ||
1052 | .name = "PNPIPE", | ||
1053 | }; | ||
1054 | |||
1055 | static struct phonet_protocol pep_pn_proto = { | ||
1056 | .ops = &phonet_stream_ops, | ||
1057 | .prot = &pep_proto, | ||
1058 | .sock_type = SOCK_SEQPACKET, | ||
1059 | }; | ||
1060 | |||
1061 | static int __init pep_register(void) | ||
1062 | { | ||
1063 | return phonet_proto_register(PN_PROTO_PIPE, &pep_pn_proto); | ||
1064 | } | ||
1065 | |||
1066 | static void __exit pep_unregister(void) | ||
1067 | { | ||
1068 | phonet_proto_unregister(PN_PROTO_PIPE, &pep_pn_proto); | ||
1069 | } | ||
1070 | |||
1071 | module_init(pep_register); | ||
1072 | module_exit(pep_unregister); | ||
1073 | MODULE_AUTHOR("Remi Denis-Courmont, Nokia"); | ||
1074 | MODULE_DESCRIPTION("Phonet pipe protocol"); | ||
1075 | MODULE_LICENSE("GPL"); | ||
1076 | MODULE_ALIAS_NET_PF_PROTO(PF_PHONET, PN_PROTO_PIPE); | ||
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c new file mode 100644 index 000000000000..53be9fc82aaa --- /dev/null +++ b/net/phonet/pn_dev.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * File: pn_dev.c | ||
3 | * | ||
4 | * Phonet network device | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * Original author: Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/net.h> | ||
28 | #include <linux/netdevice.h> | ||
29 | #include <linux/phonet.h> | ||
30 | #include <net/sock.h> | ||
31 | #include <net/phonet/pn_dev.h> | ||
32 | |||
33 | /* when accessing, remember to lock with spin_lock(&pndevs.lock); */ | ||
34 | struct phonet_device_list pndevs = { | ||
35 | .list = LIST_HEAD_INIT(pndevs.list), | ||
36 | .lock = __SPIN_LOCK_UNLOCKED(pndevs.lock), | ||
37 | }; | ||
38 | |||
39 | /* Allocate new Phonet device. */ | ||
40 | static struct phonet_device *__phonet_device_alloc(struct net_device *dev) | ||
41 | { | ||
42 | struct phonet_device *pnd = kmalloc(sizeof(*pnd), GFP_ATOMIC); | ||
43 | if (pnd == NULL) | ||
44 | return NULL; | ||
45 | pnd->netdev = dev; | ||
46 | bitmap_zero(pnd->addrs, 64); | ||
47 | |||
48 | list_add(&pnd->list, &pndevs.list); | ||
49 | return pnd; | ||
50 | } | ||
51 | |||
52 | static struct phonet_device *__phonet_get(struct net_device *dev) | ||
53 | { | ||
54 | struct phonet_device *pnd; | ||
55 | |||
56 | list_for_each_entry(pnd, &pndevs.list, list) { | ||
57 | if (pnd->netdev == dev) | ||
58 | return pnd; | ||
59 | } | ||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | static void __phonet_device_free(struct phonet_device *pnd) | ||
64 | { | ||
65 | list_del(&pnd->list); | ||
66 | kfree(pnd); | ||
67 | } | ||
68 | |||
69 | struct net_device *phonet_device_get(struct net *net) | ||
70 | { | ||
71 | struct phonet_device *pnd; | ||
72 | struct net_device *dev; | ||
73 | |||
74 | spin_lock_bh(&pndevs.lock); | ||
75 | list_for_each_entry(pnd, &pndevs.list, list) { | ||
76 | dev = pnd->netdev; | ||
77 | BUG_ON(!dev); | ||
78 | |||
79 | if (dev_net(dev) == net && | ||
80 | (dev->reg_state == NETREG_REGISTERED) && | ||
81 | ((pnd->netdev->flags & IFF_UP)) == IFF_UP) | ||
82 | break; | ||
83 | dev = NULL; | ||
84 | } | ||
85 | if (dev) | ||
86 | dev_hold(dev); | ||
87 | spin_unlock_bh(&pndevs.lock); | ||
88 | return dev; | ||
89 | } | ||
90 | |||
91 | int phonet_address_add(struct net_device *dev, u8 addr) | ||
92 | { | ||
93 | struct phonet_device *pnd; | ||
94 | int err = 0; | ||
95 | |||
96 | spin_lock_bh(&pndevs.lock); | ||
97 | /* Find or create Phonet-specific device data */ | ||
98 | pnd = __phonet_get(dev); | ||
99 | if (pnd == NULL) | ||
100 | pnd = __phonet_device_alloc(dev); | ||
101 | if (unlikely(pnd == NULL)) | ||
102 | err = -ENOMEM; | ||
103 | else if (test_and_set_bit(addr >> 2, pnd->addrs)) | ||
104 | err = -EEXIST; | ||
105 | spin_unlock_bh(&pndevs.lock); | ||
106 | return err; | ||
107 | } | ||
108 | |||
109 | int phonet_address_del(struct net_device *dev, u8 addr) | ||
110 | { | ||
111 | struct phonet_device *pnd; | ||
112 | int err = 0; | ||
113 | |||
114 | spin_lock_bh(&pndevs.lock); | ||
115 | pnd = __phonet_get(dev); | ||
116 | if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) | ||
117 | err = -EADDRNOTAVAIL; | ||
118 | if (bitmap_empty(pnd->addrs, 64)) | ||
119 | __phonet_device_free(pnd); | ||
120 | spin_unlock_bh(&pndevs.lock); | ||
121 | return err; | ||
122 | } | ||
123 | |||
124 | /* Gets a source address toward a destination, through a interface. */ | ||
125 | u8 phonet_address_get(struct net_device *dev, u8 addr) | ||
126 | { | ||
127 | struct phonet_device *pnd; | ||
128 | |||
129 | spin_lock_bh(&pndevs.lock); | ||
130 | pnd = __phonet_get(dev); | ||
131 | if (pnd) { | ||
132 | BUG_ON(bitmap_empty(pnd->addrs, 64)); | ||
133 | |||
134 | /* Use same source address as destination, if possible */ | ||
135 | if (!test_bit(addr >> 2, pnd->addrs)) | ||
136 | addr = find_first_bit(pnd->addrs, 64) << 2; | ||
137 | } else | ||
138 | addr = PN_NO_ADDR; | ||
139 | spin_unlock_bh(&pndevs.lock); | ||
140 | return addr; | ||
141 | } | ||
142 | |||
143 | int phonet_address_lookup(u8 addr) | ||
144 | { | ||
145 | struct phonet_device *pnd; | ||
146 | |||
147 | spin_lock_bh(&pndevs.lock); | ||
148 | list_for_each_entry(pnd, &pndevs.list, list) { | ||
149 | /* Don't allow unregistering devices! */ | ||
150 | if ((pnd->netdev->reg_state != NETREG_REGISTERED) || | ||
151 | ((pnd->netdev->flags & IFF_UP)) != IFF_UP) | ||
152 | continue; | ||
153 | |||
154 | if (test_bit(addr >> 2, pnd->addrs)) { | ||
155 | spin_unlock_bh(&pndevs.lock); | ||
156 | return 0; | ||
157 | } | ||
158 | } | ||
159 | spin_unlock_bh(&pndevs.lock); | ||
160 | return -EADDRNOTAVAIL; | ||
161 | } | ||
162 | |||
163 | /* notify Phonet of device events */ | ||
164 | static int phonet_device_notify(struct notifier_block *me, unsigned long what, | ||
165 | void *arg) | ||
166 | { | ||
167 | struct net_device *dev = arg; | ||
168 | |||
169 | if (what == NETDEV_UNREGISTER) { | ||
170 | struct phonet_device *pnd; | ||
171 | |||
172 | /* Destroy phonet-specific device data */ | ||
173 | spin_lock_bh(&pndevs.lock); | ||
174 | pnd = __phonet_get(dev); | ||
175 | if (pnd) | ||
176 | __phonet_device_free(pnd); | ||
177 | spin_unlock_bh(&pndevs.lock); | ||
178 | } | ||
179 | return 0; | ||
180 | |||
181 | } | ||
182 | |||
183 | static struct notifier_block phonet_device_notifier = { | ||
184 | .notifier_call = phonet_device_notify, | ||
185 | .priority = 0, | ||
186 | }; | ||
187 | |||
188 | /* Initialize Phonet devices list */ | ||
189 | void phonet_device_init(void) | ||
190 | { | ||
191 | register_netdevice_notifier(&phonet_device_notifier); | ||
192 | } | ||
193 | |||
194 | void phonet_device_exit(void) | ||
195 | { | ||
196 | struct phonet_device *pnd, *n; | ||
197 | |||
198 | rtnl_unregister_all(PF_PHONET); | ||
199 | rtnl_lock(); | ||
200 | spin_lock_bh(&pndevs.lock); | ||
201 | |||
202 | list_for_each_entry_safe(pnd, n, &pndevs.list, list) | ||
203 | __phonet_device_free(pnd); | ||
204 | |||
205 | spin_unlock_bh(&pndevs.lock); | ||
206 | rtnl_unlock(); | ||
207 | unregister_netdevice_notifier(&phonet_device_notifier); | ||
208 | } | ||
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c new file mode 100644 index 000000000000..b1770d66bc8d --- /dev/null +++ b/net/phonet/pn_netlink.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * File: pn_netlink.c | ||
3 | * | ||
4 | * Phonet netlink interface | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * Original author: Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/netlink.h> | ||
28 | #include <linux/phonet.h> | ||
29 | #include <net/sock.h> | ||
30 | #include <net/phonet/pn_dev.h> | ||
31 | |||
32 | static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, | ||
33 | u32 pid, u32 seq, int event); | ||
34 | |||
35 | static void rtmsg_notify(int event, struct net_device *dev, u8 addr) | ||
36 | { | ||
37 | struct sk_buff *skb; | ||
38 | int err = -ENOBUFS; | ||
39 | |||
40 | skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) + | ||
41 | nla_total_size(1), GFP_KERNEL); | ||
42 | if (skb == NULL) | ||
43 | goto errout; | ||
44 | err = fill_addr(skb, dev, addr, 0, 0, event); | ||
45 | if (err < 0) { | ||
46 | WARN_ON(err == -EMSGSIZE); | ||
47 | kfree_skb(skb); | ||
48 | goto errout; | ||
49 | } | ||
50 | err = rtnl_notify(skb, dev_net(dev), 0, | ||
51 | RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); | ||
52 | errout: | ||
53 | if (err < 0) | ||
54 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); | ||
55 | } | ||
56 | |||
57 | static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = { | ||
58 | [IFA_LOCAL] = { .type = NLA_U8 }, | ||
59 | }; | ||
60 | |||
61 | static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr) | ||
62 | { | ||
63 | struct net *net = sock_net(skb->sk); | ||
64 | struct nlattr *tb[IFA_MAX+1]; | ||
65 | struct net_device *dev; | ||
66 | struct ifaddrmsg *ifm; | ||
67 | int err; | ||
68 | u8 pnaddr; | ||
69 | |||
70 | if (!capable(CAP_SYS_ADMIN)) | ||
71 | return -EPERM; | ||
72 | |||
73 | ASSERT_RTNL(); | ||
74 | |||
75 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_phonet_policy); | ||
76 | if (err < 0) | ||
77 | return err; | ||
78 | |||
79 | ifm = nlmsg_data(nlh); | ||
80 | if (tb[IFA_LOCAL] == NULL) | ||
81 | return -EINVAL; | ||
82 | pnaddr = nla_get_u8(tb[IFA_LOCAL]); | ||
83 | if (pnaddr & 3) | ||
84 | /* Phonet addresses only have 6 high-order bits */ | ||
85 | return -EINVAL; | ||
86 | |||
87 | dev = __dev_get_by_index(net, ifm->ifa_index); | ||
88 | if (dev == NULL) | ||
89 | return -ENODEV; | ||
90 | |||
91 | if (nlh->nlmsg_type == RTM_NEWADDR) | ||
92 | err = phonet_address_add(dev, pnaddr); | ||
93 | else | ||
94 | err = phonet_address_del(dev, pnaddr); | ||
95 | if (!err) | ||
96 | rtmsg_notify(nlh->nlmsg_type, dev, pnaddr); | ||
97 | return err; | ||
98 | } | ||
99 | |||
100 | static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, | ||
101 | u32 pid, u32 seq, int event) | ||
102 | { | ||
103 | struct ifaddrmsg *ifm; | ||
104 | struct nlmsghdr *nlh; | ||
105 | |||
106 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), 0); | ||
107 | if (nlh == NULL) | ||
108 | return -EMSGSIZE; | ||
109 | |||
110 | ifm = nlmsg_data(nlh); | ||
111 | ifm->ifa_family = AF_PHONET; | ||
112 | ifm->ifa_prefixlen = 0; | ||
113 | ifm->ifa_flags = IFA_F_PERMANENT; | ||
114 | ifm->ifa_scope = RT_SCOPE_LINK; | ||
115 | ifm->ifa_index = dev->ifindex; | ||
116 | NLA_PUT_U8(skb, IFA_LOCAL, addr); | ||
117 | return nlmsg_end(skb, nlh); | ||
118 | |||
119 | nla_put_failure: | ||
120 | nlmsg_cancel(skb, nlh); | ||
121 | return -EMSGSIZE; | ||
122 | } | ||
123 | |||
124 | static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | ||
125 | { | ||
126 | struct phonet_device *pnd; | ||
127 | int dev_idx = 0, dev_start_idx = cb->args[0]; | ||
128 | int addr_idx = 0, addr_start_idx = cb->args[1]; | ||
129 | |||
130 | spin_lock_bh(&pndevs.lock); | ||
131 | list_for_each_entry(pnd, &pndevs.list, list) { | ||
132 | u8 addr; | ||
133 | |||
134 | if (dev_idx > dev_start_idx) | ||
135 | addr_start_idx = 0; | ||
136 | if (dev_idx++ < dev_start_idx) | ||
137 | continue; | ||
138 | |||
139 | addr_idx = 0; | ||
140 | for (addr = find_first_bit(pnd->addrs, 64); addr < 64; | ||
141 | addr = find_next_bit(pnd->addrs, 64, 1+addr)) { | ||
142 | if (addr_idx++ < addr_start_idx) | ||
143 | continue; | ||
144 | |||
145 | if (fill_addr(skb, pnd->netdev, addr << 2, | ||
146 | NETLINK_CB(cb->skb).pid, | ||
147 | cb->nlh->nlmsg_seq, RTM_NEWADDR)) | ||
148 | goto out; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | out: | ||
153 | spin_unlock_bh(&pndevs.lock); | ||
154 | cb->args[0] = dev_idx; | ||
155 | cb->args[1] = addr_idx; | ||
156 | |||
157 | return skb->len; | ||
158 | } | ||
159 | |||
160 | void __init phonet_netlink_register(void) | ||
161 | { | ||
162 | rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL); | ||
163 | rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL); | ||
164 | rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); | ||
165 | } | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c new file mode 100644 index 000000000000..d81740187fb4 --- /dev/null +++ b/net/phonet/socket.c | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * File: socket.c | ||
3 | * | ||
4 | * Phonet sockets | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
9 | * Original author: Sakari Ailus <sakari.ailus@nokia.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * version 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
23 | * 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/net.h> | ||
28 | #include <linux/poll.h> | ||
29 | #include <net/sock.h> | ||
30 | #include <net/tcp_states.h> | ||
31 | |||
32 | #include <linux/phonet.h> | ||
33 | #include <net/phonet/phonet.h> | ||
34 | #include <net/phonet/pep.h> | ||
35 | #include <net/phonet/pn_dev.h> | ||
36 | |||
37 | static int pn_socket_release(struct socket *sock) | ||
38 | { | ||
39 | struct sock *sk = sock->sk; | ||
40 | |||
41 | if (sk) { | ||
42 | sock->sk = NULL; | ||
43 | sk->sk_prot->close(sk, 0); | ||
44 | } | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static struct { | ||
49 | struct hlist_head hlist; | ||
50 | spinlock_t lock; | ||
51 | } pnsocks = { | ||
52 | .hlist = HLIST_HEAD_INIT, | ||
53 | .lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock), | ||
54 | }; | ||
55 | |||
56 | /* | ||
57 | * Find address based on socket address, match only certain fields. | ||
58 | * Also grab sock if it was found. Remember to sock_put it later. | ||
59 | */ | ||
60 | struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn) | ||
61 | { | ||
62 | struct hlist_node *node; | ||
63 | struct sock *sknode; | ||
64 | struct sock *rval = NULL; | ||
65 | u16 obj = pn_sockaddr_get_object(spn); | ||
66 | u8 res = spn->spn_resource; | ||
67 | |||
68 | spin_lock_bh(&pnsocks.lock); | ||
69 | |||
70 | sk_for_each(sknode, node, &pnsocks.hlist) { | ||
71 | struct pn_sock *pn = pn_sk(sknode); | ||
72 | BUG_ON(!pn->sobject); /* unbound socket */ | ||
73 | |||
74 | if (pn_port(obj)) { | ||
75 | /* Look up socket by port */ | ||
76 | if (pn_port(pn->sobject) != pn_port(obj)) | ||
77 | continue; | ||
78 | } else { | ||
79 | /* If port is zero, look up by resource */ | ||
80 | if (pn->resource != res) | ||
81 | continue; | ||
82 | } | ||
83 | if (pn_addr(pn->sobject) | ||
84 | && pn_addr(pn->sobject) != pn_addr(obj)) | ||
85 | continue; | ||
86 | |||
87 | rval = sknode; | ||
88 | sock_hold(sknode); | ||
89 | break; | ||
90 | } | ||
91 | |||
92 | spin_unlock_bh(&pnsocks.lock); | ||
93 | |||
94 | return rval; | ||
95 | |||
96 | } | ||
97 | |||
98 | void pn_sock_hash(struct sock *sk) | ||
99 | { | ||
100 | spin_lock_bh(&pnsocks.lock); | ||
101 | sk_add_node(sk, &pnsocks.hlist); | ||
102 | spin_unlock_bh(&pnsocks.lock); | ||
103 | } | ||
104 | EXPORT_SYMBOL(pn_sock_hash); | ||
105 | |||
106 | void pn_sock_unhash(struct sock *sk) | ||
107 | { | ||
108 | spin_lock_bh(&pnsocks.lock); | ||
109 | sk_del_node_init(sk); | ||
110 | spin_unlock_bh(&pnsocks.lock); | ||
111 | } | ||
112 | EXPORT_SYMBOL(pn_sock_unhash); | ||
113 | |||
114 | static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) | ||
115 | { | ||
116 | struct sock *sk = sock->sk; | ||
117 | struct pn_sock *pn = pn_sk(sk); | ||
118 | struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; | ||
119 | int err; | ||
120 | u16 handle; | ||
121 | u8 saddr; | ||
122 | |||
123 | if (sk->sk_prot->bind) | ||
124 | return sk->sk_prot->bind(sk, addr, len); | ||
125 | |||
126 | if (len < sizeof(struct sockaddr_pn)) | ||
127 | return -EINVAL; | ||
128 | if (spn->spn_family != AF_PHONET) | ||
129 | return -EAFNOSUPPORT; | ||
130 | |||
131 | handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr); | ||
132 | saddr = pn_addr(handle); | ||
133 | if (saddr && phonet_address_lookup(saddr)) | ||
134 | return -EADDRNOTAVAIL; | ||
135 | |||
136 | lock_sock(sk); | ||
137 | if (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) { | ||
138 | err = -EINVAL; /* attempt to rebind */ | ||
139 | goto out; | ||
140 | } | ||
141 | err = sk->sk_prot->get_port(sk, pn_port(handle)); | ||
142 | if (err) | ||
143 | goto out; | ||
144 | |||
145 | /* get_port() sets the port, bind() sets the address if applicable */ | ||
146 | pn->sobject = pn_object(saddr, pn_port(pn->sobject)); | ||
147 | pn->resource = spn->spn_resource; | ||
148 | |||
149 | /* Enable RX on the socket */ | ||
150 | sk->sk_prot->hash(sk); | ||
151 | out: | ||
152 | release_sock(sk); | ||
153 | return err; | ||
154 | } | ||
155 | |||
156 | static int pn_socket_autobind(struct socket *sock) | ||
157 | { | ||
158 | struct sockaddr_pn sa; | ||
159 | int err; | ||
160 | |||
161 | memset(&sa, 0, sizeof(sa)); | ||
162 | sa.spn_family = AF_PHONET; | ||
163 | err = pn_socket_bind(sock, (struct sockaddr *)&sa, | ||
164 | sizeof(struct sockaddr_pn)); | ||
165 | if (err != -EINVAL) | ||
166 | return err; | ||
167 | BUG_ON(!pn_port(pn_sk(sock->sk)->sobject)); | ||
168 | return 0; /* socket was already bound */ | ||
169 | } | ||
170 | |||
171 | static int pn_socket_accept(struct socket *sock, struct socket *newsock, | ||
172 | int flags) | ||
173 | { | ||
174 | struct sock *sk = sock->sk; | ||
175 | struct sock *newsk; | ||
176 | int err; | ||
177 | |||
178 | newsk = sk->sk_prot->accept(sk, flags, &err); | ||
179 | if (!newsk) | ||
180 | return err; | ||
181 | |||
182 | lock_sock(newsk); | ||
183 | sock_graft(newsk, newsock); | ||
184 | newsock->state = SS_CONNECTED; | ||
185 | release_sock(newsk); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int pn_socket_getname(struct socket *sock, struct sockaddr *addr, | ||
190 | int *sockaddr_len, int peer) | ||
191 | { | ||
192 | struct sock *sk = sock->sk; | ||
193 | struct pn_sock *pn = pn_sk(sk); | ||
194 | |||
195 | memset(addr, 0, sizeof(struct sockaddr_pn)); | ||
196 | addr->sa_family = AF_PHONET; | ||
197 | if (!peer) /* Race with bind() here is userland's problem. */ | ||
198 | pn_sockaddr_set_object((struct sockaddr_pn *)addr, | ||
199 | pn->sobject); | ||
200 | |||
201 | *sockaddr_len = sizeof(struct sockaddr_pn); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static unsigned int pn_socket_poll(struct file *file, struct socket *sock, | ||
206 | poll_table *wait) | ||
207 | { | ||
208 | struct sock *sk = sock->sk; | ||
209 | struct pep_sock *pn = pep_sk(sk); | ||
210 | unsigned int mask = 0; | ||
211 | |||
212 | poll_wait(file, &sock->wait, wait); | ||
213 | |||
214 | switch (sk->sk_state) { | ||
215 | case TCP_LISTEN: | ||
216 | return hlist_empty(&pn->ackq) ? 0 : POLLIN; | ||
217 | case TCP_CLOSE: | ||
218 | return POLLERR; | ||
219 | } | ||
220 | |||
221 | if (!skb_queue_empty(&sk->sk_receive_queue)) | ||
222 | mask |= POLLIN | POLLRDNORM; | ||
223 | if (!skb_queue_empty(&pn->ctrlreq_queue)) | ||
224 | mask |= POLLPRI; | ||
225 | if (!mask && sk->sk_state == TCP_CLOSE_WAIT) | ||
226 | return POLLHUP; | ||
227 | |||
228 | if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits) | ||
229 | mask |= POLLOUT | POLLWRNORM | POLLWRBAND; | ||
230 | |||
231 | return mask; | ||
232 | } | ||
233 | |||
234 | static int pn_socket_ioctl(struct socket *sock, unsigned int cmd, | ||
235 | unsigned long arg) | ||
236 | { | ||
237 | struct sock *sk = sock->sk; | ||
238 | struct pn_sock *pn = pn_sk(sk); | ||
239 | |||
240 | if (cmd == SIOCPNGETOBJECT) { | ||
241 | struct net_device *dev; | ||
242 | u16 handle; | ||
243 | u8 saddr; | ||
244 | |||
245 | if (get_user(handle, (__u16 __user *)arg)) | ||
246 | return -EFAULT; | ||
247 | |||
248 | lock_sock(sk); | ||
249 | if (sk->sk_bound_dev_if) | ||
250 | dev = dev_get_by_index(sock_net(sk), | ||
251 | sk->sk_bound_dev_if); | ||
252 | else | ||
253 | dev = phonet_device_get(sock_net(sk)); | ||
254 | if (dev && (dev->flags & IFF_UP)) | ||
255 | saddr = phonet_address_get(dev, pn_addr(handle)); | ||
256 | else | ||
257 | saddr = PN_NO_ADDR; | ||
258 | release_sock(sk); | ||
259 | |||
260 | if (dev) | ||
261 | dev_put(dev); | ||
262 | if (saddr == PN_NO_ADDR) | ||
263 | return -EHOSTUNREACH; | ||
264 | |||
265 | handle = pn_object(saddr, pn_port(pn->sobject)); | ||
266 | return put_user(handle, (__u16 __user *)arg); | ||
267 | } | ||
268 | |||
269 | return sk->sk_prot->ioctl(sk, cmd, arg); | ||
270 | } | ||
271 | |||
272 | static int pn_socket_listen(struct socket *sock, int backlog) | ||
273 | { | ||
274 | struct sock *sk = sock->sk; | ||
275 | int err = 0; | ||
276 | |||
277 | if (sock->state != SS_UNCONNECTED) | ||
278 | return -EINVAL; | ||
279 | if (pn_socket_autobind(sock)) | ||
280 | return -ENOBUFS; | ||
281 | |||
282 | lock_sock(sk); | ||
283 | if (sk->sk_state != TCP_CLOSE) { | ||
284 | err = -EINVAL; | ||
285 | goto out; | ||
286 | } | ||
287 | |||
288 | sk->sk_state = TCP_LISTEN; | ||
289 | sk->sk_ack_backlog = 0; | ||
290 | sk->sk_max_ack_backlog = backlog; | ||
291 | out: | ||
292 | release_sock(sk); | ||
293 | return err; | ||
294 | } | ||
295 | |||
296 | static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
297 | struct msghdr *m, size_t total_len) | ||
298 | { | ||
299 | struct sock *sk = sock->sk; | ||
300 | |||
301 | if (pn_socket_autobind(sock)) | ||
302 | return -EAGAIN; | ||
303 | |||
304 | return sk->sk_prot->sendmsg(iocb, sk, m, total_len); | ||
305 | } | ||
306 | |||
307 | const struct proto_ops phonet_dgram_ops = { | ||
308 | .family = AF_PHONET, | ||
309 | .owner = THIS_MODULE, | ||
310 | .release = pn_socket_release, | ||
311 | .bind = pn_socket_bind, | ||
312 | .connect = sock_no_connect, | ||
313 | .socketpair = sock_no_socketpair, | ||
314 | .accept = sock_no_accept, | ||
315 | .getname = pn_socket_getname, | ||
316 | .poll = datagram_poll, | ||
317 | .ioctl = pn_socket_ioctl, | ||
318 | .listen = sock_no_listen, | ||
319 | .shutdown = sock_no_shutdown, | ||
320 | .setsockopt = sock_no_setsockopt, | ||
321 | .getsockopt = sock_no_getsockopt, | ||
322 | #ifdef CONFIG_COMPAT | ||
323 | .compat_setsockopt = sock_no_setsockopt, | ||
324 | .compat_getsockopt = sock_no_getsockopt, | ||
325 | #endif | ||
326 | .sendmsg = pn_socket_sendmsg, | ||
327 | .recvmsg = sock_common_recvmsg, | ||
328 | .mmap = sock_no_mmap, | ||
329 | .sendpage = sock_no_sendpage, | ||
330 | }; | ||
331 | |||
332 | const struct proto_ops phonet_stream_ops = { | ||
333 | .family = AF_PHONET, | ||
334 | .owner = THIS_MODULE, | ||
335 | .release = pn_socket_release, | ||
336 | .bind = pn_socket_bind, | ||
337 | .connect = sock_no_connect, | ||
338 | .socketpair = sock_no_socketpair, | ||
339 | .accept = pn_socket_accept, | ||
340 | .getname = pn_socket_getname, | ||
341 | .poll = pn_socket_poll, | ||
342 | .ioctl = pn_socket_ioctl, | ||
343 | .listen = pn_socket_listen, | ||
344 | .shutdown = sock_no_shutdown, | ||
345 | .setsockopt = sock_common_setsockopt, | ||
346 | .getsockopt = sock_common_getsockopt, | ||
347 | #ifdef CONFIG_COMPAT | ||
348 | .compat_setsockopt = compat_sock_common_setsockopt, | ||
349 | .compat_getsockopt = compat_sock_common_getsockopt, | ||
350 | #endif | ||
351 | .sendmsg = pn_socket_sendmsg, | ||
352 | .recvmsg = sock_common_recvmsg, | ||
353 | .mmap = sock_no_mmap, | ||
354 | .sendpage = sock_no_sendpage, | ||
355 | }; | ||
356 | EXPORT_SYMBOL(phonet_stream_ops); | ||
357 | |||
358 | static DEFINE_MUTEX(port_mutex); | ||
359 | |||
360 | /* allocate port for a socket */ | ||
361 | int pn_sock_get_port(struct sock *sk, unsigned short sport) | ||
362 | { | ||
363 | static int port_cur; | ||
364 | struct pn_sock *pn = pn_sk(sk); | ||
365 | struct sockaddr_pn try_sa; | ||
366 | struct sock *tmpsk; | ||
367 | |||
368 | memset(&try_sa, 0, sizeof(struct sockaddr_pn)); | ||
369 | try_sa.spn_family = AF_PHONET; | ||
370 | |||
371 | mutex_lock(&port_mutex); | ||
372 | |||
373 | if (!sport) { | ||
374 | /* search free port */ | ||
375 | int port, pmin, pmax; | ||
376 | |||
377 | phonet_get_local_port_range(&pmin, &pmax); | ||
378 | for (port = pmin; port <= pmax; port++) { | ||
379 | port_cur++; | ||
380 | if (port_cur < pmin || port_cur > pmax) | ||
381 | port_cur = pmin; | ||
382 | |||
383 | pn_sockaddr_set_port(&try_sa, port_cur); | ||
384 | tmpsk = pn_find_sock_by_sa(&try_sa); | ||
385 | if (tmpsk == NULL) { | ||
386 | sport = port_cur; | ||
387 | goto found; | ||
388 | } else | ||
389 | sock_put(tmpsk); | ||
390 | } | ||
391 | } else { | ||
392 | /* try to find specific port */ | ||
393 | pn_sockaddr_set_port(&try_sa, sport); | ||
394 | tmpsk = pn_find_sock_by_sa(&try_sa); | ||
395 | if (tmpsk == NULL) | ||
396 | /* No sock there! We can use that port... */ | ||
397 | goto found; | ||
398 | else | ||
399 | sock_put(tmpsk); | ||
400 | } | ||
401 | mutex_unlock(&port_mutex); | ||
402 | |||
403 | /* the port must be in use already */ | ||
404 | return -EADDRINUSE; | ||
405 | |||
406 | found: | ||
407 | mutex_unlock(&port_mutex); | ||
408 | pn->sobject = pn_object(pn_addr(pn->sobject), sport); | ||
409 | return 0; | ||
410 | } | ||
411 | EXPORT_SYMBOL(pn_sock_get_port); | ||
diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c new file mode 100644 index 000000000000..600a4309b8c8 --- /dev/null +++ b/net/phonet/sysctl.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | * File: sysctl.c | ||
3 | * | ||
4 | * Phonet /proc/sys/net/phonet interface implementation | ||
5 | * | ||
6 | * Copyright (C) 2008 Nokia Corporation. | ||
7 | * | ||
8 | * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com> | ||
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 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | */ | ||
24 | |||
25 | #include <linux/seqlock.h> | ||
26 | #include <linux/sysctl.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | |||
30 | #define DYNAMIC_PORT_MIN 0x40 | ||
31 | #define DYNAMIC_PORT_MAX 0x7f | ||
32 | |||
33 | static DEFINE_SEQLOCK(local_port_range_lock); | ||
34 | static int local_port_range_min[2] = {0, 0}; | ||
35 | static int local_port_range_max[2] = {1023, 1023}; | ||
36 | static int local_port_range[2] = {DYNAMIC_PORT_MIN, DYNAMIC_PORT_MAX}; | ||
37 | static struct ctl_table_header *phonet_table_hrd; | ||
38 | |||
39 | static void set_local_port_range(int range[2]) | ||
40 | { | ||
41 | write_seqlock(&local_port_range_lock); | ||
42 | local_port_range[0] = range[0]; | ||
43 | local_port_range[1] = range[1]; | ||
44 | write_sequnlock(&local_port_range_lock); | ||
45 | } | ||
46 | |||
47 | void phonet_get_local_port_range(int *min, int *max) | ||
48 | { | ||
49 | unsigned seq; | ||
50 | do { | ||
51 | seq = read_seqbegin(&local_port_range_lock); | ||
52 | if (min) | ||
53 | *min = local_port_range[0]; | ||
54 | if (max) | ||
55 | *max = local_port_range[1]; | ||
56 | } while (read_seqretry(&local_port_range_lock, seq)); | ||
57 | } | ||
58 | |||
59 | static int proc_local_port_range(ctl_table *table, int write, struct file *filp, | ||
60 | void __user *buffer, | ||
61 | size_t *lenp, loff_t *ppos) | ||
62 | { | ||
63 | int ret; | ||
64 | int range[2] = {local_port_range[0], local_port_range[1]}; | ||
65 | ctl_table tmp = { | ||
66 | .data = &range, | ||
67 | .maxlen = sizeof(range), | ||
68 | .mode = table->mode, | ||
69 | .extra1 = &local_port_range_min, | ||
70 | .extra2 = &local_port_range_max, | ||
71 | }; | ||
72 | |||
73 | ret = proc_dointvec_minmax(&tmp, write, filp, buffer, lenp, ppos); | ||
74 | |||
75 | if (write && ret == 0) { | ||
76 | if (range[1] < range[0]) | ||
77 | ret = -EINVAL; | ||
78 | else | ||
79 | set_local_port_range(range); | ||
80 | } | ||
81 | |||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | static struct ctl_table phonet_table[] = { | ||
86 | { | ||
87 | .ctl_name = CTL_UNNUMBERED, | ||
88 | .procname = "local_port_range", | ||
89 | .data = &local_port_range, | ||
90 | .maxlen = sizeof(local_port_range), | ||
91 | .mode = 0644, | ||
92 | .proc_handler = &proc_local_port_range, | ||
93 | .strategy = NULL, | ||
94 | }, | ||
95 | { .ctl_name = 0 } | ||
96 | }; | ||
97 | |||
98 | struct ctl_path phonet_ctl_path[] = { | ||
99 | { .procname = "net", .ctl_name = CTL_NET, }, | ||
100 | { .procname = "phonet", .ctl_name = CTL_UNNUMBERED, }, | ||
101 | { }, | ||
102 | }; | ||
103 | |||
104 | int __init phonet_sysctl_init(void) | ||
105 | { | ||
106 | phonet_table_hrd = register_sysctl_paths(phonet_ctl_path, phonet_table); | ||
107 | return phonet_table_hrd == NULL ? -ENOMEM : 0; | ||
108 | } | ||
109 | |||
110 | void phonet_sysctl_exit(void) | ||
111 | { | ||
112 | unregister_sysctl_table(phonet_table_hrd); | ||
113 | } | ||
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c index cc49c932641d..bc450397487a 100644 --- a/net/sched/em_cmp.c +++ b/net/sched/em_cmp.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/tc_ematch/tc_em_cmp.h> | 16 | #include <linux/tc_ematch/tc_em_cmp.h> |
17 | #include <asm/unaligned.h> | ||
17 | #include <net/pkt_cls.h> | 18 | #include <net/pkt_cls.h> |
18 | 19 | ||
19 | static inline int cmp_needs_transformation(struct tcf_em_cmp *cmp) | 20 | static inline int cmp_needs_transformation(struct tcf_em_cmp *cmp) |
@@ -37,8 +38,7 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
37 | break; | 38 | break; |
38 | 39 | ||
39 | case TCF_EM_ALIGN_U16: | 40 | case TCF_EM_ALIGN_U16: |
40 | val = *ptr << 8; | 41 | val = get_unaligned_be16(ptr); |
41 | val |= *(ptr+1); | ||
42 | 42 | ||
43 | if (cmp_needs_transformation(cmp)) | 43 | if (cmp_needs_transformation(cmp)) |
44 | val = be16_to_cpu(val); | 44 | val = be16_to_cpu(val); |
@@ -47,10 +47,7 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em, | |||
47 | case TCF_EM_ALIGN_U32: | 47 | case TCF_EM_ALIGN_U32: |
48 | /* Worth checking boundries? The branching seems | 48 | /* Worth checking boundries? The branching seems |
49 | * to get worse. Visit again. */ | 49 | * to get worse. Visit again. */ |
50 | val = *ptr << 24; | 50 | val = get_unaligned_be32(ptr); |
51 | val |= *(ptr+1) << 16; | ||
52 | val |= *(ptr+2) << 8; | ||
53 | val |= *(ptr+3); | ||
54 | 51 | ||
55 | if (cmp_needs_transformation(cmp)) | 52 | if (cmp_needs_transformation(cmp)) |
56 | val = be32_to_cpu(val); | 53 | val = be32_to_cpu(val); |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ec0a0839ce51..31f6b614b59b 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -44,23 +44,29 @@ static inline int qdisc_qlen(struct Qdisc *q) | |||
44 | 44 | ||
45 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) | 45 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) |
46 | { | 46 | { |
47 | if (unlikely(skb->next)) | 47 | q->gso_skb = skb; |
48 | q->gso_skb = skb; | ||
49 | else | ||
50 | q->ops->requeue(skb, q); | ||
51 | |||
52 | __netif_schedule(q); | 48 | __netif_schedule(q); |
49 | |||
53 | return 0; | 50 | return 0; |
54 | } | 51 | } |
55 | 52 | ||
56 | static inline struct sk_buff *dequeue_skb(struct Qdisc *q) | 53 | static inline struct sk_buff *dequeue_skb(struct Qdisc *q) |
57 | { | 54 | { |
58 | struct sk_buff *skb; | 55 | struct sk_buff *skb = q->gso_skb; |
59 | 56 | ||
60 | if ((skb = q->gso_skb)) | 57 | if (unlikely(skb)) { |
61 | q->gso_skb = NULL; | 58 | struct net_device *dev = qdisc_dev(q); |
62 | else | 59 | struct netdev_queue *txq; |
60 | |||
61 | /* check the reason of requeuing without tx lock first */ | ||
62 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | ||
63 | if (!netif_tx_queue_stopped(txq) && !netif_tx_queue_frozen(txq)) | ||
64 | q->gso_skb = NULL; | ||
65 | else | ||
66 | skb = NULL; | ||
67 | } else { | ||
63 | skb = q->dequeue(q); | 68 | skb = q->dequeue(q); |
69 | } | ||
64 | 70 | ||
65 | return skb; | 71 | return skb; |
66 | } | 72 | } |
@@ -327,6 +333,7 @@ struct Qdisc noop_qdisc = { | |||
327 | .flags = TCQ_F_BUILTIN, | 333 | .flags = TCQ_F_BUILTIN, |
328 | .ops = &noop_qdisc_ops, | 334 | .ops = &noop_qdisc_ops, |
329 | .list = LIST_HEAD_INIT(noop_qdisc.list), | 335 | .list = LIST_HEAD_INIT(noop_qdisc.list), |
336 | .requeue.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), | ||
330 | .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), | 337 | .q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock), |
331 | .dev_queue = &noop_netdev_queue, | 338 | .dev_queue = &noop_netdev_queue, |
332 | }; | 339 | }; |
@@ -352,6 +359,7 @@ static struct Qdisc noqueue_qdisc = { | |||
352 | .flags = TCQ_F_BUILTIN, | 359 | .flags = TCQ_F_BUILTIN, |
353 | .ops = &noqueue_qdisc_ops, | 360 | .ops = &noqueue_qdisc_ops, |
354 | .list = LIST_HEAD_INIT(noqueue_qdisc.list), | 361 | .list = LIST_HEAD_INIT(noqueue_qdisc.list), |
362 | .requeue.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), | ||
355 | .q.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), | 363 | .q.lock = __SPIN_LOCK_UNLOCKED(noqueue_qdisc.q.lock), |
356 | .dev_queue = &noqueue_netdev_queue, | 364 | .dev_queue = &noqueue_netdev_queue, |
357 | }; | 365 | }; |
@@ -472,6 +480,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
472 | sch->padded = (char *) sch - (char *) p; | 480 | sch->padded = (char *) sch - (char *) p; |
473 | 481 | ||
474 | INIT_LIST_HEAD(&sch->list); | 482 | INIT_LIST_HEAD(&sch->list); |
483 | skb_queue_head_init(&sch->requeue); | ||
475 | skb_queue_head_init(&sch->q); | 484 | skb_queue_head_init(&sch->q); |
476 | sch->ops = ops; | 485 | sch->ops = ops; |
477 | sch->enqueue = ops->enqueue; | 486 | sch->enqueue = ops->enqueue; |
@@ -540,6 +549,7 @@ void qdisc_destroy(struct Qdisc *qdisc) | |||
540 | dev_put(qdisc_dev(qdisc)); | 549 | dev_put(qdisc_dev(qdisc)); |
541 | 550 | ||
542 | kfree_skb(qdisc->gso_skb); | 551 | kfree_skb(qdisc->gso_skb); |
552 | __skb_queue_purge(&qdisc->requeue); | ||
543 | 553 | ||
544 | kfree((char *) qdisc - qdisc->padded); | 554 | kfree((char *) qdisc - qdisc->padded); |
545 | } | 555 | } |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 8472b8b349c4..abd51cef2413 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -599,11 +599,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
599 | /* Check to see if this is a duplicate. */ | 599 | /* Check to see if this is a duplicate. */ |
600 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 600 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
601 | if (peer) { | 601 | if (peer) { |
602 | /* An UNKNOWN state is only set on transports added by | ||
603 | * user in sctp_connectx() call. Such transports should be | ||
604 | * considered CONFIRMED per RFC 4960, Section 5.4. | ||
605 | */ | ||
602 | if (peer->state == SCTP_UNKNOWN) { | 606 | if (peer->state == SCTP_UNKNOWN) { |
603 | if (peer_state == SCTP_ACTIVE) | 607 | peer->state = SCTP_ACTIVE; |
604 | peer->state = SCTP_ACTIVE; | ||
605 | if (peer_state == SCTP_UNCONFIRMED) | ||
606 | peer->state = SCTP_UNCONFIRMED; | ||
607 | } | 608 | } |
608 | return peer; | 609 | return peer; |
609 | } | 610 | } |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index f62bc2468935..6d5944a745d4 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -457,7 +457,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
457 | { | 457 | { |
458 | int error = 0; | 458 | int error = 0; |
459 | 459 | ||
460 | if (sctp_is_any(addr)) { | 460 | if (sctp_is_any(NULL, addr)) { |
461 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); | 461 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); |
462 | } else if (sctp_in_scope(addr, scope)) { | 462 | } else if (sctp_in_scope(addr, scope)) { |
463 | /* Now that the address is in scope, check to see if | 463 | /* Now that the address is in scope, check to see if |
@@ -477,11 +477,21 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
477 | } | 477 | } |
478 | 478 | ||
479 | /* Is this a wildcard address? */ | 479 | /* Is this a wildcard address? */ |
480 | int sctp_is_any(const union sctp_addr *addr) | 480 | int sctp_is_any(struct sock *sk, const union sctp_addr *addr) |
481 | { | 481 | { |
482 | struct sctp_af *af = sctp_get_af_specific(addr->sa.sa_family); | 482 | unsigned short fam = 0; |
483 | struct sctp_af *af; | ||
484 | |||
485 | /* Try to get the right address family */ | ||
486 | if (addr->sa.sa_family != AF_UNSPEC) | ||
487 | fam = addr->sa.sa_family; | ||
488 | else if (sk) | ||
489 | fam = sk->sk_family; | ||
490 | |||
491 | af = sctp_get_af_specific(fam); | ||
483 | if (!af) | 492 | if (!af) |
484 | return 0; | 493 | return 0; |
494 | |||
485 | return af->is_any(addr); | 495 | return af->is_any(addr); |
486 | } | 496 | } |
487 | 497 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 47f91afa0211..c78da3c9dd34 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -837,6 +837,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, | |||
837 | struct sctp_sock *opt) | 837 | struct sctp_sock *opt) |
838 | { | 838 | { |
839 | struct sctp_af *af1, *af2; | 839 | struct sctp_af *af1, *af2; |
840 | struct sock *sk = sctp_opt2sk(opt); | ||
840 | 841 | ||
841 | af1 = sctp_get_af_specific(addr1->sa.sa_family); | 842 | af1 = sctp_get_af_specific(addr1->sa.sa_family); |
842 | af2 = sctp_get_af_specific(addr2->sa.sa_family); | 843 | af2 = sctp_get_af_specific(addr2->sa.sa_family); |
@@ -845,11 +846,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, | |||
845 | return 0; | 846 | return 0; |
846 | 847 | ||
847 | /* If the socket is IPv6 only, v4 addrs will not match */ | 848 | /* If the socket is IPv6 only, v4 addrs will not match */ |
848 | if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) | 849 | if (__ipv6_only_sock(sk) && af1 != af2) |
849 | return 0; | 850 | return 0; |
850 | 851 | ||
851 | /* Today, wildcard AF_INET/AF_INET6. */ | 852 | /* Today, wildcard AF_INET/AF_INET6. */ |
852 | if (sctp_is_any(addr1) || sctp_is_any(addr2)) | 853 | if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) |
853 | return 1; | 854 | return 1; |
854 | 855 | ||
855 | if (addr1->sa.sa_family != addr2->sa.sa_family) | 856 | if (addr1->sa.sa_family != addr2->sa.sa_family) |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 0dc4a7dfb234..c3f417f7ec6e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -533,7 +533,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { | 533 | if (!(dst->dev->features & NETIF_F_NO_CSUM)) { |
534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 534 | crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); |
535 | crc32 = sctp_end_cksum(crc32); | 535 | crc32 = sctp_end_cksum(crc32); |
536 | } | 536 | } else |
537 | nskb->ip_summed = CHECKSUM_UNNECESSARY; | ||
537 | 538 | ||
538 | /* 3) Put the resultant value into the checksum field in the | 539 | /* 3) Put the resultant value into the checksum field in the |
539 | * common header, and leave the rest of the bits unchanged. | 540 | * common header, and leave the rest of the bits unchanged. |
@@ -698,7 +699,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, | |||
698 | * When a Fast Retransmit is being performed the sender SHOULD | 699 | * When a Fast Retransmit is being performed the sender SHOULD |
699 | * ignore the value of cwnd and SHOULD NOT delay retransmission. | 700 | * ignore the value of cwnd and SHOULD NOT delay retransmission. |
700 | */ | 701 | */ |
701 | if (chunk->fast_retransmit <= 0) | 702 | if (chunk->fast_retransmit != SCTP_NEED_FRTX) |
702 | if (transport->flight_size >= transport->cwnd) { | 703 | if (transport->flight_size >= transport->cwnd) { |
703 | retval = SCTP_XMIT_RWND_FULL; | 704 | retval = SCTP_XMIT_RWND_FULL; |
704 | goto finish; | 705 | goto finish; |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 4328ad5439c9..247ebc95c1e5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -420,7 +420,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
420 | * be added to the retransmit queue. | 420 | * be added to the retransmit queue. |
421 | */ | 421 | */ |
422 | if ((reason == SCTP_RTXR_FAST_RTX && | 422 | if ((reason == SCTP_RTXR_FAST_RTX && |
423 | (chunk->fast_retransmit > 0)) || | 423 | (chunk->fast_retransmit == SCTP_NEED_FRTX)) || |
424 | (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { | 424 | (reason != SCTP_RTXR_FAST_RTX && !chunk->tsn_gap_acked)) { |
425 | /* If this chunk was sent less then 1 rto ago, do not | 425 | /* If this chunk was sent less then 1 rto ago, do not |
426 | * retransmit this chunk, but give the peer time | 426 | * retransmit this chunk, but give the peer time |
@@ -650,8 +650,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
650 | /* Mark the chunk as ineligible for fast retransmit | 650 | /* Mark the chunk as ineligible for fast retransmit |
651 | * after it is retransmitted. | 651 | * after it is retransmitted. |
652 | */ | 652 | */ |
653 | if (chunk->fast_retransmit > 0) | 653 | if (chunk->fast_retransmit == SCTP_NEED_FRTX) |
654 | chunk->fast_retransmit = -1; | 654 | chunk->fast_retransmit = SCTP_DONT_FRTX; |
655 | 655 | ||
656 | /* Force start T3-rtx timer when fast retransmitting | 656 | /* Force start T3-rtx timer when fast retransmitting |
657 | * the earliest outstanding TSN | 657 | * the earliest outstanding TSN |
@@ -680,8 +680,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
680 | */ | 680 | */ |
681 | if (rtx_timeout || fast_rtx) { | 681 | if (rtx_timeout || fast_rtx) { |
682 | list_for_each_entry(chunk1, lqueue, transmitted_list) { | 682 | list_for_each_entry(chunk1, lqueue, transmitted_list) { |
683 | if (chunk1->fast_retransmit > 0) | 683 | if (chunk1->fast_retransmit == SCTP_NEED_FRTX) |
684 | chunk1->fast_retransmit = -1; | 684 | chunk1->fast_retransmit = SCTP_DONT_FRTX; |
685 | } | 685 | } |
686 | } | 686 | } |
687 | 687 | ||
@@ -1129,12 +1129,13 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1129 | unsigned outstanding; | 1129 | unsigned outstanding; |
1130 | struct sctp_transport *primary = asoc->peer.primary_path; | 1130 | struct sctp_transport *primary = asoc->peer.primary_path; |
1131 | int count_of_newacks = 0; | 1131 | int count_of_newacks = 0; |
1132 | int gap_ack_blocks; | ||
1132 | 1133 | ||
1133 | /* Grab the association's destination address list. */ | 1134 | /* Grab the association's destination address list. */ |
1134 | transport_list = &asoc->peer.transport_addr_list; | 1135 | transport_list = &asoc->peer.transport_addr_list; |
1135 | 1136 | ||
1136 | sack_ctsn = ntohl(sack->cum_tsn_ack); | 1137 | sack_ctsn = ntohl(sack->cum_tsn_ack); |
1137 | 1138 | gap_ack_blocks = ntohs(sack->num_gap_ack_blocks); | |
1138 | /* | 1139 | /* |
1139 | * SFR-CACC algorithm: | 1140 | * SFR-CACC algorithm: |
1140 | * On receipt of a SACK the sender SHOULD execute the | 1141 | * On receipt of a SACK the sender SHOULD execute the |
@@ -1144,35 +1145,38 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1144 | * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be | 1145 | * on the current primary, the CHANGEOVER_ACTIVE flag SHOULD be |
1145 | * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for | 1146 | * cleared. The CYCLING_CHANGEOVER flag SHOULD also be cleared for |
1146 | * all destinations. | 1147 | * all destinations. |
1147 | */ | ||
1148 | if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { | ||
1149 | primary->cacc.changeover_active = 0; | ||
1150 | list_for_each_entry(transport, transport_list, | ||
1151 | transports) { | ||
1152 | transport->cacc.cycling_changeover = 0; | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | /* | ||
1157 | * SFR-CACC algorithm: | ||
1158 | * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE | 1148 | * 2) If the SACK contains gap acks and the flag CHANGEOVER_ACTIVE |
1159 | * is set the receiver of the SACK MUST take the following actions: | 1149 | * is set the receiver of the SACK MUST take the following actions: |
1160 | * | 1150 | * |
1161 | * A) Initialize the cacc_saw_newack to 0 for all destination | 1151 | * A) Initialize the cacc_saw_newack to 0 for all destination |
1162 | * addresses. | 1152 | * addresses. |
1153 | * | ||
1154 | * Only bother if changeover_active is set. Otherwise, this is | ||
1155 | * totally suboptimal to do on every SACK. | ||
1163 | */ | 1156 | */ |
1164 | if (sack->num_gap_ack_blocks && | 1157 | if (primary->cacc.changeover_active) { |
1165 | primary->cacc.changeover_active) { | 1158 | u8 clear_cycling = 0; |
1166 | list_for_each_entry(transport, transport_list, transports) { | 1159 | |
1167 | transport->cacc.cacc_saw_newack = 0; | 1160 | if (TSN_lte(primary->cacc.next_tsn_at_change, sack_ctsn)) { |
1161 | primary->cacc.changeover_active = 0; | ||
1162 | clear_cycling = 1; | ||
1163 | } | ||
1164 | |||
1165 | if (clear_cycling || gap_ack_blocks) { | ||
1166 | list_for_each_entry(transport, transport_list, | ||
1167 | transports) { | ||
1168 | if (clear_cycling) | ||
1169 | transport->cacc.cycling_changeover = 0; | ||
1170 | if (gap_ack_blocks) | ||
1171 | transport->cacc.cacc_saw_newack = 0; | ||
1172 | } | ||
1168 | } | 1173 | } |
1169 | } | 1174 | } |
1170 | 1175 | ||
1171 | /* Get the highest TSN in the sack. */ | 1176 | /* Get the highest TSN in the sack. */ |
1172 | highest_tsn = sack_ctsn; | 1177 | highest_tsn = sack_ctsn; |
1173 | if (sack->num_gap_ack_blocks) | 1178 | if (gap_ack_blocks) |
1174 | highest_tsn += | 1179 | highest_tsn += ntohs(frags[gap_ack_blocks - 1].gab.end); |
1175 | ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); | ||
1176 | 1180 | ||
1177 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { | 1181 | if (TSN_lt(asoc->highest_sacked, highest_tsn)) { |
1178 | highest_new_tsn = highest_tsn; | 1182 | highest_new_tsn = highest_tsn; |
@@ -1181,11 +1185,11 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1181 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); | 1185 | highest_new_tsn = sctp_highest_new_tsn(sack, asoc); |
1182 | } | 1186 | } |
1183 | 1187 | ||
1188 | |||
1184 | /* Run through the retransmit queue. Credit bytes received | 1189 | /* Run through the retransmit queue. Credit bytes received |
1185 | * and free those chunks that we can. | 1190 | * and free those chunks that we can. |
1186 | */ | 1191 | */ |
1187 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); | 1192 | sctp_check_transmitted(q, &q->retransmit, NULL, sack, highest_new_tsn); |
1188 | sctp_mark_missing(q, &q->retransmit, NULL, highest_new_tsn, 0); | ||
1189 | 1193 | ||
1190 | /* Run through the transmitted queue. | 1194 | /* Run through the transmitted queue. |
1191 | * Credit bytes received and free those chunks which we can. | 1195 | * Credit bytes received and free those chunks which we can. |
@@ -1204,9 +1208,10 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) | |||
1204 | count_of_newacks ++; | 1208 | count_of_newacks ++; |
1205 | } | 1209 | } |
1206 | 1210 | ||
1207 | list_for_each_entry(transport, transport_list, transports) { | 1211 | if (gap_ack_blocks) { |
1208 | sctp_mark_missing(q, &transport->transmitted, transport, | 1212 | list_for_each_entry(transport, transport_list, transports) |
1209 | highest_new_tsn, count_of_newacks); | 1213 | sctp_mark_missing(q, &transport->transmitted, transport, |
1214 | highest_new_tsn, count_of_newacks); | ||
1210 | } | 1215 | } |
1211 | 1216 | ||
1212 | /* Move the Cumulative TSN Ack Point if appropriate. */ | 1217 | /* Move the Cumulative TSN Ack Point if appropriate. */ |
@@ -1651,7 +1656,7 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1651 | * chunk if it has NOT been fast retransmitted or marked for | 1656 | * chunk if it has NOT been fast retransmitted or marked for |
1652 | * fast retransmit already. | 1657 | * fast retransmit already. |
1653 | */ | 1658 | */ |
1654 | if (!chunk->fast_retransmit && | 1659 | if (chunk->fast_retransmit == SCTP_CAN_FRTX && |
1655 | !chunk->tsn_gap_acked && | 1660 | !chunk->tsn_gap_acked && |
1656 | TSN_lt(tsn, highest_new_tsn_in_sack)) { | 1661 | TSN_lt(tsn, highest_new_tsn_in_sack)) { |
1657 | 1662 | ||
@@ -1676,7 +1681,7 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1676 | */ | 1681 | */ |
1677 | 1682 | ||
1678 | if (chunk->tsn_missing_report >= 3) { | 1683 | if (chunk->tsn_missing_report >= 3) { |
1679 | chunk->fast_retransmit = 1; | 1684 | chunk->fast_retransmit = SCTP_NEED_FRTX; |
1680 | do_fast_retransmit = 1; | 1685 | do_fast_retransmit = 1; |
1681 | } | 1686 | } |
1682 | } | 1687 | } |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index e8ca4e54981f..76726bcff3e9 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1012,6 +1012,29 @@ end: | |||
1012 | return retval; | 1012 | return retval; |
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
1016 | const struct sctp_association *asoc, | ||
1017 | const struct sctp_chunk *chunk, | ||
1018 | struct sctp_paramhdr *param) | ||
1019 | { | ||
1020 | struct sctp_chunk *retval; | ||
1021 | static const char error[] = "The following parameter had invalid length:"; | ||
1022 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
1023 | sizeof(sctp_paramhdr_t); | ||
1024 | |||
1025 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
1026 | if (!retval) | ||
1027 | goto nodata; | ||
1028 | |||
1029 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
1030 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1031 | sctp_addto_chunk(retval, sizeof(error), error); | ||
1032 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
1033 | |||
1034 | nodata: | ||
1035 | return retval; | ||
1036 | } | ||
1037 | |||
1015 | /* Make a HEARTBEAT chunk. */ | 1038 | /* Make a HEARTBEAT chunk. */ |
1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1039 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1017 | const struct sctp_transport *transport, | 1040 | const struct sctp_transport *transport, |
@@ -1188,7 +1211,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb, | |||
1188 | */ | 1211 | */ |
1189 | retval->tsn_missing_report = 0; | 1212 | retval->tsn_missing_report = 0; |
1190 | retval->tsn_gap_acked = 0; | 1213 | retval->tsn_gap_acked = 0; |
1191 | retval->fast_retransmit = 0; | 1214 | retval->fast_retransmit = SCTP_CAN_FRTX; |
1192 | 1215 | ||
1193 | /* If this is a fragmented message, track all fragments | 1216 | /* If this is a fragmented message, track all fragments |
1194 | * of the message (for SEND_FAILED). | 1217 | * of the message (for SEND_FAILED). |
@@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1782 | const struct sctp_chunk *chunk, | 1805 | const struct sctp_chunk *chunk, |
1783 | struct sctp_chunk **errp) | 1806 | struct sctp_chunk **errp) |
1784 | { | 1807 | { |
1785 | static const char error[] = "The following parameter had invalid length:"; | ||
1786 | size_t payload_len = WORD_ROUND(sizeof(error)) + | ||
1787 | sizeof(sctp_paramhdr_t); | ||
1788 | |||
1789 | |||
1790 | /* This is a fatal error. Any accumulated non-fatal errors are | 1808 | /* This is a fatal error. Any accumulated non-fatal errors are |
1791 | * not reported. | 1809 | * not reported. |
1792 | */ | 1810 | */ |
@@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1794 | sctp_chunk_free(*errp); | 1812 | sctp_chunk_free(*errp); |
1795 | 1813 | ||
1796 | /* Create an error chunk and fill it in with our payload. */ | 1814 | /* Create an error chunk and fill it in with our payload. */ |
1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1815 | *errp = sctp_make_violation_paramlen(asoc, chunk, param); |
1798 | |||
1799 | if (*errp) { | ||
1800 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | ||
1801 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
1802 | sctp_addto_chunk(*errp, sizeof(error), error); | ||
1803 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
1804 | } | ||
1805 | 1816 | ||
1806 | return 0; | 1817 | return 0; |
1807 | } | 1818 | } |
@@ -1886,11 +1897,13 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1886 | /* if the peer reports AUTH, assume that he | 1897 | /* if the peer reports AUTH, assume that he |
1887 | * supports AUTH. | 1898 | * supports AUTH. |
1888 | */ | 1899 | */ |
1889 | asoc->peer.auth_capable = 1; | 1900 | if (sctp_auth_enable) |
1901 | asoc->peer.auth_capable = 1; | ||
1890 | break; | 1902 | break; |
1891 | case SCTP_CID_ASCONF: | 1903 | case SCTP_CID_ASCONF: |
1892 | case SCTP_CID_ASCONF_ACK: | 1904 | case SCTP_CID_ASCONF_ACK: |
1893 | asoc->peer.asconf_capable = 1; | 1905 | if (sctp_addip_enable) |
1906 | asoc->peer.asconf_capable = 1; | ||
1894 | break; | 1907 | break; |
1895 | default: | 1908 | default: |
1896 | break; | 1909 | break; |
@@ -2319,12 +2332,10 @@ clean_up: | |||
2319 | /* Release the transport structures. */ | 2332 | /* Release the transport structures. */ |
2320 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 2333 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
2321 | transport = list_entry(pos, struct sctp_transport, transports); | 2334 | transport = list_entry(pos, struct sctp_transport, transports); |
2322 | list_del_init(pos); | 2335 | if (transport->state != SCTP_ACTIVE) |
2323 | sctp_transport_free(transport); | 2336 | sctp_assoc_rm_peer(asoc, transport); |
2324 | } | 2337 | } |
2325 | 2338 | ||
2326 | asoc->peer.transport_count = 0; | ||
2327 | |||
2328 | nomem: | 2339 | nomem: |
2329 | return 0; | 2340 | return 0; |
2330 | } | 2341 | } |
@@ -2456,10 +2467,13 @@ do_addr_param: | |||
2456 | break; | 2467 | break; |
2457 | 2468 | ||
2458 | case SCTP_PARAM_ADAPTATION_LAYER_IND: | 2469 | case SCTP_PARAM_ADAPTATION_LAYER_IND: |
2459 | asoc->peer.adaptation_ind = param.aind->adaptation_ind; | 2470 | asoc->peer.adaptation_ind = ntohl(param.aind->adaptation_ind); |
2460 | break; | 2471 | break; |
2461 | 2472 | ||
2462 | case SCTP_PARAM_SET_PRIMARY: | 2473 | case SCTP_PARAM_SET_PRIMARY: |
2474 | if (!sctp_addip_enable) | ||
2475 | goto fall_through; | ||
2476 | |||
2463 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2477 | addr_param = param.v + sizeof(sctp_addip_param_t); |
2464 | 2478 | ||
2465 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2479 | af = sctp_get_af_specific(param_type2af(param.p->type)); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 9732c797e8ed..13d9eea5cf1a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -889,6 +889,35 @@ static void sctp_cmd_adaptation_ind(sctp_cmd_seq_t *commands, | |||
889 | sctp_ulpq_tail_event(&asoc->ulpq, ev); | 889 | sctp_ulpq_tail_event(&asoc->ulpq, ev); |
890 | } | 890 | } |
891 | 891 | ||
892 | |||
893 | static void sctp_cmd_t1_timer_update(struct sctp_association *asoc, | ||
894 | sctp_event_timeout_t timer, | ||
895 | char *name) | ||
896 | { | ||
897 | struct sctp_transport *t; | ||
898 | |||
899 | t = asoc->init_last_sent_to; | ||
900 | asoc->init_err_counter++; | ||
901 | |||
902 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
903 | asoc->timeouts[timer] *= 2; | ||
904 | if (asoc->timeouts[timer] > asoc->max_init_timeo) { | ||
905 | asoc->timeouts[timer] = asoc->max_init_timeo; | ||
906 | } | ||
907 | asoc->init_cycle++; | ||
908 | SCTP_DEBUG_PRINTK( | ||
909 | "T1 %s Timeout adjustment" | ||
910 | " init_err_counter: %d" | ||
911 | " cycle: %d" | ||
912 | " timeout: %ld\n", | ||
913 | name, | ||
914 | asoc->init_err_counter, | ||
915 | asoc->init_cycle, | ||
916 | asoc->timeouts[timer]); | ||
917 | } | ||
918 | |||
919 | } | ||
920 | |||
892 | /* These three macros allow us to pull the debugging code out of the | 921 | /* These three macros allow us to pull the debugging code out of the |
893 | * main flow of sctp_do_sm() to keep attention focused on the real | 922 | * main flow of sctp_do_sm() to keep attention focused on the real |
894 | * functionality there. | 923 | * functionality there. |
@@ -1196,6 +1225,11 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1196 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 1225 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
1197 | SCTP_CHUNK(cmd->obj.ptr)); | 1226 | SCTP_CHUNK(cmd->obj.ptr)); |
1198 | 1227 | ||
1228 | if (new_obj->transport) { | ||
1229 | new_obj->transport->init_sent_count++; | ||
1230 | asoc->init_last_sent_to = new_obj->transport; | ||
1231 | } | ||
1232 | |||
1199 | /* FIXME - Eventually come up with a cleaner way to | 1233 | /* FIXME - Eventually come up with a cleaner way to |
1200 | * enabling COOKIE-ECHO + DATA bundling during | 1234 | * enabling COOKIE-ECHO + DATA bundling during |
1201 | * multihoming stale cookie scenarios, the following | 1235 | * multihoming stale cookie scenarios, the following |
@@ -1345,26 +1379,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1345 | * all transports have been tried at the current | 1379 | * all transports have been tried at the current |
1346 | * timeout. | 1380 | * timeout. |
1347 | */ | 1381 | */ |
1348 | t = asoc->init_last_sent_to; | 1382 | sctp_cmd_t1_timer_update(asoc, |
1349 | asoc->init_err_counter++; | 1383 | SCTP_EVENT_TIMEOUT_T1_INIT, |
1350 | 1384 | "INIT"); | |
1351 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
1352 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
1353 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
1354 | asoc->max_init_timeo) { | ||
1355 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
1356 | asoc->max_init_timeo; | ||
1357 | } | ||
1358 | asoc->init_cycle++; | ||
1359 | SCTP_DEBUG_PRINTK( | ||
1360 | "T1 INIT Timeout adjustment" | ||
1361 | " init_err_counter: %d" | ||
1362 | " cycle: %d" | ||
1363 | " timeout: %ld\n", | ||
1364 | asoc->init_err_counter, | ||
1365 | asoc->init_cycle, | ||
1366 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
1367 | } | ||
1368 | 1385 | ||
1369 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | 1386 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, |
1370 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 1387 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
@@ -1377,20 +1394,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1377 | * all transports have been tried at the current | 1394 | * all transports have been tried at the current |
1378 | * timeout. | 1395 | * timeout. |
1379 | */ | 1396 | */ |
1380 | asoc->init_err_counter++; | 1397 | sctp_cmd_t1_timer_update(asoc, |
1381 | 1398 | SCTP_EVENT_TIMEOUT_T1_COOKIE, | |
1382 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; | 1399 | "COOKIE"); |
1383 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
1384 | asoc->max_init_timeo) { | ||
1385 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
1386 | asoc->max_init_timeo; | ||
1387 | } | ||
1388 | SCTP_DEBUG_PRINTK( | ||
1389 | "T1 COOKIE Timeout adjustment" | ||
1390 | " init_err_counter: %d" | ||
1391 | " timeout: %ld\n", | ||
1392 | asoc->init_err_counter, | ||
1393 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
1394 | 1400 | ||
1395 | /* If we've sent any data bundled with | 1401 | /* If we've sent any data bundled with |
1396 | * COOKIE-ECHO we need to resend. | 1402 | * COOKIE-ECHO we need to resend. |
@@ -1422,6 +1428,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1422 | case SCTP_CMD_INIT_COUNTER_RESET: | 1428 | case SCTP_CMD_INIT_COUNTER_RESET: |
1423 | asoc->init_err_counter = 0; | 1429 | asoc->init_err_counter = 0; |
1424 | asoc->init_cycle = 0; | 1430 | asoc->init_cycle = 0; |
1431 | list_for_each_entry(t, &asoc->peer.transport_addr_list, | ||
1432 | transports) { | ||
1433 | t->init_sent_count = 0; | ||
1434 | } | ||
1425 | break; | 1435 | break; |
1426 | 1436 | ||
1427 | case SCTP_CMD_REPORT_DUP: | 1437 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..ea3a34cbe470 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
119 | const struct sctp_endpoint *ep, | 119 | const struct sctp_endpoint *ep, |
120 | const struct sctp_association *asoc, | 120 | const struct sctp_association *asoc, |
121 | const sctp_subtype_t type, | 121 | const sctp_subtype_t type, |
122 | void *arg, | 122 | void *arg, void *ext, |
123 | sctp_cmd_seq_t *commands); | 123 | sctp_cmd_seq_t *commands); |
124 | 124 | ||
125 | static sctp_disposition_t sctp_sf_violation_ctsn( | 125 | static sctp_disposition_t sctp_sf_violation_ctsn( |
@@ -315,8 +315,10 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
315 | /* If the packet is an OOTB packet which is temporarily on the | 315 | /* If the packet is an OOTB packet which is temporarily on the |
316 | * control endpoint, respond with an ABORT. | 316 | * control endpoint, respond with an ABORT. |
317 | */ | 317 | */ |
318 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) | 318 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { |
319 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
319 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 320 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
321 | } | ||
320 | 322 | ||
321 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification | 323 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification |
322 | * Tag. | 324 | * Tag. |
@@ -635,8 +637,10 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
635 | /* If the packet is an OOTB packet which is temporarily on the | 637 | /* If the packet is an OOTB packet which is temporarily on the |
636 | * control endpoint, respond with an ABORT. | 638 | * control endpoint, respond with an ABORT. |
637 | */ | 639 | */ |
638 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) | 640 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { |
641 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
639 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 642 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
643 | } | ||
640 | 644 | ||
641 | /* Make sure that the COOKIE_ECHO chunk has a valid length. | 645 | /* Make sure that the COOKIE_ECHO chunk has a valid length. |
642 | * In this case, we check that we have enough for at least a | 646 | * In this case, we check that we have enough for at least a |
@@ -2076,10 +2080,6 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2076 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | 2080 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) |
2077 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 2081 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); |
2078 | 2082 | ||
2079 | /* Stop the T5-shutdown guard timer. */ | ||
2080 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | ||
2081 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
2082 | |||
2083 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2083 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); |
2084 | } | 2084 | } |
2085 | 2085 | ||
@@ -3382,6 +3382,8 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, | |||
3382 | * packet and the state function that handles OOTB SHUTDOWN_ACK is | 3382 | * packet and the state function that handles OOTB SHUTDOWN_ACK is |
3383 | * called with a NULL association. | 3383 | * called with a NULL association. |
3384 | */ | 3384 | */ |
3385 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | ||
3386 | |||
3385 | return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); | 3387 | return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); |
3386 | } | 3388 | } |
3387 | 3389 | ||
@@ -3425,7 +3427,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3425 | addr_param = (union sctp_addr_param *)hdr->params; | 3427 | addr_param = (union sctp_addr_param *)hdr->params; |
3426 | length = ntohs(addr_param->p.length); | 3428 | length = ntohs(addr_param->p.length); |
3427 | if (length < sizeof(sctp_paramhdr_t)) | 3429 | if (length < sizeof(sctp_paramhdr_t)) |
3428 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3430 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3429 | (void *)addr_param, commands); | 3431 | (void *)addr_param, commands); |
3430 | 3432 | ||
3431 | /* Verify the ASCONF chunk before processing it. */ | 3433 | /* Verify the ASCONF chunk before processing it. */ |
@@ -3433,8 +3435,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3433 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3435 | (sctp_paramhdr_t *)((void *)addr_param + length), |
3434 | (void *)chunk->chunk_end, | 3436 | (void *)chunk->chunk_end, |
3435 | &err_param)) | 3437 | &err_param)) |
3436 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3438 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3437 | (void *)&err_param, commands); | 3439 | (void *)err_param, commands); |
3438 | 3440 | ||
3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3441 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
3440 | * the endpoint stored in a new association variable | 3442 | * the endpoint stored in a new association variable |
@@ -3542,8 +3544,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3542 | (sctp_paramhdr_t *)addip_hdr->params, | 3544 | (sctp_paramhdr_t *)addip_hdr->params, |
3543 | (void *)asconf_ack->chunk_end, | 3545 | (void *)asconf_ack->chunk_end, |
3544 | &err_param)) | 3546 | &err_param)) |
3545 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3547 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
3546 | (void *)&err_param, commands); | 3548 | (void *)err_param, commands); |
3547 | 3549 | ||
3548 | if (last_asconf) { | 3550 | if (last_asconf) { |
3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; | 3551 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; |
@@ -4240,12 +4242,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
4240 | const struct sctp_endpoint *ep, | 4242 | const struct sctp_endpoint *ep, |
4241 | const struct sctp_association *asoc, | 4243 | const struct sctp_association *asoc, |
4242 | const sctp_subtype_t type, | 4244 | const sctp_subtype_t type, |
4243 | void *arg, | 4245 | void *arg, void *ext, |
4244 | sctp_cmd_seq_t *commands) { | 4246 | sctp_cmd_seq_t *commands) |
4245 | static const char err_str[] = "The following parameter had invalid length:"; | 4247 | { |
4248 | struct sctp_chunk *chunk = arg; | ||
4249 | struct sctp_paramhdr *param = ext; | ||
4250 | struct sctp_chunk *abort = NULL; | ||
4246 | 4251 | ||
4247 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4252 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
4248 | sizeof(err_str)); | 4253 | goto discard; |
4254 | |||
4255 | /* Make the abort chunk. */ | ||
4256 | abort = sctp_make_violation_paramlen(asoc, chunk, param); | ||
4257 | if (!abort) | ||
4258 | goto nomem; | ||
4259 | |||
4260 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4261 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | ||
4262 | |||
4263 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
4264 | SCTP_ERROR(ECONNABORTED)); | ||
4265 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
4266 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | ||
4267 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
4268 | |||
4269 | discard: | ||
4270 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
4271 | |||
4272 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
4273 | |||
4274 | return SCTP_DISPOSITION_ABORT; | ||
4275 | nomem: | ||
4276 | return SCTP_DISPOSITION_NOMEM; | ||
4249 | } | 4277 | } |
4250 | 4278 | ||
4251 | /* Handle a protocol violation when the peer trying to advance the | 4279 | /* Handle a protocol violation when the peer trying to advance the |
@@ -4517,13 +4545,6 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( | |||
4517 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4545 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4518 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); | 4546 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); |
4519 | 4547 | ||
4520 | /* sctpimpguide-05 Section 2.12.2 | ||
4521 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
4522 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
4523 | */ | ||
4524 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
4525 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
4526 | |||
4527 | disposition = SCTP_DISPOSITION_CONSUME; | 4548 | disposition = SCTP_DISPOSITION_CONSUME; |
4528 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 4549 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
4529 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 4550 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, |
@@ -4968,6 +4989,13 @@ sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | |||
4968 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 4989 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
4969 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); | 4990 | SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN)); |
4970 | 4991 | ||
4992 | /* RFC 4960 Section 9.2 | ||
4993 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
4994 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
4995 | */ | ||
4996 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
4997 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
4998 | |||
4971 | if (asoc->autoclose) | 4999 | if (asoc->autoclose) |
4972 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5000 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4973 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); | 5001 | SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); |
@@ -5279,6 +5307,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
5279 | if (!repl) | 5307 | if (!repl) |
5280 | return SCTP_DISPOSITION_NOMEM; | 5308 | return SCTP_DISPOSITION_NOMEM; |
5281 | 5309 | ||
5310 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
5311 | SCTP_CHUNK(repl)); | ||
5282 | /* Issue a sideeffect to do the needed accounting. */ | 5312 | /* Issue a sideeffect to do the needed accounting. */ |
5283 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, | 5313 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
5284 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 5314 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
@@ -5494,12 +5524,6 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
5494 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 5524 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
5495 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); | 5525 | SCTP_STATE(SCTP_STATE_SHUTDOWN_PENDING)); |
5496 | 5526 | ||
5497 | /* sctpimpguide-05 Section 2.12.2 | ||
5498 | * The sender of the SHUTDOWN MAY also start an overall guard timer | ||
5499 | * 'T5-shutdown-guard' to bound the overall time for shutdown sequence. | ||
5500 | */ | ||
5501 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | ||
5502 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | ||
5503 | disposition = SCTP_DISPOSITION_CONSUME; | 5527 | disposition = SCTP_DISPOSITION_CONSUME; |
5504 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 5528 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
5505 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 5529 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index d991237fb400..dd4ddc40c0ad 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -897,7 +897,7 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
897 | /* SCTP_STATE_ESTABLISHED */ \ | 897 | /* SCTP_STATE_ESTABLISHED */ \ |
898 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 898 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
899 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 899 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
900 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 900 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
901 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 901 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
902 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ | 902 | TYPE_SCTP_FUNC(sctp_sf_t5_timer_expire), \ |
903 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 903 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5ffb9dec1c3f..a1b904529d5e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2309,7 +2309,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk, | |||
2309 | /* If an address other than INADDR_ANY is specified, and | 2309 | /* If an address other than INADDR_ANY is specified, and |
2310 | * no transport is found, then the request is invalid. | 2310 | * no transport is found, then the request is invalid. |
2311 | */ | 2311 | */ |
2312 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 2312 | if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { |
2313 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 2313 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
2314 | params.spp_assoc_id); | 2314 | params.spp_assoc_id); |
2315 | if (!trans) | 2315 | if (!trans) |
@@ -4062,7 +4062,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, | |||
4062 | /* If an address other than INADDR_ANY is specified, and | 4062 | /* If an address other than INADDR_ANY is specified, and |
4063 | * no transport is found, then the request is invalid. | 4063 | * no transport is found, then the request is invalid. |
4064 | */ | 4064 | */ |
4065 | if (!sctp_is_any(( union sctp_addr *)¶ms.spp_address)) { | 4065 | if (!sctp_is_any(sk, ( union sctp_addr *)¶ms.spp_address)) { |
4066 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, | 4066 | trans = sctp_addr_id2transport(sk, ¶ms.spp_address, |
4067 | params.spp_assoc_id); | 4067 | params.spp_assoc_id); |
4068 | if (!trans) { | 4068 | if (!trans) { |
@@ -4414,7 +4414,7 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len, | |||
4414 | if (sctp_list_single_entry(&bp->address_list)) { | 4414 | if (sctp_list_single_entry(&bp->address_list)) { |
4415 | addr = list_entry(bp->address_list.next, | 4415 | addr = list_entry(bp->address_list.next, |
4416 | struct sctp_sockaddr_entry, list); | 4416 | struct sctp_sockaddr_entry, list); |
4417 | if (sctp_is_any(&addr->a)) { | 4417 | if (sctp_is_any(sk, &addr->a)) { |
4418 | rcu_read_lock(); | 4418 | rcu_read_lock(); |
4419 | list_for_each_entry_rcu(addr, | 4419 | list_for_each_entry_rcu(addr, |
4420 | &sctp_local_addr_list, list) { | 4420 | &sctp_local_addr_list, list) { |
@@ -4602,7 +4602,7 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, | |||
4602 | if (sctp_list_single_entry(&bp->address_list)) { | 4602 | if (sctp_list_single_entry(&bp->address_list)) { |
4603 | addr = list_entry(bp->address_list.next, | 4603 | addr = list_entry(bp->address_list.next, |
4604 | struct sctp_sockaddr_entry, list); | 4604 | struct sctp_sockaddr_entry, list); |
4605 | if (sctp_is_any(&addr->a)) { | 4605 | if (sctp_is_any(sk, &addr->a)) { |
4606 | cnt = sctp_copy_laddrs_old(sk, bp->port, | 4606 | cnt = sctp_copy_laddrs_old(sk, bp->port, |
4607 | getaddrs.addr_num, | 4607 | getaddrs.addr_num, |
4608 | addrs, &bytes_copied); | 4608 | addrs, &bytes_copied); |
@@ -4695,7 +4695,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
4695 | if (sctp_list_single_entry(&bp->address_list)) { | 4695 | if (sctp_list_single_entry(&bp->address_list)) { |
4696 | addr = list_entry(bp->address_list.next, | 4696 | addr = list_entry(bp->address_list.next, |
4697 | struct sctp_sockaddr_entry, list); | 4697 | struct sctp_sockaddr_entry, list); |
4698 | if (sctp_is_any(&addr->a)) { | 4698 | if (sctp_is_any(sk, &addr->a)) { |
4699 | cnt = sctp_copy_laddrs(sk, bp->port, addrs, | 4699 | cnt = sctp_copy_laddrs(sk, bp->port, addrs, |
4700 | space_left, &bytes_copied); | 4700 | space_left, &bytes_copied); |
4701 | if (cnt < 0) { | 4701 | if (cnt < 0) { |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 5061a26c5028..7b23803343cc 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -317,7 +317,7 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, | |||
317 | } | 317 | } |
318 | 318 | ||
319 | /* Insert before pos. */ | 319 | /* Insert before pos. */ |
320 | __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->reasm); | 320 | __skb_queue_before(&ulpq->reasm, pos, sctp_event2skb(event)); |
321 | 321 | ||
322 | } | 322 | } |
323 | 323 | ||
@@ -825,8 +825,7 @@ static void sctp_ulpq_store_ordered(struct sctp_ulpq *ulpq, | |||
825 | 825 | ||
826 | 826 | ||
827 | /* Insert before pos. */ | 827 | /* Insert before pos. */ |
828 | __skb_insert(sctp_event2skb(event), pos->prev, pos, &ulpq->lobby); | 828 | __skb_queue_before(&ulpq->lobby, pos, sctp_event2skb(event)); |
829 | |||
830 | } | 829 | } |
831 | 830 | ||
832 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, | 831 | static struct sctp_ulpevent *sctp_ulpq_order(struct sctp_ulpq *ulpq, |
diff --git a/net/socket.c b/net/socket.c index 8ef8ba81b9e2..3e8d4e35c08f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1511,6 +1511,7 @@ out_fd: | |||
1511 | goto out_put; | 1511 | goto out_put; |
1512 | } | 1512 | } |
1513 | 1513 | ||
1514 | #if 0 | ||
1514 | #ifdef HAVE_SET_RESTORE_SIGMASK | 1515 | #ifdef HAVE_SET_RESTORE_SIGMASK |
1515 | asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, | 1516 | asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, |
1516 | int __user *upeer_addrlen, | 1517 | int __user *upeer_addrlen, |
@@ -1564,6 +1565,7 @@ asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, | |||
1564 | return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); | 1565 | return do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); |
1565 | } | 1566 | } |
1566 | #endif | 1567 | #endif |
1568 | #endif | ||
1567 | 1569 | ||
1568 | asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, | 1570 | asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, |
1569 | int __user *upeer_addrlen) | 1571 | int __user *upeer_addrlen) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a910cd2d0fd1..5cadbeb76a14 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -29,113 +29,11 @@ MODULE_AUTHOR("Johannes Berg"); | |||
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | MODULE_DESCRIPTION("wireless configuration support"); | 30 | MODULE_DESCRIPTION("wireless configuration support"); |
31 | 31 | ||
32 | struct list_head regulatory_requests; | ||
33 | |||
34 | /* Central wireless core regulatory domains, we only need two, | ||
35 | * the current one and a world regulatory domain in case we have no | ||
36 | * information to give us an alpha2 */ | ||
37 | struct ieee80211_regdomain *cfg80211_regdomain; | ||
38 | |||
39 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
40 | const struct ieee80211_regdomain world_regdom = { | ||
41 | .n_reg_rules = 1, | ||
42 | .alpha2 = "00", | ||
43 | .reg_rules = { | ||
44 | REG_RULE(2402, 2472, 40, 6, 20, | ||
45 | NL80211_RRF_PASSIVE_SCAN | | ||
46 | NL80211_RRF_NO_IBSS), | ||
47 | } | ||
48 | }; | ||
49 | |||
50 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
51 | /* All this fucking static junk will be removed soon, so | ||
52 | * don't fucking count on it !@#$ */ | ||
53 | |||
54 | static char *ieee80211_regdom = "US"; | ||
55 | module_param(ieee80211_regdom, charp, 0444); | ||
56 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
57 | |||
58 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
59 | * We make emphasis we are using the exact same frequencies | ||
60 | * as before */ | ||
61 | |||
62 | const struct ieee80211_regdomain us_regdom = { | ||
63 | .n_reg_rules = 6, | ||
64 | .alpha2 = "US", | ||
65 | .reg_rules = { | ||
66 | /* IEEE 802.11b/g, channels 1..11 */ | ||
67 | REG_RULE(2412-20, 2462+20, 40, 6, 27, 0), | ||
68 | /* IEEE 802.11a, channel 36 */ | ||
69 | REG_RULE(5180-20, 5180+20, 40, 6, 23, 0), | ||
70 | /* IEEE 802.11a, channel 40 */ | ||
71 | REG_RULE(5200-20, 5200+20, 40, 6, 23, 0), | ||
72 | /* IEEE 802.11a, channel 44 */ | ||
73 | REG_RULE(5220-20, 5220+20, 40, 6, 23, 0), | ||
74 | /* IEEE 802.11a, channels 48..64 */ | ||
75 | REG_RULE(5240-20, 5320+20, 40, 6, 23, 0), | ||
76 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
77 | REG_RULE(5745-20, 5825+20, 40, 6, 30, 0), | ||
78 | } | ||
79 | }; | ||
80 | |||
81 | const struct ieee80211_regdomain jp_regdom = { | ||
82 | .n_reg_rules = 3, | ||
83 | .alpha2 = "JP", | ||
84 | .reg_rules = { | ||
85 | /* IEEE 802.11b/g, channels 1..14 */ | ||
86 | REG_RULE(2412-20, 2484+20, 40, 6, 20, 0), | ||
87 | /* IEEE 802.11a, channels 34..48 */ | ||
88 | REG_RULE(5170-20, 5240+20, 40, 6, 20, | ||
89 | NL80211_RRF_PASSIVE_SCAN), | ||
90 | /* IEEE 802.11a, channels 52..64 */ | ||
91 | REG_RULE(5260-20, 5320+20, 40, 6, 20, | ||
92 | NL80211_RRF_NO_IBSS | | ||
93 | NL80211_RRF_DFS), | ||
94 | } | ||
95 | }; | ||
96 | |||
97 | const struct ieee80211_regdomain eu_regdom = { | ||
98 | .n_reg_rules = 6, | ||
99 | /* This alpha2 is bogus, we leave it here just for stupid | ||
100 | * backward compatibility */ | ||
101 | .alpha2 = "EU", | ||
102 | .reg_rules = { | ||
103 | /* IEEE 802.11b/g, channels 1..13 */ | ||
104 | REG_RULE(2412-20, 2472+20, 40, 6, 20, 0), | ||
105 | /* IEEE 802.11a, channel 36 */ | ||
106 | REG_RULE(5180-20, 5180+20, 40, 6, 23, | ||
107 | NL80211_RRF_PASSIVE_SCAN), | ||
108 | /* IEEE 802.11a, channel 40 */ | ||
109 | REG_RULE(5200-20, 5200+20, 40, 6, 23, | ||
110 | NL80211_RRF_PASSIVE_SCAN), | ||
111 | /* IEEE 802.11a, channel 44 */ | ||
112 | REG_RULE(5220-20, 5220+20, 40, 6, 23, | ||
113 | NL80211_RRF_PASSIVE_SCAN), | ||
114 | /* IEEE 802.11a, channels 48..64 */ | ||
115 | REG_RULE(5240-20, 5320+20, 40, 6, 20, | ||
116 | NL80211_RRF_NO_IBSS | | ||
117 | NL80211_RRF_DFS), | ||
118 | /* IEEE 802.11a, channels 100..140 */ | ||
119 | REG_RULE(5500-20, 5700+20, 40, 6, 30, | ||
120 | NL80211_RRF_NO_IBSS | | ||
121 | NL80211_RRF_DFS), | ||
122 | } | ||
123 | }; | ||
124 | |||
125 | #endif | ||
126 | |||
127 | struct ieee80211_regdomain *cfg80211_world_regdom = | ||
128 | (struct ieee80211_regdomain *) &world_regdom; | ||
129 | |||
130 | LIST_HEAD(regulatory_requests); | ||
131 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
132 | |||
133 | /* RCU might be appropriate here since we usually | 32 | /* RCU might be appropriate here since we usually |
134 | * only read the list, and that can happen quite | 33 | * only read the list, and that can happen quite |
135 | * often because we need to do it for each command */ | 34 | * often because we need to do it for each command */ |
136 | LIST_HEAD(cfg80211_drv_list); | 35 | LIST_HEAD(cfg80211_drv_list); |
137 | DEFINE_MUTEX(cfg80211_drv_mutex); | 36 | DEFINE_MUTEX(cfg80211_drv_mutex); |
138 | static int wiphy_counter; | ||
139 | 37 | ||
140 | /* for debugfs */ | 38 | /* for debugfs */ |
141 | static struct dentry *ieee80211_debugfs_dir; | 39 | static struct dentry *ieee80211_debugfs_dir; |
@@ -307,6 +205,8 @@ out_unlock: | |||
307 | 205 | ||
308 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | 206 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) |
309 | { | 207 | { |
208 | static int wiphy_counter; | ||
209 | |||
310 | struct cfg80211_registered_device *drv; | 210 | struct cfg80211_registered_device *drv; |
311 | int alloc_size; | 211 | int alloc_size; |
312 | 212 | ||
@@ -323,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
323 | 223 | ||
324 | mutex_lock(&cfg80211_drv_mutex); | 224 | mutex_lock(&cfg80211_drv_mutex); |
325 | 225 | ||
326 | drv->idx = wiphy_counter; | 226 | drv->idx = wiphy_counter++; |
327 | |||
328 | /* now increase counter for the next device unless | ||
329 | * it has wrapped previously */ | ||
330 | if (wiphy_counter >= 0) | ||
331 | wiphy_counter++; | ||
332 | |||
333 | mutex_unlock(&cfg80211_drv_mutex); | ||
334 | 227 | ||
335 | if (unlikely(drv->idx < 0)) { | 228 | if (unlikely(drv->idx < 0)) { |
229 | wiphy_counter--; | ||
230 | mutex_unlock(&cfg80211_drv_mutex); | ||
336 | /* ugh, wrapped! */ | 231 | /* ugh, wrapped! */ |
337 | kfree(drv); | 232 | kfree(drv); |
338 | return NULL; | 233 | return NULL; |
339 | } | 234 | } |
340 | 235 | ||
236 | mutex_unlock(&cfg80211_drv_mutex); | ||
237 | |||
341 | /* give it a proper name */ | 238 | /* give it a proper name */ |
342 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, | 239 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, |
343 | PHY_NAME "%d", drv->idx); | 240 | PHY_NAME "%d", drv->idx); |
@@ -485,6 +382,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
485 | 382 | ||
486 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | 383 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); |
487 | 384 | ||
385 | WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); | ||
386 | |||
488 | switch (state) { | 387 | switch (state) { |
489 | case NETDEV_REGISTER: | 388 | case NETDEV_REGISTER: |
490 | mutex_lock(&rdev->devlist_mtx); | 389 | mutex_lock(&rdev->devlist_mtx); |
@@ -514,34 +413,10 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
514 | .notifier_call = cfg80211_netdev_notifier_call, | 413 | .notifier_call = cfg80211_netdev_notifier_call, |
515 | }; | 414 | }; |
516 | 415 | ||
517 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
518 | const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
519 | { | ||
520 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
521 | return &us_regdom; | ||
522 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
523 | return &jp_regdom; | ||
524 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
525 | return &eu_regdom; | ||
526 | /* Default, as per the old rules */ | ||
527 | return &us_regdom; | ||
528 | } | ||
529 | #endif | ||
530 | |||
531 | static int cfg80211_init(void) | 416 | static int cfg80211_init(void) |
532 | { | 417 | { |
533 | int err; | 418 | int err; |
534 | 419 | ||
535 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
536 | cfg80211_regdomain = | ||
537 | (struct ieee80211_regdomain *) static_regdom(ieee80211_regdom); | ||
538 | /* Used during reset_regdomains_static() */ | ||
539 | cfg80211_world_regdom = cfg80211_regdomain; | ||
540 | #else | ||
541 | cfg80211_regdomain = | ||
542 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
543 | #endif | ||
544 | |||
545 | err = wiphy_sysfs_init(); | 420 | err = wiphy_sysfs_init(); |
546 | if (err) | 421 | if (err) |
547 | goto out_fail_sysfs; | 422 | goto out_fail_sysfs; |
@@ -560,25 +435,6 @@ static int cfg80211_init(void) | |||
560 | if (err) | 435 | if (err) |
561 | goto out_fail_reg; | 436 | goto out_fail_reg; |
562 | 437 | ||
563 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
564 | printk(KERN_INFO "cfg80211: Using old static regulatory domain:\n"); | ||
565 | print_regdomain_info(cfg80211_regdomain); | ||
566 | /* The old code still requests for a new regdomain and if | ||
567 | * you have CRDA you get it updated, otherwise you get | ||
568 | * stuck with the static values. We ignore "EU" code as | ||
569 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
570 | if (ieee80211_regdom[0] != 'E' && | ||
571 | ieee80211_regdom[1] != 'U') | ||
572 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
573 | ieee80211_regdom, NULL); | ||
574 | #else | ||
575 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
576 | if (err) | ||
577 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
578 | "unable to update world regulatory domain, " | ||
579 | "using static definition\n"); | ||
580 | #endif | ||
581 | |||
582 | return 0; | 438 | return 0; |
583 | 439 | ||
584 | out_fail_reg: | 440 | out_fail_reg: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 1221d726ed50..572793c8c7ab 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -299,7 +299,7 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
299 | 299 | ||
300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); | 300 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); |
301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); | 301 | NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); |
302 | /* TODO: interface type */ | 302 | NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); |
303 | return genlmsg_end(msg, hdr); | 303 | return genlmsg_end(msg, hdr); |
304 | 304 | ||
305 | nla_put_failure: | 305 | nla_put_failure: |
@@ -418,41 +418,56 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
418 | int err, ifindex; | 418 | int err, ifindex; |
419 | enum nl80211_iftype type; | 419 | enum nl80211_iftype type; |
420 | struct net_device *dev; | 420 | struct net_device *dev; |
421 | u32 flags; | 421 | u32 _flags, *flags = NULL; |
422 | 422 | ||
423 | memset(¶ms, 0, sizeof(params)); | 423 | memset(¶ms, 0, sizeof(params)); |
424 | 424 | ||
425 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
426 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
427 | if (type > NL80211_IFTYPE_MAX) | ||
428 | return -EINVAL; | ||
429 | } else | ||
430 | return -EINVAL; | ||
431 | |||
432 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 425 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
433 | if (err) | 426 | if (err) |
434 | return err; | 427 | return err; |
435 | ifindex = dev->ifindex; | 428 | ifindex = dev->ifindex; |
429 | type = dev->ieee80211_ptr->iftype; | ||
436 | dev_put(dev); | 430 | dev_put(dev); |
437 | 431 | ||
432 | err = -EINVAL; | ||
433 | if (info->attrs[NL80211_ATTR_IFTYPE]) { | ||
434 | type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); | ||
435 | if (type > NL80211_IFTYPE_MAX) | ||
436 | goto unlock; | ||
437 | } | ||
438 | |||
438 | if (!drv->ops->change_virtual_intf || | 439 | if (!drv->ops->change_virtual_intf || |
439 | !(drv->wiphy.interface_modes & (1 << type))) { | 440 | !(drv->wiphy.interface_modes & (1 << type))) { |
440 | err = -EOPNOTSUPP; | 441 | err = -EOPNOTSUPP; |
441 | goto unlock; | 442 | goto unlock; |
442 | } | 443 | } |
443 | 444 | ||
444 | if (type == NL80211_IFTYPE_MESH_POINT && | 445 | if (info->attrs[NL80211_ATTR_MESH_ID]) { |
445 | info->attrs[NL80211_ATTR_MESH_ID]) { | 446 | if (type != NL80211_IFTYPE_MESH_POINT) { |
447 | err = -EINVAL; | ||
448 | goto unlock; | ||
449 | } | ||
446 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); | 450 | params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); |
447 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 451 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
448 | } | 452 | } |
449 | 453 | ||
454 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | ||
455 | if (type != NL80211_IFTYPE_MONITOR) { | ||
456 | err = -EINVAL; | ||
457 | goto unlock; | ||
458 | } | ||
459 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | ||
460 | &_flags); | ||
461 | if (!err) | ||
462 | flags = &_flags; | ||
463 | } | ||
450 | rtnl_lock(); | 464 | rtnl_lock(); |
451 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | ||
452 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | ||
453 | &flags); | ||
454 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 465 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
455 | type, err ? NULL : &flags, ¶ms); | 466 | type, flags, ¶ms); |
467 | |||
468 | dev = __dev_get_by_index(&init_net, ifindex); | ||
469 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | ||
470 | |||
456 | rtnl_unlock(); | 471 | rtnl_unlock(); |
457 | 472 | ||
458 | unlock: | 473 | unlock: |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 592b2e391d42..626dbb688499 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -42,6 +42,18 @@ | |||
42 | #include "core.h" | 42 | #include "core.h" |
43 | #include "reg.h" | 43 | #include "reg.h" |
44 | 44 | ||
45 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
46 | struct regulatory_request { | ||
47 | struct list_head list; | ||
48 | struct wiphy *wiphy; | ||
49 | int granted; | ||
50 | enum reg_set_by initiator; | ||
51 | char alpha2[2]; | ||
52 | }; | ||
53 | |||
54 | static LIST_HEAD(regulatory_requests); | ||
55 | DEFINE_MUTEX(cfg80211_reg_mutex); | ||
56 | |||
45 | /* To trigger userspace events */ | 57 | /* To trigger userspace events */ |
46 | static struct platform_device *reg_pdev; | 58 | static struct platform_device *reg_pdev; |
47 | 59 | ||
@@ -51,7 +63,156 @@ static u32 supported_bandwidths[] = { | |||
51 | MHZ_TO_KHZ(20), | 63 | MHZ_TO_KHZ(20), |
52 | }; | 64 | }; |
53 | 65 | ||
54 | bool is_world_regdom(char *alpha2) | 66 | static struct list_head regulatory_requests; |
67 | |||
68 | /* Central wireless core regulatory domains, we only need two, | ||
69 | * the current one and a world regulatory domain in case we have no | ||
70 | * information to give us an alpha2 */ | ||
71 | static const struct ieee80211_regdomain *cfg80211_regdomain; | ||
72 | |||
73 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | ||
74 | static const struct ieee80211_regdomain world_regdom = { | ||
75 | .n_reg_rules = 1, | ||
76 | .alpha2 = "00", | ||
77 | .reg_rules = { | ||
78 | REG_RULE(2412-10, 2462+10, 40, 6, 20, | ||
79 | NL80211_RRF_PASSIVE_SCAN | | ||
80 | NL80211_RRF_NO_IBSS), | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static const struct ieee80211_regdomain *cfg80211_world_regdom = | ||
85 | &world_regdom; | ||
86 | |||
87 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
88 | static char *ieee80211_regdom = "US"; | ||
89 | module_param(ieee80211_regdom, charp, 0444); | ||
90 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | ||
91 | |||
92 | /* We assume 40 MHz bandwidth for the old regulatory work. | ||
93 | * We make emphasis we are using the exact same frequencies | ||
94 | * as before */ | ||
95 | |||
96 | static const struct ieee80211_regdomain us_regdom = { | ||
97 | .n_reg_rules = 6, | ||
98 | .alpha2 = "US", | ||
99 | .reg_rules = { | ||
100 | /* IEEE 802.11b/g, channels 1..11 */ | ||
101 | REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), | ||
102 | /* IEEE 802.11a, channel 36 */ | ||
103 | REG_RULE(5180-10, 5180+10, 40, 6, 23, 0), | ||
104 | /* IEEE 802.11a, channel 40 */ | ||
105 | REG_RULE(5200-10, 5200+10, 40, 6, 23, 0), | ||
106 | /* IEEE 802.11a, channel 44 */ | ||
107 | REG_RULE(5220-10, 5220+10, 40, 6, 23, 0), | ||
108 | /* IEEE 802.11a, channels 48..64 */ | ||
109 | REG_RULE(5240-10, 5320+10, 40, 6, 23, 0), | ||
110 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
111 | REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | static const struct ieee80211_regdomain jp_regdom = { | ||
116 | .n_reg_rules = 3, | ||
117 | .alpha2 = "JP", | ||
118 | .reg_rules = { | ||
119 | /* IEEE 802.11b/g, channels 1..14 */ | ||
120 | REG_RULE(2412-10, 2484+10, 40, 6, 20, 0), | ||
121 | /* IEEE 802.11a, channels 34..48 */ | ||
122 | REG_RULE(5170-10, 5240+10, 40, 6, 20, | ||
123 | NL80211_RRF_PASSIVE_SCAN), | ||
124 | /* IEEE 802.11a, channels 52..64 */ | ||
125 | REG_RULE(5260-10, 5320+10, 40, 6, 20, | ||
126 | NL80211_RRF_NO_IBSS | | ||
127 | NL80211_RRF_DFS), | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | static const struct ieee80211_regdomain eu_regdom = { | ||
132 | .n_reg_rules = 6, | ||
133 | /* This alpha2 is bogus, we leave it here just for stupid | ||
134 | * backward compatibility */ | ||
135 | .alpha2 = "EU", | ||
136 | .reg_rules = { | ||
137 | /* IEEE 802.11b/g, channels 1..13 */ | ||
138 | REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), | ||
139 | /* IEEE 802.11a, channel 36 */ | ||
140 | REG_RULE(5180-10, 5180+10, 40, 6, 23, | ||
141 | NL80211_RRF_PASSIVE_SCAN), | ||
142 | /* IEEE 802.11a, channel 40 */ | ||
143 | REG_RULE(5200-10, 5200+10, 40, 6, 23, | ||
144 | NL80211_RRF_PASSIVE_SCAN), | ||
145 | /* IEEE 802.11a, channel 44 */ | ||
146 | REG_RULE(5220-10, 5220+10, 40, 6, 23, | ||
147 | NL80211_RRF_PASSIVE_SCAN), | ||
148 | /* IEEE 802.11a, channels 48..64 */ | ||
149 | REG_RULE(5240-10, 5320+10, 40, 6, 20, | ||
150 | NL80211_RRF_NO_IBSS | | ||
151 | NL80211_RRF_DFS), | ||
152 | /* IEEE 802.11a, channels 100..140 */ | ||
153 | REG_RULE(5500-10, 5700+10, 40, 6, 30, | ||
154 | NL80211_RRF_NO_IBSS | | ||
155 | NL80211_RRF_DFS), | ||
156 | } | ||
157 | }; | ||
158 | |||
159 | static const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
160 | { | ||
161 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
162 | return &us_regdom; | ||
163 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
164 | return &jp_regdom; | ||
165 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
166 | return &eu_regdom; | ||
167 | /* Default, as per the old rules */ | ||
168 | return &us_regdom; | ||
169 | } | ||
170 | |||
171 | static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
172 | { | ||
173 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
174 | return true; | ||
175 | return false; | ||
176 | } | ||
177 | #else | ||
178 | static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
179 | { | ||
180 | return false; | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | static void reset_regdomains(void) | ||
185 | { | ||
186 | /* avoid freeing static information or freeing something twice */ | ||
187 | if (cfg80211_regdomain == cfg80211_world_regdom) | ||
188 | cfg80211_regdomain = NULL; | ||
189 | if (cfg80211_world_regdom == &world_regdom) | ||
190 | cfg80211_world_regdom = NULL; | ||
191 | if (cfg80211_regdomain == &world_regdom) | ||
192 | cfg80211_regdomain = NULL; | ||
193 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
194 | cfg80211_regdomain = NULL; | ||
195 | |||
196 | kfree(cfg80211_regdomain); | ||
197 | kfree(cfg80211_world_regdom); | ||
198 | |||
199 | cfg80211_world_regdom = &world_regdom; | ||
200 | cfg80211_regdomain = NULL; | ||
201 | } | ||
202 | |||
203 | /* Dynamic world regulatory domain requested by the wireless | ||
204 | * core upon initialization */ | ||
205 | static void update_world_regdomain(const struct ieee80211_regdomain *rd) | ||
206 | { | ||
207 | BUG_ON(list_empty(®ulatory_requests)); | ||
208 | |||
209 | reset_regdomains(); | ||
210 | |||
211 | cfg80211_world_regdom = rd; | ||
212 | cfg80211_regdomain = rd; | ||
213 | } | ||
214 | |||
215 | bool is_world_regdom(const char *alpha2) | ||
55 | { | 216 | { |
56 | if (!alpha2) | 217 | if (!alpha2) |
57 | return false; | 218 | return false; |
@@ -60,7 +221,7 @@ bool is_world_regdom(char *alpha2) | |||
60 | return false; | 221 | return false; |
61 | } | 222 | } |
62 | 223 | ||
63 | static bool is_alpha2_set(char *alpha2) | 224 | static bool is_alpha2_set(const char *alpha2) |
64 | { | 225 | { |
65 | if (!alpha2) | 226 | if (!alpha2) |
66 | return false; | 227 | return false; |
@@ -77,7 +238,7 @@ static bool is_alpha_upper(char letter) | |||
77 | return false; | 238 | return false; |
78 | } | 239 | } |
79 | 240 | ||
80 | static bool is_unknown_alpha2(char *alpha2) | 241 | static bool is_unknown_alpha2(const char *alpha2) |
81 | { | 242 | { |
82 | if (!alpha2) | 243 | if (!alpha2) |
83 | return false; | 244 | return false; |
@@ -88,7 +249,7 @@ static bool is_unknown_alpha2(char *alpha2) | |||
88 | return false; | 249 | return false; |
89 | } | 250 | } |
90 | 251 | ||
91 | static bool is_an_alpha2(char *alpha2) | 252 | static bool is_an_alpha2(const char *alpha2) |
92 | { | 253 | { |
93 | if (!alpha2) | 254 | if (!alpha2) |
94 | return false; | 255 | return false; |
@@ -97,7 +258,7 @@ static bool is_an_alpha2(char *alpha2) | |||
97 | return false; | 258 | return false; |
98 | } | 259 | } |
99 | 260 | ||
100 | static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | 261 | static bool alpha2_equal(const char *alpha2_x, const char *alpha2_y) |
101 | { | 262 | { |
102 | if (!alpha2_x || !alpha2_y) | 263 | if (!alpha2_x || !alpha2_y) |
103 | return false; | 264 | return false; |
@@ -107,7 +268,7 @@ static bool alpha2_equal(char *alpha2_x, char *alpha2_y) | |||
107 | return false; | 268 | return false; |
108 | } | 269 | } |
109 | 270 | ||
110 | static bool regdom_changed(char *alpha2) | 271 | static bool regdom_changed(const char *alpha2) |
111 | { | 272 | { |
112 | if (!cfg80211_regdomain) | 273 | if (!cfg80211_regdomain) |
113 | return true; | 274 | return true; |
@@ -130,12 +291,8 @@ static int call_crda(const char *alpha2) | |||
130 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", | 291 | printk(KERN_INFO "cfg80211: Calling CRDA for country: %c%c\n", |
131 | alpha2[0], alpha2[1]); | 292 | alpha2[0], alpha2[1]); |
132 | else | 293 | else |
133 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
134 | return -EINVAL; | ||
135 | #else | ||
136 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " | 294 | printk(KERN_INFO "cfg80211: Calling CRDA to update world " |
137 | "regulatory domain\n"); | 295 | "regulatory domain\n"); |
138 | #endif | ||
139 | 296 | ||
140 | country_env[8] = alpha2[0]; | 297 | country_env[8] = alpha2[0]; |
141 | country_env[9] = alpha2[1]; | 298 | country_env[9] = alpha2[1]; |
@@ -238,7 +395,7 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
238 | } | 395 | } |
239 | } | 396 | } |
240 | 397 | ||
241 | static bool __reg_is_valid_request(char *alpha2, | 398 | static bool __reg_is_valid_request(const char *alpha2, |
242 | struct regulatory_request **request) | 399 | struct regulatory_request **request) |
243 | { | 400 | { |
244 | struct regulatory_request *req; | 401 | struct regulatory_request *req; |
@@ -254,16 +411,16 @@ static bool __reg_is_valid_request(char *alpha2, | |||
254 | } | 411 | } |
255 | 412 | ||
256 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ | 413 | /* Used by nl80211 before kmalloc'ing our regulatory domain */ |
257 | bool reg_is_valid_request(char *alpha2) | 414 | bool reg_is_valid_request(const char *alpha2) |
258 | { | 415 | { |
259 | struct regulatory_request *request = NULL; | 416 | struct regulatory_request *request = NULL; |
260 | return __reg_is_valid_request(alpha2, &request); | 417 | return __reg_is_valid_request(alpha2, &request); |
261 | } | 418 | } |
262 | 419 | ||
263 | /* Sanity check on a regulatory rule */ | 420 | /* Sanity check on a regulatory rule */ |
264 | static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | 421 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
265 | { | 422 | { |
266 | struct ieee80211_freq_range *freq_range = &rule->freq_range; | 423 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; |
267 | u32 freq_diff; | 424 | u32 freq_diff; |
268 | 425 | ||
269 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) | 426 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) |
@@ -280,9 +437,9 @@ static bool is_valid_reg_rule(struct ieee80211_reg_rule *rule) | |||
280 | return true; | 437 | return true; |
281 | } | 438 | } |
282 | 439 | ||
283 | static bool is_valid_rd(struct ieee80211_regdomain *rd) | 440 | static bool is_valid_rd(const struct ieee80211_regdomain *rd) |
284 | { | 441 | { |
285 | struct ieee80211_reg_rule *reg_rule = NULL; | 442 | const struct ieee80211_reg_rule *reg_rule = NULL; |
286 | unsigned int i; | 443 | unsigned int i; |
287 | 444 | ||
288 | if (!rd->n_reg_rules) | 445 | if (!rd->n_reg_rules) |
@@ -494,12 +651,12 @@ unlock_and_exit: | |||
494 | EXPORT_SYMBOL(regulatory_hint); | 651 | EXPORT_SYMBOL(regulatory_hint); |
495 | 652 | ||
496 | 653 | ||
497 | static void print_rd_rules(struct ieee80211_regdomain *rd) | 654 | static void print_rd_rules(const struct ieee80211_regdomain *rd) |
498 | { | 655 | { |
499 | unsigned int i; | 656 | unsigned int i; |
500 | struct ieee80211_reg_rule *reg_rule = NULL; | 657 | const struct ieee80211_reg_rule *reg_rule = NULL; |
501 | struct ieee80211_freq_range *freq_range = NULL; | 658 | const struct ieee80211_freq_range *freq_range = NULL; |
502 | struct ieee80211_power_rule *power_rule = NULL; | 659 | const struct ieee80211_power_rule *power_rule = NULL; |
503 | 660 | ||
504 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " | 661 | printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " |
505 | "(max_antenna_gain, max_eirp)\n"); | 662 | "(max_antenna_gain, max_eirp)\n"); |
@@ -529,7 +686,7 @@ static void print_rd_rules(struct ieee80211_regdomain *rd) | |||
529 | } | 686 | } |
530 | } | 687 | } |
531 | 688 | ||
532 | static void print_regdomain(struct ieee80211_regdomain *rd) | 689 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
533 | { | 690 | { |
534 | 691 | ||
535 | if (is_world_regdom(rd->alpha2)) | 692 | if (is_world_regdom(rd->alpha2)) |
@@ -548,85 +705,25 @@ static void print_regdomain(struct ieee80211_regdomain *rd) | |||
548 | print_rd_rules(rd); | 705 | print_rd_rules(rd); |
549 | } | 706 | } |
550 | 707 | ||
551 | void print_regdomain_info(struct ieee80211_regdomain *rd) | 708 | void print_regdomain_info(const struct ieee80211_regdomain *rd) |
552 | { | 709 | { |
553 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", | 710 | printk(KERN_INFO "cfg80211: Regulatory domain: %c%c\n", |
554 | rd->alpha2[0], rd->alpha2[1]); | 711 | rd->alpha2[0], rd->alpha2[1]); |
555 | print_rd_rules(rd); | 712 | print_rd_rules(rd); |
556 | } | 713 | } |
557 | 714 | ||
558 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 715 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
559 | |||
560 | static bool is_old_static_regdom(struct ieee80211_regdomain *rd) | ||
561 | { | ||
562 | if (rd == &us_regdom || rd == &jp_regdom || rd == &eu_regdom) | ||
563 | return true; | ||
564 | return false; | ||
565 | } | ||
566 | |||
567 | /* The old crap never deals with a world regulatory domain, it only | ||
568 | * deals with the static regulatory domain passed and if possible | ||
569 | * an updated "US" or "JP" regulatory domain. We do however store the | ||
570 | * old static regulatory domain in cfg80211_world_regdom for convenience | ||
571 | * of use here */ | ||
572 | static void reset_regdomains_static(void) | ||
573 | { | ||
574 | if (!is_old_static_regdom(cfg80211_regdomain)) | ||
575 | kfree(cfg80211_regdomain); | ||
576 | /* This is setting the regdom to the old static regdom */ | ||
577 | cfg80211_regdomain = | ||
578 | (struct ieee80211_regdomain *) cfg80211_world_regdom; | ||
579 | } | ||
580 | #else | ||
581 | static void reset_regdomains(void) | ||
582 | { | ||
583 | if (cfg80211_world_regdom && cfg80211_world_regdom != &world_regdom) { | ||
584 | if (cfg80211_world_regdom == cfg80211_regdomain) { | ||
585 | kfree(cfg80211_regdomain); | ||
586 | } else { | ||
587 | kfree(cfg80211_world_regdom); | ||
588 | kfree(cfg80211_regdomain); | ||
589 | } | ||
590 | } else if (cfg80211_regdomain && cfg80211_regdomain != &world_regdom) | ||
591 | kfree(cfg80211_regdomain); | ||
592 | |||
593 | cfg80211_world_regdom = (struct ieee80211_regdomain *) &world_regdom; | ||
594 | cfg80211_regdomain = NULL; | ||
595 | } | ||
596 | |||
597 | /* Dynamic world regulatory domain requested by the wireless | ||
598 | * core upon initialization */ | ||
599 | static void update_world_regdomain(struct ieee80211_regdomain *rd) | ||
600 | { | ||
601 | BUG_ON(list_empty(®ulatory_requests)); | ||
602 | |||
603 | reset_regdomains(); | ||
604 | |||
605 | cfg80211_world_regdom = rd; | ||
606 | cfg80211_regdomain = rd; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | static int __set_regdom(struct ieee80211_regdomain *rd) | ||
611 | { | 716 | { |
612 | struct regulatory_request *request = NULL; | 717 | struct regulatory_request *request = NULL; |
613 | 718 | ||
614 | /* Some basic sanity checks first */ | 719 | /* Some basic sanity checks first */ |
615 | 720 | ||
616 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
617 | /* We ignore the world regdom with the old static regdomains setup | ||
618 | * as there is no point to it with satic regulatory definitions :( | ||
619 | * Don't worry this shit will be removed soon... */ | ||
620 | if (is_world_regdom(rd->alpha2)) | ||
621 | return -EINVAL; | ||
622 | #else | ||
623 | if (is_world_regdom(rd->alpha2)) { | 721 | if (is_world_regdom(rd->alpha2)) { |
624 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 722 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
625 | return -EINVAL; | 723 | return -EINVAL; |
626 | update_world_regdomain(rd); | 724 | update_world_regdomain(rd); |
627 | return 0; | 725 | return 0; |
628 | } | 726 | } |
629 | #endif | ||
630 | 727 | ||
631 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && | 728 | if (!is_alpha2_set(rd->alpha2) && !is_an_alpha2(rd->alpha2) && |
632 | !is_unknown_alpha2(rd->alpha2)) | 729 | !is_unknown_alpha2(rd->alpha2)) |
@@ -635,15 +732,10 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
635 | if (list_empty(®ulatory_requests)) | 732 | if (list_empty(®ulatory_requests)) |
636 | return -EINVAL; | 733 | return -EINVAL; |
637 | 734 | ||
638 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 735 | /* allow overriding the static definitions if CRDA is present */ |
639 | /* Static "US" and "JP" will be overridden, but just once */ | ||
640 | if (!is_old_static_regdom(cfg80211_regdomain) && | 736 | if (!is_old_static_regdom(cfg80211_regdomain) && |
641 | !regdom_changed(rd->alpha2)) | 737 | !regdom_changed(rd->alpha2)) |
642 | return -EINVAL; | ||
643 | #else | ||
644 | if (!regdom_changed(rd->alpha2)) | ||
645 | return -EINVAL; | 738 | return -EINVAL; |
646 | #endif | ||
647 | 739 | ||
648 | /* Now lets set the regulatory domain, update all driver channels | 740 | /* Now lets set the regulatory domain, update all driver channels |
649 | * and finally inform them of what we have done, in case they want | 741 | * and finally inform them of what we have done, in case they want |
@@ -653,11 +745,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
653 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) | 745 | if (WARN_ON(!__reg_is_valid_request(rd->alpha2, &request))) |
654 | return -EINVAL; | 746 | return -EINVAL; |
655 | 747 | ||
656 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
657 | reset_regdomains_static(); | ||
658 | #else | ||
659 | reset_regdomains(); | 748 | reset_regdomains(); |
660 | #endif | ||
661 | 749 | ||
662 | /* Country IE parsing coming soon */ | 750 | /* Country IE parsing coming soon */ |
663 | switch (request->initiator) { | 751 | switch (request->initiator) { |
@@ -689,7 +777,7 @@ static int __set_regdom(struct ieee80211_regdomain *rd) | |||
689 | * multiple drivers can be ironed out later. Caller must've already | 777 | * multiple drivers can be ironed out later. Caller must've already |
690 | * kmalloc'd the rd structure. If this calls fails you should kfree() | 778 | * kmalloc'd the rd structure. If this calls fails you should kfree() |
691 | * the passed rd. Caller must hold cfg80211_drv_mutex */ | 779 | * the passed rd. Caller must hold cfg80211_drv_mutex */ |
692 | int set_regdom(struct ieee80211_regdomain *rd) | 780 | int set_regdom(const struct ieee80211_regdomain *rd) |
693 | { | 781 | { |
694 | struct regulatory_request *this_request = NULL, *prev_request = NULL; | 782 | struct regulatory_request *this_request = NULL, *prev_request = NULL; |
695 | int r; | 783 | int r; |
@@ -735,25 +823,50 @@ int set_regdom(struct ieee80211_regdomain *rd) | |||
735 | 823 | ||
736 | int regulatory_init(void) | 824 | int regulatory_init(void) |
737 | { | 825 | { |
826 | int err; | ||
827 | |||
738 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); | 828 | reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0); |
739 | if (IS_ERR(reg_pdev)) | 829 | if (IS_ERR(reg_pdev)) |
740 | return PTR_ERR(reg_pdev); | 830 | return PTR_ERR(reg_pdev); |
831 | |||
832 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
833 | cfg80211_regdomain = static_regdom(ieee80211_regdom); | ||
834 | |||
835 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | ||
836 | print_regdomain_info(cfg80211_regdomain); | ||
837 | /* The old code still requests for a new regdomain and if | ||
838 | * you have CRDA you get it updated, otherwise you get | ||
839 | * stuck with the static values. We ignore "EU" code as | ||
840 | * that is not a valid ISO / IEC 3166 alpha2 */ | ||
841 | if (ieee80211_regdom[0] != 'E' && ieee80211_regdom[1] != 'U') | ||
842 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | ||
843 | ieee80211_regdom, NULL); | ||
844 | #else | ||
845 | cfg80211_regdomain = cfg80211_world_regdom; | ||
846 | |||
847 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", NULL); | ||
848 | if (err) | ||
849 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | ||
850 | "unable to update world regulatory domain, " | ||
851 | "using static definition\n"); | ||
852 | #endif | ||
853 | |||
741 | return 0; | 854 | return 0; |
742 | } | 855 | } |
743 | 856 | ||
744 | void regulatory_exit(void) | 857 | void regulatory_exit(void) |
745 | { | 858 | { |
746 | struct regulatory_request *req, *req_tmp; | 859 | struct regulatory_request *req, *req_tmp; |
860 | |||
747 | mutex_lock(&cfg80211_drv_mutex); | 861 | mutex_lock(&cfg80211_drv_mutex); |
748 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 862 | |
749 | reset_regdomains_static(); | ||
750 | #else | ||
751 | reset_regdomains(); | 863 | reset_regdomains(); |
752 | #endif | 864 | |
753 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { | 865 | list_for_each_entry_safe(req, req_tmp, ®ulatory_requests, list) { |
754 | list_del(&req->list); | 866 | list_del(&req->list); |
755 | kfree(req); | 867 | kfree(req); |
756 | } | 868 | } |
757 | platform_device_unregister(reg_pdev); | 869 | platform_device_unregister(reg_pdev); |
870 | |||
758 | mutex_unlock(&cfg80211_drv_mutex); | 871 | mutex_unlock(&cfg80211_drv_mutex); |
759 | } | 872 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index d75fd0232972..a33362872f3c 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -1,44 +1,13 @@ | |||
1 | #ifndef __NET_WIRELESS_REG_H | 1 | #ifndef __NET_WIRELESS_REG_H |
2 | #define __NET_WIRELESS_REG_H | 2 | #define __NET_WIRELESS_REG_H |
3 | 3 | ||
4 | extern const struct ieee80211_regdomain world_regdom; | 4 | extern struct mutex cfg80211_reg_mutex; |
5 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | 5 | bool is_world_regdom(const char *alpha2); |
6 | extern const struct ieee80211_regdomain us_regdom; | 6 | bool reg_is_valid_request(const char *alpha2); |
7 | extern const struct ieee80211_regdomain jp_regdom; | ||
8 | extern const struct ieee80211_regdomain eu_regdom; | ||
9 | #endif | ||
10 | |||
11 | extern struct ieee80211_regdomain *cfg80211_regdomain; | ||
12 | extern struct ieee80211_regdomain *cfg80211_world_regdom; | ||
13 | extern struct list_head regulatory_requests; | ||
14 | |||
15 | struct regdom_last_setby { | ||
16 | struct wiphy *wiphy; | ||
17 | u8 initiator; | ||
18 | }; | ||
19 | |||
20 | /* wiphy is set if this request's initiator is REGDOM_SET_BY_DRIVER */ | ||
21 | struct regulatory_request { | ||
22 | struct list_head list; | ||
23 | struct wiphy *wiphy; | ||
24 | int granted; | ||
25 | enum reg_set_by initiator; | ||
26 | char alpha2[2]; | ||
27 | }; | ||
28 | |||
29 | bool is_world_regdom(char *alpha2); | ||
30 | bool reg_is_valid_request(char *alpha2); | ||
31 | |||
32 | int set_regdom(struct ieee80211_regdomain *rd); | ||
33 | int __regulatory_hint_alpha2(struct wiphy *wiphy, enum reg_set_by set_by, | ||
34 | const char *alpha2); | ||
35 | 7 | ||
36 | int regulatory_init(void); | 8 | int regulatory_init(void); |
37 | void regulatory_exit(void); | 9 | void regulatory_exit(void); |
38 | 10 | ||
39 | void print_regdomain_info(struct ieee80211_regdomain *); | 11 | int set_regdom(const struct ieee80211_regdomain *rd); |
40 | |||
41 | /* If a char is A-Z */ | ||
42 | #define IS_ALPHA(letter) (letter >= 65 && letter <= 90) | ||
43 | 12 | ||
44 | #endif /* __NET_WIRELESS_REG_H */ | 13 | #endif /* __NET_WIRELESS_REG_H */ |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e982..dc50f1e71f76 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) | |||
27 | - skb_headroom(skb); | 27 | - skb_headroom(skb); |
28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); | 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); |
29 | 29 | ||
30 | if (nhead > 0 || ntail > 0) | 30 | if (nhead <= 0) { |
31 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | 31 | if (ntail <= 0) |
32 | 32 | return 0; | |
33 | return 0; | 33 | nhead = 0; |
34 | } else if (ntail < 0) | ||
35 | ntail = 0; | ||
36 | |||
37 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | ||
34 | } | 38 | } |
35 | 39 | ||
36 | static int xfrm_output_one(struct sk_buff *skb, int err) | 40 | static int xfrm_output_one(struct sk_buff *skb, int err) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ef9ccbc38752..832b47c1de80 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(xfrm_cfg_mutex); | |||
46 | 46 | ||
47 | static DEFINE_RWLOCK(xfrm_policy_lock); | 47 | static DEFINE_RWLOCK(xfrm_policy_lock); |
48 | 48 | ||
49 | static struct list_head xfrm_policy_bytype[XFRM_POLICY_TYPE_MAX]; | 49 | static struct list_head xfrm_policy_all; |
50 | unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; | 50 | unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; |
51 | EXPORT_SYMBOL(xfrm_policy_count); | 51 | EXPORT_SYMBOL(xfrm_policy_count); |
52 | 52 | ||
@@ -164,7 +164,7 @@ static void xfrm_policy_timer(unsigned long data) | |||
164 | 164 | ||
165 | read_lock(&xp->lock); | 165 | read_lock(&xp->lock); |
166 | 166 | ||
167 | if (xp->dead) | 167 | if (xp->walk.dead) |
168 | goto out; | 168 | goto out; |
169 | 169 | ||
170 | dir = xfrm_policy_id2dir(xp->index); | 170 | dir = xfrm_policy_id2dir(xp->index); |
@@ -236,7 +236,7 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) | |||
236 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); | 236 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); |
237 | 237 | ||
238 | if (policy) { | 238 | if (policy) { |
239 | INIT_LIST_HEAD(&policy->bytype); | 239 | INIT_LIST_HEAD(&policy->walk.all); |
240 | INIT_HLIST_NODE(&policy->bydst); | 240 | INIT_HLIST_NODE(&policy->bydst); |
241 | INIT_HLIST_NODE(&policy->byidx); | 241 | INIT_HLIST_NODE(&policy->byidx); |
242 | rwlock_init(&policy->lock); | 242 | rwlock_init(&policy->lock); |
@@ -252,17 +252,13 @@ EXPORT_SYMBOL(xfrm_policy_alloc); | |||
252 | 252 | ||
253 | void xfrm_policy_destroy(struct xfrm_policy *policy) | 253 | void xfrm_policy_destroy(struct xfrm_policy *policy) |
254 | { | 254 | { |
255 | BUG_ON(!policy->dead); | 255 | BUG_ON(!policy->walk.dead); |
256 | 256 | ||
257 | BUG_ON(policy->bundles); | 257 | BUG_ON(policy->bundles); |
258 | 258 | ||
259 | if (del_timer(&policy->timer)) | 259 | if (del_timer(&policy->timer)) |
260 | BUG(); | 260 | BUG(); |
261 | 261 | ||
262 | write_lock_bh(&xfrm_policy_lock); | ||
263 | list_del(&policy->bytype); | ||
264 | write_unlock_bh(&xfrm_policy_lock); | ||
265 | |||
266 | security_xfrm_policy_free(policy->security); | 262 | security_xfrm_policy_free(policy->security); |
267 | kfree(policy); | 263 | kfree(policy); |
268 | } | 264 | } |
@@ -310,8 +306,8 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) | |||
310 | int dead; | 306 | int dead; |
311 | 307 | ||
312 | write_lock_bh(&policy->lock); | 308 | write_lock_bh(&policy->lock); |
313 | dead = policy->dead; | 309 | dead = policy->walk.dead; |
314 | policy->dead = 1; | 310 | policy->walk.dead = 1; |
315 | write_unlock_bh(&policy->lock); | 311 | write_unlock_bh(&policy->lock); |
316 | 312 | ||
317 | if (unlikely(dead)) { | 313 | if (unlikely(dead)) { |
@@ -609,6 +605,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
609 | if (delpol) { | 605 | if (delpol) { |
610 | hlist_del(&delpol->bydst); | 606 | hlist_del(&delpol->bydst); |
611 | hlist_del(&delpol->byidx); | 607 | hlist_del(&delpol->byidx); |
608 | list_del(&delpol->walk.all); | ||
612 | xfrm_policy_count[dir]--; | 609 | xfrm_policy_count[dir]--; |
613 | } | 610 | } |
614 | policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); | 611 | policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); |
@@ -617,7 +614,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
617 | policy->curlft.use_time = 0; | 614 | policy->curlft.use_time = 0; |
618 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 615 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
619 | xfrm_pol_hold(policy); | 616 | xfrm_pol_hold(policy); |
620 | list_add_tail(&policy->bytype, &xfrm_policy_bytype[policy->type]); | 617 | list_add(&policy->walk.all, &xfrm_policy_all); |
621 | write_unlock_bh(&xfrm_policy_lock); | 618 | write_unlock_bh(&xfrm_policy_lock); |
622 | 619 | ||
623 | if (delpol) | 620 | if (delpol) |
@@ -684,6 +681,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
684 | } | 681 | } |
685 | hlist_del(&pol->bydst); | 682 | hlist_del(&pol->bydst); |
686 | hlist_del(&pol->byidx); | 683 | hlist_del(&pol->byidx); |
684 | list_del(&pol->walk.all); | ||
687 | xfrm_policy_count[dir]--; | 685 | xfrm_policy_count[dir]--; |
688 | } | 686 | } |
689 | ret = pol; | 687 | ret = pol; |
@@ -727,6 +725,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
727 | } | 725 | } |
728 | hlist_del(&pol->bydst); | 726 | hlist_del(&pol->bydst); |
729 | hlist_del(&pol->byidx); | 727 | hlist_del(&pol->byidx); |
728 | list_del(&pol->walk.all); | ||
730 | xfrm_policy_count[dir]--; | 729 | xfrm_policy_count[dir]--; |
731 | } | 730 | } |
732 | ret = pol; | 731 | ret = pol; |
@@ -840,6 +839,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
840 | continue; | 839 | continue; |
841 | hlist_del(&pol->bydst); | 840 | hlist_del(&pol->bydst); |
842 | hlist_del(&pol->byidx); | 841 | hlist_del(&pol->byidx); |
842 | list_del(&pol->walk.all); | ||
843 | write_unlock_bh(&xfrm_policy_lock); | 843 | write_unlock_bh(&xfrm_policy_lock); |
844 | 844 | ||
845 | xfrm_audit_policy_delete(pol, 1, | 845 | xfrm_audit_policy_delete(pol, 1, |
@@ -867,60 +867,68 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk, | |||
867 | int (*func)(struct xfrm_policy *, int, int, void*), | 867 | int (*func)(struct xfrm_policy *, int, int, void*), |
868 | void *data) | 868 | void *data) |
869 | { | 869 | { |
870 | struct xfrm_policy *old, *pol, *last = NULL; | 870 | struct xfrm_policy *pol; |
871 | struct xfrm_policy_walk_entry *x; | ||
871 | int error = 0; | 872 | int error = 0; |
872 | 873 | ||
873 | if (walk->type >= XFRM_POLICY_TYPE_MAX && | 874 | if (walk->type >= XFRM_POLICY_TYPE_MAX && |
874 | walk->type != XFRM_POLICY_TYPE_ANY) | 875 | walk->type != XFRM_POLICY_TYPE_ANY) |
875 | return -EINVAL; | 876 | return -EINVAL; |
876 | 877 | ||
877 | if (walk->policy == NULL && walk->count != 0) | 878 | if (list_empty(&walk->walk.all) && walk->seq != 0) |
878 | return 0; | 879 | return 0; |
879 | 880 | ||
880 | old = pol = walk->policy; | 881 | write_lock_bh(&xfrm_policy_lock); |
881 | walk->policy = NULL; | 882 | if (list_empty(&walk->walk.all)) |
882 | read_lock_bh(&xfrm_policy_lock); | 883 | x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all); |
883 | 884 | else | |
884 | for (; walk->cur_type < XFRM_POLICY_TYPE_MAX; walk->cur_type++) { | 885 | x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); |
885 | if (walk->type != walk->cur_type && | 886 | list_for_each_entry_from(x, &xfrm_policy_all, all) { |
886 | walk->type != XFRM_POLICY_TYPE_ANY) | 887 | if (x->dead) |
887 | continue; | 888 | continue; |
888 | 889 | pol = container_of(x, struct xfrm_policy, walk); | |
889 | if (pol == NULL) { | 890 | if (walk->type != XFRM_POLICY_TYPE_ANY && |
890 | pol = list_first_entry(&xfrm_policy_bytype[walk->cur_type], | 891 | walk->type != pol->type) |
891 | struct xfrm_policy, bytype); | 892 | continue; |
892 | } | 893 | error = func(pol, xfrm_policy_id2dir(pol->index), |
893 | list_for_each_entry_from(pol, &xfrm_policy_bytype[walk->cur_type], bytype) { | 894 | walk->seq, data); |
894 | if (pol->dead) | 895 | if (error) { |
895 | continue; | 896 | list_move_tail(&walk->walk.all, &x->all); |
896 | if (last) { | 897 | goto out; |
897 | error = func(last, xfrm_policy_id2dir(last->index), | ||
898 | walk->count, data); | ||
899 | if (error) { | ||
900 | xfrm_pol_hold(last); | ||
901 | walk->policy = last; | ||
902 | goto out; | ||
903 | } | ||
904 | } | ||
905 | last = pol; | ||
906 | walk->count++; | ||
907 | } | 898 | } |
908 | pol = NULL; | 899 | walk->seq++; |
909 | } | 900 | } |
910 | if (walk->count == 0) { | 901 | if (walk->seq == 0) { |
911 | error = -ENOENT; | 902 | error = -ENOENT; |
912 | goto out; | 903 | goto out; |
913 | } | 904 | } |
914 | if (last) | 905 | list_del_init(&walk->walk.all); |
915 | error = func(last, xfrm_policy_id2dir(last->index), 0, data); | ||
916 | out: | 906 | out: |
917 | read_unlock_bh(&xfrm_policy_lock); | 907 | write_unlock_bh(&xfrm_policy_lock); |
918 | if (old != NULL) | ||
919 | xfrm_pol_put(old); | ||
920 | return error; | 908 | return error; |
921 | } | 909 | } |
922 | EXPORT_SYMBOL(xfrm_policy_walk); | 910 | EXPORT_SYMBOL(xfrm_policy_walk); |
923 | 911 | ||
912 | void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type) | ||
913 | { | ||
914 | INIT_LIST_HEAD(&walk->walk.all); | ||
915 | walk->walk.dead = 1; | ||
916 | walk->type = type; | ||
917 | walk->seq = 0; | ||
918 | } | ||
919 | EXPORT_SYMBOL(xfrm_policy_walk_init); | ||
920 | |||
921 | void xfrm_policy_walk_done(struct xfrm_policy_walk *walk) | ||
922 | { | ||
923 | if (list_empty(&walk->walk.all)) | ||
924 | return; | ||
925 | |||
926 | write_lock_bh(&xfrm_policy_lock); | ||
927 | list_del(&walk->walk.all); | ||
928 | write_unlock_bh(&xfrm_policy_lock); | ||
929 | } | ||
930 | EXPORT_SYMBOL(xfrm_policy_walk_done); | ||
931 | |||
924 | /* | 932 | /* |
925 | * Find policy to apply to this flow. | 933 | * Find policy to apply to this flow. |
926 | * | 934 | * |
@@ -1077,7 +1085,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | |||
1077 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, | 1085 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, |
1078 | pol->family, dir); | 1086 | pol->family, dir); |
1079 | 1087 | ||
1080 | list_add_tail(&pol->bytype, &xfrm_policy_bytype[pol->type]); | 1088 | list_add(&pol->walk.all, &xfrm_policy_all); |
1081 | hlist_add_head(&pol->bydst, chain); | 1089 | hlist_add_head(&pol->bydst, chain); |
1082 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); | 1090 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); |
1083 | xfrm_policy_count[dir]++; | 1091 | xfrm_policy_count[dir]++; |
@@ -1095,6 +1103,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | |||
1095 | 1103 | ||
1096 | hlist_del(&pol->bydst); | 1104 | hlist_del(&pol->bydst); |
1097 | hlist_del(&pol->byidx); | 1105 | hlist_del(&pol->byidx); |
1106 | list_del(&pol->walk.all); | ||
1098 | xfrm_policy_count[dir]--; | 1107 | xfrm_policy_count[dir]--; |
1099 | 1108 | ||
1100 | return pol; | 1109 | return pol; |
@@ -1720,7 +1729,7 @@ restart: | |||
1720 | 1729 | ||
1721 | for (pi = 0; pi < npols; pi++) { | 1730 | for (pi = 0; pi < npols; pi++) { |
1722 | read_lock_bh(&pols[pi]->lock); | 1731 | read_lock_bh(&pols[pi]->lock); |
1723 | pol_dead |= pols[pi]->dead; | 1732 | pol_dead |= pols[pi]->walk.dead; |
1724 | read_unlock_bh(&pols[pi]->lock); | 1733 | read_unlock_bh(&pols[pi]->lock); |
1725 | } | 1734 | } |
1726 | 1735 | ||
@@ -2415,9 +2424,7 @@ static void __init xfrm_policy_init(void) | |||
2415 | panic("XFRM: failed to allocate bydst hash\n"); | 2424 | panic("XFRM: failed to allocate bydst hash\n"); |
2416 | } | 2425 | } |
2417 | 2426 | ||
2418 | for (dir = 0; dir < XFRM_POLICY_TYPE_MAX; dir++) | 2427 | INIT_LIST_HEAD(&xfrm_policy_all); |
2419 | INIT_LIST_HEAD(&xfrm_policy_bytype[dir]); | ||
2420 | |||
2421 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); | 2428 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); |
2422 | register_netdevice_notifier(&xfrm_dev_notifier); | 2429 | register_netdevice_notifier(&xfrm_dev_notifier); |
2423 | } | 2430 | } |
@@ -2601,7 +2608,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol, | |||
2601 | int i, j, n = 0; | 2608 | int i, j, n = 0; |
2602 | 2609 | ||
2603 | write_lock_bh(&pol->lock); | 2610 | write_lock_bh(&pol->lock); |
2604 | if (unlikely(pol->dead)) { | 2611 | if (unlikely(pol->walk.dead)) { |
2605 | /* target policy has been deleted */ | 2612 | /* target policy has been deleted */ |
2606 | write_unlock_bh(&pol->lock); | 2613 | write_unlock_bh(&pol->lock); |
2607 | return -ENOENT; | 2614 | return -ENOENT; |
@@ -2672,7 +2679,8 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate) | |||
2672 | } | 2679 | } |
2673 | 2680 | ||
2674 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 2681 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
2675 | struct xfrm_migrate *m, int num_migrate) | 2682 | struct xfrm_migrate *m, int num_migrate, |
2683 | struct xfrm_kmaddress *k) | ||
2676 | { | 2684 | { |
2677 | int i, err, nx_cur = 0, nx_new = 0; | 2685 | int i, err, nx_cur = 0, nx_new = 0; |
2678 | struct xfrm_policy *pol = NULL; | 2686 | struct xfrm_policy *pol = NULL; |
@@ -2716,7 +2724,7 @@ int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
2716 | } | 2724 | } |
2717 | 2725 | ||
2718 | /* Stage 5 - announce */ | 2726 | /* Stage 5 - announce */ |
2719 | km_migrate(sel, dir, type, m, num_migrate); | 2727 | km_migrate(sel, dir, type, m, num_migrate, k); |
2720 | 2728 | ||
2721 | xfrm_pol_put(pol); | 2729 | xfrm_pol_put(pol); |
2722 | 2730 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index abbe2702c400..508337f97249 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -59,11 +59,6 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | |||
59 | static unsigned int xfrm_state_num; | 59 | static unsigned int xfrm_state_num; |
60 | static unsigned int xfrm_state_genid; | 60 | static unsigned int xfrm_state_genid; |
61 | 61 | ||
62 | /* Counter indicating ongoing walk, protected by xfrm_state_lock. */ | ||
63 | static unsigned long xfrm_state_walk_ongoing; | ||
64 | /* Counter indicating walk completion, protected by xfrm_cfg_mutex. */ | ||
65 | static unsigned long xfrm_state_walk_completed; | ||
66 | |||
67 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | 62 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); |
68 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); | 63 | static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); |
69 | 64 | ||
@@ -196,8 +191,7 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock); | |||
196 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; | 191 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; |
197 | 192 | ||
198 | static struct work_struct xfrm_state_gc_work; | 193 | static struct work_struct xfrm_state_gc_work; |
199 | static LIST_HEAD(xfrm_state_gc_leftovers); | 194 | static HLIST_HEAD(xfrm_state_gc_list); |
200 | static LIST_HEAD(xfrm_state_gc_list); | ||
201 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); | 195 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); |
202 | 196 | ||
203 | int __xfrm_state_delete(struct xfrm_state *x); | 197 | int __xfrm_state_delete(struct xfrm_state *x); |
@@ -409,23 +403,16 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
409 | 403 | ||
410 | static void xfrm_state_gc_task(struct work_struct *data) | 404 | static void xfrm_state_gc_task(struct work_struct *data) |
411 | { | 405 | { |
412 | struct xfrm_state *x, *tmp; | 406 | struct xfrm_state *x; |
413 | unsigned long completed; | 407 | struct hlist_node *entry, *tmp; |
408 | struct hlist_head gc_list; | ||
414 | 409 | ||
415 | mutex_lock(&xfrm_cfg_mutex); | ||
416 | spin_lock_bh(&xfrm_state_gc_lock); | 410 | spin_lock_bh(&xfrm_state_gc_lock); |
417 | list_splice_tail_init(&xfrm_state_gc_list, &xfrm_state_gc_leftovers); | 411 | hlist_move_list(&xfrm_state_gc_list, &gc_list); |
418 | spin_unlock_bh(&xfrm_state_gc_lock); | 412 | spin_unlock_bh(&xfrm_state_gc_lock); |
419 | 413 | ||
420 | completed = xfrm_state_walk_completed; | 414 | hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) |
421 | mutex_unlock(&xfrm_cfg_mutex); | ||
422 | |||
423 | list_for_each_entry_safe(x, tmp, &xfrm_state_gc_leftovers, gclist) { | ||
424 | if ((long)(x->lastused - completed) > 0) | ||
425 | break; | ||
426 | list_del(&x->gclist); | ||
427 | xfrm_state_gc_destroy(x); | 415 | xfrm_state_gc_destroy(x); |
428 | } | ||
429 | 416 | ||
430 | wake_up(&km_waitq); | 417 | wake_up(&km_waitq); |
431 | } | 418 | } |
@@ -526,7 +513,7 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
526 | if (x) { | 513 | if (x) { |
527 | atomic_set(&x->refcnt, 1); | 514 | atomic_set(&x->refcnt, 1); |
528 | atomic_set(&x->tunnel_users, 0); | 515 | atomic_set(&x->tunnel_users, 0); |
529 | INIT_LIST_HEAD(&x->all); | 516 | INIT_LIST_HEAD(&x->km.all); |
530 | INIT_HLIST_NODE(&x->bydst); | 517 | INIT_HLIST_NODE(&x->bydst); |
531 | INIT_HLIST_NODE(&x->bysrc); | 518 | INIT_HLIST_NODE(&x->bysrc); |
532 | INIT_HLIST_NODE(&x->byspi); | 519 | INIT_HLIST_NODE(&x->byspi); |
@@ -553,7 +540,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) | |||
553 | WARN_ON(x->km.state != XFRM_STATE_DEAD); | 540 | WARN_ON(x->km.state != XFRM_STATE_DEAD); |
554 | 541 | ||
555 | spin_lock_bh(&xfrm_state_gc_lock); | 542 | spin_lock_bh(&xfrm_state_gc_lock); |
556 | list_add_tail(&x->gclist, &xfrm_state_gc_list); | 543 | hlist_add_head(&x->gclist, &xfrm_state_gc_list); |
557 | spin_unlock_bh(&xfrm_state_gc_lock); | 544 | spin_unlock_bh(&xfrm_state_gc_lock); |
558 | schedule_work(&xfrm_state_gc_work); | 545 | schedule_work(&xfrm_state_gc_work); |
559 | } | 546 | } |
@@ -566,8 +553,7 @@ int __xfrm_state_delete(struct xfrm_state *x) | |||
566 | if (x->km.state != XFRM_STATE_DEAD) { | 553 | if (x->km.state != XFRM_STATE_DEAD) { |
567 | x->km.state = XFRM_STATE_DEAD; | 554 | x->km.state = XFRM_STATE_DEAD; |
568 | spin_lock(&xfrm_state_lock); | 555 | spin_lock(&xfrm_state_lock); |
569 | x->lastused = xfrm_state_walk_ongoing; | 556 | list_del(&x->km.all); |
570 | list_del_rcu(&x->all); | ||
571 | hlist_del(&x->bydst); | 557 | hlist_del(&x->bydst); |
572 | hlist_del(&x->bysrc); | 558 | hlist_del(&x->bysrc); |
573 | if (x->id.spi) | 559 | if (x->id.spi) |
@@ -868,7 +854,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
868 | 854 | ||
869 | if (km_query(x, tmpl, pol) == 0) { | 855 | if (km_query(x, tmpl, pol) == 0) { |
870 | x->km.state = XFRM_STATE_ACQ; | 856 | x->km.state = XFRM_STATE_ACQ; |
871 | list_add_tail(&x->all, &xfrm_state_all); | 857 | list_add(&x->km.all, &xfrm_state_all); |
872 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 858 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
873 | h = xfrm_src_hash(daddr, saddr, family); | 859 | h = xfrm_src_hash(daddr, saddr, family); |
874 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 860 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
@@ -937,7 +923,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
937 | 923 | ||
938 | x->genid = ++xfrm_state_genid; | 924 | x->genid = ++xfrm_state_genid; |
939 | 925 | ||
940 | list_add_tail(&x->all, &xfrm_state_all); | 926 | list_add(&x->km.all, &xfrm_state_all); |
941 | 927 | ||
942 | h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, | 928 | h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, |
943 | x->props.reqid, x->props.family); | 929 | x->props.reqid, x->props.family); |
@@ -1066,7 +1052,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
1066 | xfrm_state_hold(x); | 1052 | xfrm_state_hold(x); |
1067 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 1053 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; |
1068 | add_timer(&x->timer); | 1054 | add_timer(&x->timer); |
1069 | list_add_tail(&x->all, &xfrm_state_all); | 1055 | list_add(&x->km.all, &xfrm_state_all); |
1070 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 1056 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); |
1071 | h = xfrm_src_hash(daddr, saddr, family); | 1057 | h = xfrm_src_hash(daddr, saddr, family); |
1072 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 1058 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); |
@@ -1563,61 +1549,59 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, | |||
1563 | int (*func)(struct xfrm_state *, int, void*), | 1549 | int (*func)(struct xfrm_state *, int, void*), |
1564 | void *data) | 1550 | void *data) |
1565 | { | 1551 | { |
1566 | struct xfrm_state *old, *x, *last = NULL; | 1552 | struct xfrm_state *state; |
1553 | struct xfrm_state_walk *x; | ||
1567 | int err = 0; | 1554 | int err = 0; |
1568 | 1555 | ||
1569 | if (walk->state == NULL && walk->count != 0) | 1556 | if (walk->seq != 0 && list_empty(&walk->all)) |
1570 | return 0; | 1557 | return 0; |
1571 | 1558 | ||
1572 | old = x = walk->state; | ||
1573 | walk->state = NULL; | ||
1574 | spin_lock_bh(&xfrm_state_lock); | 1559 | spin_lock_bh(&xfrm_state_lock); |
1575 | if (x == NULL) | 1560 | if (list_empty(&walk->all)) |
1576 | x = list_first_entry(&xfrm_state_all, struct xfrm_state, all); | 1561 | x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all); |
1562 | else | ||
1563 | x = list_entry(&walk->all, struct xfrm_state_walk, all); | ||
1577 | list_for_each_entry_from(x, &xfrm_state_all, all) { | 1564 | list_for_each_entry_from(x, &xfrm_state_all, all) { |
1578 | if (x->km.state == XFRM_STATE_DEAD) | 1565 | if (x->state == XFRM_STATE_DEAD) |
1579 | continue; | 1566 | continue; |
1580 | if (!xfrm_id_proto_match(x->id.proto, walk->proto)) | 1567 | state = container_of(x, struct xfrm_state, km); |
1568 | if (!xfrm_id_proto_match(state->id.proto, walk->proto)) | ||
1581 | continue; | 1569 | continue; |
1582 | if (last) { | 1570 | err = func(state, walk->seq, data); |
1583 | err = func(last, walk->count, data); | 1571 | if (err) { |
1584 | if (err) { | 1572 | list_move_tail(&walk->all, &x->all); |
1585 | xfrm_state_hold(last); | 1573 | goto out; |
1586 | walk->state = last; | ||
1587 | xfrm_state_walk_ongoing++; | ||
1588 | goto out; | ||
1589 | } | ||
1590 | } | 1574 | } |
1591 | last = x; | 1575 | walk->seq++; |
1592 | walk->count++; | ||
1593 | } | 1576 | } |
1594 | if (walk->count == 0) { | 1577 | if (walk->seq == 0) { |
1595 | err = -ENOENT; | 1578 | err = -ENOENT; |
1596 | goto out; | 1579 | goto out; |
1597 | } | 1580 | } |
1598 | if (last) | 1581 | list_del_init(&walk->all); |
1599 | err = func(last, 0, data); | ||
1600 | out: | 1582 | out: |
1601 | spin_unlock_bh(&xfrm_state_lock); | 1583 | spin_unlock_bh(&xfrm_state_lock); |
1602 | if (old != NULL) { | ||
1603 | xfrm_state_put(old); | ||
1604 | xfrm_state_walk_completed++; | ||
1605 | if (!list_empty(&xfrm_state_gc_leftovers)) | ||
1606 | schedule_work(&xfrm_state_gc_work); | ||
1607 | } | ||
1608 | return err; | 1584 | return err; |
1609 | } | 1585 | } |
1610 | EXPORT_SYMBOL(xfrm_state_walk); | 1586 | EXPORT_SYMBOL(xfrm_state_walk); |
1611 | 1587 | ||
1588 | void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) | ||
1589 | { | ||
1590 | INIT_LIST_HEAD(&walk->all); | ||
1591 | walk->proto = proto; | ||
1592 | walk->state = XFRM_STATE_DEAD; | ||
1593 | walk->seq = 0; | ||
1594 | } | ||
1595 | EXPORT_SYMBOL(xfrm_state_walk_init); | ||
1596 | |||
1612 | void xfrm_state_walk_done(struct xfrm_state_walk *walk) | 1597 | void xfrm_state_walk_done(struct xfrm_state_walk *walk) |
1613 | { | 1598 | { |
1614 | if (walk->state != NULL) { | 1599 | if (list_empty(&walk->all)) |
1615 | xfrm_state_put(walk->state); | 1600 | return; |
1616 | walk->state = NULL; | 1601 | |
1617 | xfrm_state_walk_completed++; | 1602 | spin_lock_bh(&xfrm_state_lock); |
1618 | if (!list_empty(&xfrm_state_gc_leftovers)) | 1603 | list_del(&walk->all); |
1619 | schedule_work(&xfrm_state_gc_work); | 1604 | spin_lock_bh(&xfrm_state_lock); |
1620 | } | ||
1621 | } | 1605 | } |
1622 | EXPORT_SYMBOL(xfrm_state_walk_done); | 1606 | EXPORT_SYMBOL(xfrm_state_walk_done); |
1623 | 1607 | ||
@@ -1830,7 +1814,8 @@ EXPORT_SYMBOL(km_policy_expired); | |||
1830 | 1814 | ||
1831 | #ifdef CONFIG_XFRM_MIGRATE | 1815 | #ifdef CONFIG_XFRM_MIGRATE |
1832 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1816 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1833 | struct xfrm_migrate *m, int num_migrate) | 1817 | struct xfrm_migrate *m, int num_migrate, |
1818 | struct xfrm_kmaddress *k) | ||
1834 | { | 1819 | { |
1835 | int err = -EINVAL; | 1820 | int err = -EINVAL; |
1836 | int ret; | 1821 | int ret; |
@@ -1839,7 +1824,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1839 | read_lock(&xfrm_km_lock); | 1824 | read_lock(&xfrm_km_lock); |
1840 | list_for_each_entry(km, &xfrm_km_list, list) { | 1825 | list_for_each_entry(km, &xfrm_km_list, list) { |
1841 | if (km->migrate) { | 1826 | if (km->migrate) { |
1842 | ret = km->migrate(sel, dir, type, m, num_migrate); | 1827 | ret = km->migrate(sel, dir, type, m, num_migrate, k); |
1843 | if (!ret) | 1828 | if (!ret) |
1844 | err = ret; | 1829 | err = ret; |
1845 | } | 1830 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 04c41504f84c..4a8a1abb59ee 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1102,7 +1102,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, | |||
1102 | return xp; | 1102 | return xp; |
1103 | error: | 1103 | error: |
1104 | *errp = err; | 1104 | *errp = err; |
1105 | xp->dead = 1; | 1105 | xp->walk.dead = 1; |
1106 | xfrm_policy_destroy(xp); | 1106 | xfrm_policy_destroy(xp); |
1107 | return NULL; | 1107 | return NULL; |
1108 | } | 1108 | } |
@@ -1595,7 +1595,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1595 | return -ENOENT; | 1595 | return -ENOENT; |
1596 | 1596 | ||
1597 | read_lock(&xp->lock); | 1597 | read_lock(&xp->lock); |
1598 | if (xp->dead) { | 1598 | if (xp->walk.dead) { |
1599 | read_unlock(&xp->lock); | 1599 | read_unlock(&xp->lock); |
1600 | goto out; | 1600 | goto out; |
1601 | } | 1601 | } |
@@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1710 | 1710 | ||
1711 | #ifdef CONFIG_XFRM_MIGRATE | 1711 | #ifdef CONFIG_XFRM_MIGRATE |
1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, |
1713 | struct xfrm_kmaddress *k, | ||
1713 | struct nlattr **attrs, int *num) | 1714 | struct nlattr **attrs, int *num) |
1714 | { | 1715 | { |
1715 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; | 1716 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
1716 | struct xfrm_user_migrate *um; | 1717 | struct xfrm_user_migrate *um; |
1717 | int i, num_migrate; | 1718 | int i, num_migrate; |
1718 | 1719 | ||
1720 | if (k != NULL) { | ||
1721 | struct xfrm_user_kmaddress *uk; | ||
1722 | |||
1723 | uk = nla_data(attrs[XFRMA_KMADDRESS]); | ||
1724 | memcpy(&k->local, &uk->local, sizeof(k->local)); | ||
1725 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); | ||
1726 | k->family = uk->family; | ||
1727 | k->reserved = uk->reserved; | ||
1728 | } | ||
1729 | |||
1719 | um = nla_data(rt); | 1730 | um = nla_data(rt); |
1720 | num_migrate = nla_len(rt) / sizeof(*um); | 1731 | num_migrate = nla_len(rt) / sizeof(*um); |
1721 | 1732 | ||
@@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1745 | { | 1756 | { |
1746 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); | 1757 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
1747 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 1758 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
1759 | struct xfrm_kmaddress km, *kmp; | ||
1748 | u8 type; | 1760 | u8 type; |
1749 | int err; | 1761 | int err; |
1750 | int n = 0; | 1762 | int n = 0; |
@@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1752 | if (attrs[XFRMA_MIGRATE] == NULL) | 1764 | if (attrs[XFRMA_MIGRATE] == NULL) |
1753 | return -EINVAL; | 1765 | return -EINVAL; |
1754 | 1766 | ||
1767 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; | ||
1768 | |||
1755 | err = copy_from_user_policy_type(&type, attrs); | 1769 | err = copy_from_user_policy_type(&type, attrs); |
1756 | if (err) | 1770 | if (err) |
1757 | return err; | 1771 | return err; |
1758 | 1772 | ||
1759 | err = copy_from_user_migrate((struct xfrm_migrate *)m, | 1773 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
1760 | attrs, &n); | ||
1761 | if (err) | 1774 | if (err) |
1762 | return err; | 1775 | return err; |
1763 | 1776 | ||
1764 | if (!n) | 1777 | if (!n) |
1765 | return 0; | 1778 | return 0; |
1766 | 1779 | ||
1767 | xfrm_migrate(&pi->sel, pi->dir, type, m, n); | 1780 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
1768 | 1781 | ||
1769 | return 0; | 1782 | return 0; |
1770 | } | 1783 | } |
@@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | |||
1795 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 1808 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
1796 | } | 1809 | } |
1797 | 1810 | ||
1798 | static inline size_t xfrm_migrate_msgsize(int num_migrate) | 1811 | static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) |
1812 | { | ||
1813 | struct xfrm_user_kmaddress uk; | ||
1814 | |||
1815 | memset(&uk, 0, sizeof(uk)); | ||
1816 | uk.family = k->family; | ||
1817 | uk.reserved = k->reserved; | ||
1818 | memcpy(&uk.local, &k->local, sizeof(uk.local)); | ||
1819 | memcpy(&uk.remote, &k->local, sizeof(uk.remote)); | ||
1820 | |||
1821 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | ||
1822 | } | ||
1823 | |||
1824 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | ||
1799 | { | 1825 | { |
1800 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 1826 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
1801 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 1827 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
1802 | + userpolicy_type_attrsize(); | 1828 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
1829 | + userpolicy_type_attrsize(); | ||
1803 | } | 1830 | } |
1804 | 1831 | ||
1805 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | 1832 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, |
1806 | int num_migrate, struct xfrm_selector *sel, | 1833 | int num_migrate, struct xfrm_kmaddress *k, |
1807 | u8 dir, u8 type) | 1834 | struct xfrm_selector *sel, u8 dir, u8 type) |
1808 | { | 1835 | { |
1809 | struct xfrm_migrate *mp; | 1836 | struct xfrm_migrate *mp; |
1810 | struct xfrm_userpolicy_id *pol_id; | 1837 | struct xfrm_userpolicy_id *pol_id; |
@@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | |||
1821 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | 1848 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); |
1822 | pol_id->dir = dir; | 1849 | pol_id->dir = dir; |
1823 | 1850 | ||
1851 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) | ||
1852 | goto nlmsg_failure; | ||
1853 | |||
1824 | if (copy_to_user_policy_type(type, skb) < 0) | 1854 | if (copy_to_user_policy_type(type, skb) < 0) |
1825 | goto nlmsg_failure; | 1855 | goto nlmsg_failure; |
1826 | 1856 | ||
@@ -1836,23 +1866,25 @@ nlmsg_failure: | |||
1836 | } | 1866 | } |
1837 | 1867 | ||
1838 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1868 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1839 | struct xfrm_migrate *m, int num_migrate) | 1869 | struct xfrm_migrate *m, int num_migrate, |
1870 | struct xfrm_kmaddress *k) | ||
1840 | { | 1871 | { |
1841 | struct sk_buff *skb; | 1872 | struct sk_buff *skb; |
1842 | 1873 | ||
1843 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); | 1874 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
1844 | if (skb == NULL) | 1875 | if (skb == NULL) |
1845 | return -ENOMEM; | 1876 | return -ENOMEM; |
1846 | 1877 | ||
1847 | /* build migrate */ | 1878 | /* build migrate */ |
1848 | if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) | 1879 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
1849 | BUG(); | 1880 | BUG(); |
1850 | 1881 | ||
1851 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 1882 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
1852 | } | 1883 | } |
1853 | #else | 1884 | #else |
1854 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1885 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1855 | struct xfrm_migrate *m, int num_migrate) | 1886 | struct xfrm_migrate *m, int num_migrate, |
1887 | struct xfrm_kmaddress *k) | ||
1856 | { | 1888 | { |
1857 | return -ENOPROTOOPT; | 1889 | return -ENOPROTOOPT; |
1858 | } | 1890 | } |
@@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
1901 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, | 1933 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, |
1902 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 1934 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
1903 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 1935 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
1936 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | ||
1904 | }; | 1937 | }; |
1905 | 1938 | ||
1906 | static struct xfrm_link { | 1939 | static struct xfrm_link { |