diff options
author | Jiri Kosina <jkosina@suse.cz> | 2011-05-18 11:06:31 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-05-18 11:06:49 -0400 |
commit | 6b7b8e488bbdedeccabdd001a78ffcbe43bb8a3a (patch) | |
tree | f2f77cc31b4548745778fca6a51b09e1d8a49804 /net | |
parent | b50f315cbb865079a16a12fd9ae6083f98fd592c (diff) | |
parent | c1d10d18c542278b7fbc413c289d3cb6219da6b3 (diff) |
Merge branch 'master' into upstream.
This is sync with Linus' tree to receive KEY_IMAGES definition
that went in through input tree.
Diffstat (limited to 'net')
226 files changed, 2402 insertions, 1222 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 7850412f52b7..0eb1a886b370 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -124,6 +124,9 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
124 | 124 | ||
125 | grp->nr_vlans--; | 125 | grp->nr_vlans--; |
126 | 126 | ||
127 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
128 | vlan_gvrp_request_leave(dev); | ||
129 | |||
127 | vlan_group_set_device(grp, vlan_id, NULL); | 130 | vlan_group_set_device(grp, vlan_id, NULL); |
128 | if (!grp->killall) | 131 | if (!grp->killall) |
129 | synchronize_net(); | 132 | synchronize_net(); |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index ae610f046de5..b2ff6c8d3603 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -487,9 +487,6 @@ static int vlan_dev_stop(struct net_device *dev) | |||
487 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 487 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
488 | struct net_device *real_dev = vlan->real_dev; | 488 | struct net_device *real_dev = vlan->real_dev; |
489 | 489 | ||
490 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
491 | vlan_gvrp_request_leave(dev); | ||
492 | |||
493 | dev_mc_unsync(real_dev, dev); | 490 | dev_mc_unsync(real_dev, dev); |
494 | dev_uc_unsync(real_dev, dev); | 491 | dev_uc_unsync(real_dev, dev); |
495 | if (dev->flags & IFF_ALLMULTI) | 492 | if (dev->flags & IFF_ALLMULTI) |
@@ -720,6 +717,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
720 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; | 717 | dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid; |
721 | #endif | 718 | #endif |
722 | 719 | ||
720 | dev->needed_headroom = real_dev->needed_headroom; | ||
723 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { | 721 | if (real_dev->features & NETIF_F_HW_VLAN_TX) { |
724 | dev->header_ops = real_dev->header_ops; | 722 | dev->header_ops = real_dev->header_ops; |
725 | dev->hard_header_len = real_dev->hard_header_len; | 723 | dev->hard_header_len = real_dev->hard_header_len; |
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index d1314cf18adf..d940c49d168a 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -54,7 +54,7 @@ static const char name_conf[] = "config"; | |||
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Structures for interfacing with the /proc filesystem. | 56 | * Structures for interfacing with the /proc filesystem. |
57 | * VLAN creates its own directory /proc/net/vlan with the folowing | 57 | * VLAN creates its own directory /proc/net/vlan with the following |
58 | * entries: | 58 | * entries: |
59 | * config device status/configuration | 59 | * config device status/configuration |
60 | * <device> entry for each device | 60 | * <device> entry for each device |
diff --git a/net/9p/client.c b/net/9p/client.c index 347ec0cd2718..a9aa2dd66482 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -178,7 +178,7 @@ free_and_return: | |||
178 | * @tag: numeric id for transaction | 178 | * @tag: numeric id for transaction |
179 | * | 179 | * |
180 | * this is a simple array lookup, but will grow the | 180 | * this is a simple array lookup, but will grow the |
181 | * request_slots as necessary to accomodate transaction | 181 | * request_slots as necessary to accommodate transaction |
182 | * ids which did not previously have a slot. | 182 | * ids which did not previously have a slot. |
183 | * | 183 | * |
184 | * this code relies on the client spinlock to manage locks, its | 184 | * this code relies on the client spinlock to manage locks, its |
@@ -223,7 +223,7 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
223 | 223 | ||
224 | req = &c->reqs[row][col]; | 224 | req = &c->reqs[row][col]; |
225 | if (!req->tc) { | 225 | if (!req->tc) { |
226 | req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); | 226 | req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); |
227 | if (!req->wq) { | 227 | if (!req->wq) { |
228 | printk(KERN_ERR "Couldn't grow tag array\n"); | 228 | printk(KERN_ERR "Couldn't grow tag array\n"); |
229 | return ERR_PTR(-ENOMEM); | 229 | return ERR_PTR(-ENOMEM); |
@@ -233,17 +233,17 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
233 | P9_TRANS_PREF_PAYLOAD_SEP) { | 233 | P9_TRANS_PREF_PAYLOAD_SEP) { |
234 | int alloc_msize = min(c->msize, 4096); | 234 | int alloc_msize = min(c->msize, 4096); |
235 | req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, | 235 | req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, |
236 | GFP_KERNEL); | 236 | GFP_NOFS); |
237 | req->tc->capacity = alloc_msize; | 237 | req->tc->capacity = alloc_msize; |
238 | req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, | 238 | req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize, |
239 | GFP_KERNEL); | 239 | GFP_NOFS); |
240 | req->rc->capacity = alloc_msize; | 240 | req->rc->capacity = alloc_msize; |
241 | } else { | 241 | } else { |
242 | req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, | 242 | req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize, |
243 | GFP_KERNEL); | 243 | GFP_NOFS); |
244 | req->tc->capacity = c->msize; | 244 | req->tc->capacity = c->msize; |
245 | req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, | 245 | req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize, |
246 | GFP_KERNEL); | 246 | GFP_NOFS); |
247 | req->rc->capacity = c->msize; | 247 | req->rc->capacity = c->msize; |
248 | } | 248 | } |
249 | if ((!req->tc) || (!req->rc)) { | 249 | if ((!req->tc) || (!req->rc)) { |
@@ -614,7 +614,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
614 | 614 | ||
615 | err = c->trans_mod->request(c, req); | 615 | err = c->trans_mod->request(c, req); |
616 | if (err < 0) { | 616 | if (err < 0) { |
617 | if (err != -ERESTARTSYS) | 617 | if (err != -ERESTARTSYS && err != -EFAULT) |
618 | c->status = Disconnected; | 618 | c->status = Disconnected; |
619 | goto reterr; | 619 | goto reterr; |
620 | } | 620 | } |
@@ -929,15 +929,15 @@ error: | |||
929 | } | 929 | } |
930 | EXPORT_SYMBOL(p9_client_attach); | 930 | EXPORT_SYMBOL(p9_client_attach); |
931 | 931 | ||
932 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | 932 | struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, |
933 | int clone) | 933 | char **wnames, int clone) |
934 | { | 934 | { |
935 | int err; | 935 | int err; |
936 | struct p9_client *clnt; | 936 | struct p9_client *clnt; |
937 | struct p9_fid *fid; | 937 | struct p9_fid *fid; |
938 | struct p9_qid *wqids; | 938 | struct p9_qid *wqids; |
939 | struct p9_req_t *req; | 939 | struct p9_req_t *req; |
940 | int16_t nwqids, count; | 940 | uint16_t nwqids, count; |
941 | 941 | ||
942 | err = 0; | 942 | err = 0; |
943 | wqids = NULL; | 943 | wqids = NULL; |
@@ -955,7 +955,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
955 | fid = oldfid; | 955 | fid = oldfid; |
956 | 956 | ||
957 | 957 | ||
958 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n", | 958 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n", |
959 | oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); | 959 | oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); |
960 | 960 | ||
961 | req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, | 961 | req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, |
@@ -1220,27 +1220,6 @@ error: | |||
1220 | } | 1220 | } |
1221 | EXPORT_SYMBOL(p9_client_fsync); | 1221 | EXPORT_SYMBOL(p9_client_fsync); |
1222 | 1222 | ||
1223 | int p9_client_sync_fs(struct p9_fid *fid) | ||
1224 | { | ||
1225 | int err = 0; | ||
1226 | struct p9_req_t *req; | ||
1227 | struct p9_client *clnt; | ||
1228 | |||
1229 | P9_DPRINTK(P9_DEBUG_9P, ">>> TSYNC_FS fid %d\n", fid->fid); | ||
1230 | |||
1231 | clnt = fid->clnt; | ||
1232 | req = p9_client_rpc(clnt, P9_TSYNCFS, "d", fid->fid); | ||
1233 | if (IS_ERR(req)) { | ||
1234 | err = PTR_ERR(req); | ||
1235 | goto error; | ||
1236 | } | ||
1237 | P9_DPRINTK(P9_DEBUG_9P, "<<< RSYNCFS fid %d\n", fid->fid); | ||
1238 | p9_free_req(clnt, req); | ||
1239 | error: | ||
1240 | return err; | ||
1241 | } | ||
1242 | EXPORT_SYMBOL(p9_client_sync_fs); | ||
1243 | |||
1244 | int p9_client_clunk(struct p9_fid *fid) | 1223 | int p9_client_clunk(struct p9_fid *fid) |
1245 | { | 1224 | { |
1246 | int err; | 1225 | int err; |
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 2ce515b859b3..a873277cb996 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
@@ -205,7 +205,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
205 | if (errcode) | 205 | if (errcode) |
206 | break; | 206 | break; |
207 | 207 | ||
208 | *sptr = kmalloc(len + 1, GFP_KERNEL); | 208 | *sptr = kmalloc(len + 1, GFP_NOFS); |
209 | if (*sptr == NULL) { | 209 | if (*sptr == NULL) { |
210 | errcode = -EFAULT; | 210 | errcode = -EFAULT; |
211 | break; | 211 | break; |
@@ -265,7 +265,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
265 | } | 265 | } |
266 | break; | 266 | break; |
267 | case 'T':{ | 267 | case 'T':{ |
268 | int16_t *nwname = va_arg(ap, int16_t *); | 268 | uint16_t *nwname = va_arg(ap, uint16_t *); |
269 | char ***wnames = va_arg(ap, char ***); | 269 | char ***wnames = va_arg(ap, char ***); |
270 | 270 | ||
271 | errcode = p9pdu_readf(pdu, proto_version, | 271 | errcode = p9pdu_readf(pdu, proto_version, |
@@ -273,7 +273,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
273 | if (!errcode) { | 273 | if (!errcode) { |
274 | *wnames = | 274 | *wnames = |
275 | kmalloc(sizeof(char *) * *nwname, | 275 | kmalloc(sizeof(char *) * *nwname, |
276 | GFP_KERNEL); | 276 | GFP_NOFS); |
277 | if (!*wnames) | 277 | if (!*wnames) |
278 | errcode = -ENOMEM; | 278 | errcode = -ENOMEM; |
279 | } | 279 | } |
@@ -317,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
317 | *wqids = | 317 | *wqids = |
318 | kmalloc(*nwqid * | 318 | kmalloc(*nwqid * |
319 | sizeof(struct p9_qid), | 319 | sizeof(struct p9_qid), |
320 | GFP_KERNEL); | 320 | GFP_NOFS); |
321 | if (*wqids == NULL) | 321 | if (*wqids == NULL) |
322 | errcode = -ENOMEM; | 322 | errcode = -ENOMEM; |
323 | } | 323 | } |
@@ -468,7 +468,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
468 | case 'E':{ | 468 | case 'E':{ |
469 | int32_t cnt = va_arg(ap, int32_t); | 469 | int32_t cnt = va_arg(ap, int32_t); |
470 | const char *k = va_arg(ap, const void *); | 470 | const char *k = va_arg(ap, const void *); |
471 | const char *u = va_arg(ap, const void *); | 471 | const char __user *u = va_arg(ap, |
472 | const void __user *); | ||
472 | errcode = p9pdu_writef(pdu, proto_version, "d", | 473 | errcode = p9pdu_writef(pdu, proto_version, "d", |
473 | cnt); | 474 | cnt); |
474 | if (!errcode && pdu_write_urw(pdu, k, u, cnt)) | 475 | if (!errcode && pdu_write_urw(pdu, k, u, cnt)) |
@@ -495,7 +496,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, | |||
495 | } | 496 | } |
496 | break; | 497 | break; |
497 | case 'T':{ | 498 | case 'T':{ |
498 | int16_t nwname = va_arg(ap, int); | 499 | uint16_t nwname = va_arg(ap, int); |
499 | const char **wnames = va_arg(ap, const char **); | 500 | const char **wnames = va_arg(ap, const char **); |
500 | 501 | ||
501 | errcode = p9pdu_writef(pdu, proto_version, "w", | 502 | errcode = p9pdu_writef(pdu, proto_version, "w", |
@@ -673,6 +674,7 @@ int p9dirent_read(char *buf, int len, struct p9_dirent *dirent, | |||
673 | } | 674 | } |
674 | 675 | ||
675 | strcpy(dirent->d_name, nameptr); | 676 | strcpy(dirent->d_name, nameptr); |
677 | kfree(nameptr); | ||
676 | 678 | ||
677 | out: | 679 | out: |
678 | return fake_pdu.offset; | 680 | return fake_pdu.offset; |
diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index d62b9aa58df8..9a70ebdec56e 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c | |||
@@ -36,14 +36,14 @@ p9_release_req_pages(struct trans_rpage_info *rpinfo) | |||
36 | EXPORT_SYMBOL(p9_release_req_pages); | 36 | EXPORT_SYMBOL(p9_release_req_pages); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * p9_nr_pages - Return number of pages needed to accomodate the payload. | 39 | * p9_nr_pages - Return number of pages needed to accommodate the payload. |
40 | */ | 40 | */ |
41 | int | 41 | int |
42 | p9_nr_pages(struct p9_req_t *req) | 42 | p9_nr_pages(struct p9_req_t *req) |
43 | { | 43 | { |
44 | int start_page, end_page; | 44 | unsigned long start_page, end_page; |
45 | start_page = (unsigned long long)req->tc->pubuf >> PAGE_SHIFT; | 45 | start_page = (unsigned long)req->tc->pubuf >> PAGE_SHIFT; |
46 | end_page = ((unsigned long long)req->tc->pubuf + req->tc->pbuf_size + | 46 | end_page = ((unsigned long)req->tc->pubuf + req->tc->pbuf_size + |
47 | PAGE_SIZE - 1) >> PAGE_SHIFT; | 47 | PAGE_SIZE - 1) >> PAGE_SHIFT; |
48 | return end_page - start_page; | 48 | return end_page - start_page; |
49 | } | 49 | } |
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(p9_nr_pages); | |||
55 | * @req: Request to be sent to server. | 55 | * @req: Request to be sent to server. |
56 | * @pdata_off: data offset into the first page after translation (gup). | 56 | * @pdata_off: data offset into the first page after translation (gup). |
57 | * @pdata_len: Total length of the IO. gup may not return requested # of pages. | 57 | * @pdata_len: Total length of the IO. gup may not return requested # of pages. |
58 | * @nr_pages: number of pages to accomodate the payload | 58 | * @nr_pages: number of pages to accommodate the payload |
59 | * @rw: Indicates if the pages are for read or write. | 59 | * @rw: Indicates if the pages are for read or write. |
60 | */ | 60 | */ |
61 | int | 61 | int |
@@ -63,26 +63,21 @@ p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len, | |||
63 | int nr_pages, u8 rw) | 63 | int nr_pages, u8 rw) |
64 | { | 64 | { |
65 | uint32_t first_page_bytes = 0; | 65 | uint32_t first_page_bytes = 0; |
66 | uint32_t pdata_mapped_pages; | 66 | int32_t pdata_mapped_pages; |
67 | struct trans_rpage_info *rpinfo; | 67 | struct trans_rpage_info *rpinfo; |
68 | 68 | ||
69 | *pdata_off = (size_t)req->tc->pubuf & (PAGE_SIZE-1); | 69 | *pdata_off = (__force size_t)req->tc->pubuf & (PAGE_SIZE-1); |
70 | 70 | ||
71 | if (*pdata_off) | 71 | if (*pdata_off) |
72 | first_page_bytes = min((PAGE_SIZE - *pdata_off), | 72 | first_page_bytes = min(((size_t)PAGE_SIZE - *pdata_off), |
73 | req->tc->pbuf_size); | 73 | req->tc->pbuf_size); |
74 | 74 | ||
75 | rpinfo = req->tc->private; | 75 | rpinfo = req->tc->private; |
76 | pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf, | 76 | pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf, |
77 | nr_pages, rw, &rpinfo->rp_data[0]); | 77 | nr_pages, rw, &rpinfo->rp_data[0]); |
78 | if (pdata_mapped_pages <= 0) | ||
79 | return pdata_mapped_pages; | ||
78 | 80 | ||
79 | if (pdata_mapped_pages < 0) { | ||
80 | printk(KERN_ERR "get_user_pages_fast failed:%d udata:%p" | ||
81 | "nr_pages:%d\n", pdata_mapped_pages, | ||
82 | req->tc->pubuf, nr_pages); | ||
83 | pdata_mapped_pages = 0; | ||
84 | return -EIO; | ||
85 | } | ||
86 | rpinfo->rp_nr_pages = pdata_mapped_pages; | 81 | rpinfo->rp_nr_pages = pdata_mapped_pages; |
87 | if (*pdata_off) { | 82 | if (*pdata_off) { |
88 | *pdata_len = first_page_bytes; | 83 | *pdata_len = first_page_bytes; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a30471e51740..aa5672b15eae 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -350,7 +350,7 @@ static void p9_read_work(struct work_struct *work) | |||
350 | 350 | ||
351 | if (m->req->rc == NULL) { | 351 | if (m->req->rc == NULL) { |
352 | m->req->rc = kmalloc(sizeof(struct p9_fcall) + | 352 | m->req->rc = kmalloc(sizeof(struct p9_fcall) + |
353 | m->client->msize, GFP_KERNEL); | 353 | m->client->msize, GFP_NOFS); |
354 | if (!m->req->rc) { | 354 | if (!m->req->rc) { |
355 | m->req = NULL; | 355 | m->req = NULL; |
356 | err = -ENOMEM; | 356 | err = -ENOMEM; |
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 29a54ccd213d..150e0c4bbf40 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -424,7 +424,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
424 | struct p9_rdma_context *rpl_context = NULL; | 424 | struct p9_rdma_context *rpl_context = NULL; |
425 | 425 | ||
426 | /* Allocate an fcall for the reply */ | 426 | /* Allocate an fcall for the reply */ |
427 | rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL); | 427 | rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); |
428 | if (!rpl_context) { | 428 | if (!rpl_context) { |
429 | err = -ENOMEM; | 429 | err = -ENOMEM; |
430 | goto err_close; | 430 | goto err_close; |
@@ -437,7 +437,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
437 | */ | 437 | */ |
438 | if (!req->rc) { | 438 | if (!req->rc) { |
439 | req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize, | 439 | req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize, |
440 | GFP_KERNEL); | 440 | GFP_NOFS); |
441 | if (req->rc) { | 441 | if (req->rc) { |
442 | req->rc->sdata = (char *) req->rc + | 442 | req->rc->sdata = (char *) req->rc + |
443 | sizeof(struct p9_fcall); | 443 | sizeof(struct p9_fcall); |
@@ -468,7 +468,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) | |||
468 | req->rc = NULL; | 468 | req->rc = NULL; |
469 | 469 | ||
470 | /* Post the request */ | 470 | /* Post the request */ |
471 | c = kmalloc(sizeof *c, GFP_KERNEL); | 471 | c = kmalloc(sizeof *c, GFP_NOFS); |
472 | if (!c) { | 472 | if (!c) { |
473 | err = -ENOMEM; | 473 | err = -ENOMEM; |
474 | goto err_free1; | 474 | goto err_free1; |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 9b550ed9c711..244e70742183 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <net/9p/client.h> | 43 | #include <net/9p/client.h> |
44 | #include <net/9p/transport.h> | 44 | #include <net/9p/transport.h> |
45 | #include <linux/scatterlist.h> | 45 | #include <linux/scatterlist.h> |
46 | #include <linux/swap.h> | ||
46 | #include <linux/virtio.h> | 47 | #include <linux/virtio.h> |
47 | #include <linux/virtio_9p.h> | 48 | #include <linux/virtio_9p.h> |
48 | #include "trans_common.h" | 49 | #include "trans_common.h" |
@@ -51,6 +52,8 @@ | |||
51 | 52 | ||
52 | /* a single mutex to manage channel initialization and attachment */ | 53 | /* a single mutex to manage channel initialization and attachment */ |
53 | static DEFINE_MUTEX(virtio_9p_lock); | 54 | static DEFINE_MUTEX(virtio_9p_lock); |
55 | static DECLARE_WAIT_QUEUE_HEAD(vp_wq); | ||
56 | static atomic_t vp_pinned = ATOMIC_INIT(0); | ||
54 | 57 | ||
55 | /** | 58 | /** |
56 | * struct virtio_chan - per-instance transport information | 59 | * struct virtio_chan - per-instance transport information |
@@ -78,7 +81,10 @@ struct virtio_chan { | |||
78 | struct virtqueue *vq; | 81 | struct virtqueue *vq; |
79 | int ring_bufs_avail; | 82 | int ring_bufs_avail; |
80 | wait_queue_head_t *vc_wq; | 83 | wait_queue_head_t *vc_wq; |
81 | 84 | /* This is global limit. Since we don't have a global structure, | |
85 | * will be placing it in each channel. | ||
86 | */ | ||
87 | int p9_max_pages; | ||
82 | /* Scatterlist: can be too big for stack. */ | 88 | /* Scatterlist: can be too big for stack. */ |
83 | struct scatterlist sg[VIRTQUEUE_NUM]; | 89 | struct scatterlist sg[VIRTQUEUE_NUM]; |
84 | 90 | ||
@@ -141,34 +147,36 @@ static void req_done(struct virtqueue *vq) | |||
141 | 147 | ||
142 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); | 148 | P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n"); |
143 | 149 | ||
144 | do { | 150 | while (1) { |
145 | spin_lock_irqsave(&chan->lock, flags); | 151 | spin_lock_irqsave(&chan->lock, flags); |
146 | rc = virtqueue_get_buf(chan->vq, &len); | 152 | rc = virtqueue_get_buf(chan->vq, &len); |
147 | 153 | ||
148 | if (rc != NULL) { | 154 | if (rc == NULL) { |
149 | if (!chan->ring_bufs_avail) { | ||
150 | chan->ring_bufs_avail = 1; | ||
151 | wake_up(chan->vc_wq); | ||
152 | } | ||
153 | spin_unlock_irqrestore(&chan->lock, flags); | ||
154 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | ||
155 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", | ||
156 | rc->tag); | ||
157 | req = p9_tag_lookup(chan->client, rc->tag); | ||
158 | req->status = REQ_STATUS_RCVD; | ||
159 | if (req->tc->private) { | ||
160 | struct trans_rpage_info *rp = req->tc->private; | ||
161 | /*Release pages */ | ||
162 | p9_release_req_pages(rp); | ||
163 | if (rp->rp_alloc) | ||
164 | kfree(rp); | ||
165 | req->tc->private = NULL; | ||
166 | } | ||
167 | p9_client_cb(chan->client, req); | ||
168 | } else { | ||
169 | spin_unlock_irqrestore(&chan->lock, flags); | 155 | spin_unlock_irqrestore(&chan->lock, flags); |
156 | break; | ||
157 | } | ||
158 | |||
159 | chan->ring_bufs_avail = 1; | ||
160 | spin_unlock_irqrestore(&chan->lock, flags); | ||
161 | /* Wakeup if anyone waiting for VirtIO ring space. */ | ||
162 | wake_up(chan->vc_wq); | ||
163 | P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc); | ||
164 | P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | ||
165 | req = p9_tag_lookup(chan->client, rc->tag); | ||
166 | if (req->tc->private) { | ||
167 | struct trans_rpage_info *rp = req->tc->private; | ||
168 | int p = rp->rp_nr_pages; | ||
169 | /*Release pages */ | ||
170 | p9_release_req_pages(rp); | ||
171 | atomic_sub(p, &vp_pinned); | ||
172 | wake_up(&vp_wq); | ||
173 | if (rp->rp_alloc) | ||
174 | kfree(rp); | ||
175 | req->tc->private = NULL; | ||
170 | } | 176 | } |
171 | } while (rc != NULL); | 177 | req->status = REQ_STATUS_RCVD; |
178 | p9_client_cb(chan->client, req); | ||
179 | } | ||
172 | } | 180 | } |
173 | 181 | ||
174 | /** | 182 | /** |
@@ -263,7 +271,6 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
263 | 271 | ||
264 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); | 272 | P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n"); |
265 | 273 | ||
266 | req_retry: | ||
267 | req->status = REQ_STATUS_SENT; | 274 | req->status = REQ_STATUS_SENT; |
268 | 275 | ||
269 | if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) { | 276 | if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) { |
@@ -271,6 +278,14 @@ req_retry: | |||
271 | int rpinfo_size = sizeof(struct trans_rpage_info) + | 278 | int rpinfo_size = sizeof(struct trans_rpage_info) + |
272 | sizeof(struct page *) * nr_pages; | 279 | sizeof(struct page *) * nr_pages; |
273 | 280 | ||
281 | if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { | ||
282 | err = wait_event_interruptible(vp_wq, | ||
283 | atomic_read(&vp_pinned) < chan->p9_max_pages); | ||
284 | if (err == -ERESTARTSYS) | ||
285 | return err; | ||
286 | P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n"); | ||
287 | } | ||
288 | |||
274 | if (rpinfo_size <= (req->tc->capacity - req->tc->size)) { | 289 | if (rpinfo_size <= (req->tc->capacity - req->tc->size)) { |
275 | /* We can use sdata */ | 290 | /* We can use sdata */ |
276 | req->tc->private = req->tc->sdata + req->tc->size; | 291 | req->tc->private = req->tc->sdata + req->tc->size; |
@@ -293,9 +308,12 @@ req_retry: | |||
293 | if (rpinfo->rp_alloc) | 308 | if (rpinfo->rp_alloc) |
294 | kfree(rpinfo); | 309 | kfree(rpinfo); |
295 | return err; | 310 | return err; |
311 | } else { | ||
312 | atomic_add(rpinfo->rp_nr_pages, &vp_pinned); | ||
296 | } | 313 | } |
297 | } | 314 | } |
298 | 315 | ||
316 | req_retry_pinned: | ||
299 | spin_lock_irqsave(&chan->lock, flags); | 317 | spin_lock_irqsave(&chan->lock, flags); |
300 | 318 | ||
301 | /* Handle out VirtIO ring buffers */ | 319 | /* Handle out VirtIO ring buffers */ |
@@ -308,8 +326,11 @@ req_retry: | |||
308 | outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, | 326 | outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, |
309 | pdata_off, rpinfo->rp_data, pdata_len); | 327 | pdata_off, rpinfo->rp_data, pdata_len); |
310 | } else { | 328 | } else { |
311 | char *pbuf = req->tc->pubuf ? req->tc->pubuf : | 329 | char *pbuf; |
312 | req->tc->pkbuf; | 330 | if (req->tc->pubuf) |
331 | pbuf = (__force char *) req->tc->pubuf; | ||
332 | else | ||
333 | pbuf = req->tc->pkbuf; | ||
313 | outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf, | 334 | outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf, |
314 | req->tc->pbuf_size); | 335 | req->tc->pbuf_size); |
315 | } | 336 | } |
@@ -334,8 +355,12 @@ req_retry: | |||
334 | in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM, | 355 | in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM, |
335 | pdata_off, rpinfo->rp_data, pdata_len); | 356 | pdata_off, rpinfo->rp_data, pdata_len); |
336 | } else { | 357 | } else { |
337 | char *pbuf = req->tc->pubuf ? req->tc->pubuf : | 358 | char *pbuf; |
338 | req->tc->pkbuf; | 359 | if (req->tc->pubuf) |
360 | pbuf = (__force char *) req->tc->pubuf; | ||
361 | else | ||
362 | pbuf = req->tc->pkbuf; | ||
363 | |||
339 | in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM, | 364 | in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM, |
340 | pbuf, req->tc->pbuf_size); | 365 | pbuf, req->tc->pbuf_size); |
341 | } | 366 | } |
@@ -356,7 +381,7 @@ req_retry: | |||
356 | return err; | 381 | return err; |
357 | 382 | ||
358 | P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); | 383 | P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n"); |
359 | goto req_retry; | 384 | goto req_retry_pinned; |
360 | } else { | 385 | } else { |
361 | spin_unlock_irqrestore(&chan->lock, flags); | 386 | spin_unlock_irqrestore(&chan->lock, flags); |
362 | P9_DPRINTK(P9_DEBUG_TRANS, | 387 | P9_DPRINTK(P9_DEBUG_TRANS, |
@@ -453,6 +478,8 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
453 | } | 478 | } |
454 | init_waitqueue_head(chan->vc_wq); | 479 | init_waitqueue_head(chan->vc_wq); |
455 | chan->ring_bufs_avail = 1; | 480 | chan->ring_bufs_avail = 1; |
481 | /* Ceiling limit to avoid denial of service attacks */ | ||
482 | chan->p9_max_pages = nr_free_buffer_pages()/4; | ||
456 | 483 | ||
457 | mutex_lock(&virtio_9p_lock); | 484 | mutex_lock(&virtio_9p_lock); |
458 | list_add_tail(&chan->chan_list, &virtio_chan_list); | 485 | list_add_tail(&chan->chan_list, &virtio_chan_list); |
diff --git a/net/9p/util.c b/net/9p/util.c index e048701a72d2..da6af81e59d9 100644 --- a/net/9p/util.c +++ b/net/9p/util.c | |||
@@ -67,7 +67,7 @@ EXPORT_SYMBOL(p9_idpool_create); | |||
67 | 67 | ||
68 | /** | 68 | /** |
69 | * p9_idpool_destroy - create a new per-connection id pool | 69 | * p9_idpool_destroy - create a new per-connection id pool |
70 | * @p: idpool to destory | 70 | * @p: idpool to destroy |
71 | */ | 71 | */ |
72 | 72 | ||
73 | void p9_idpool_destroy(struct p9_idpool *p) | 73 | void p9_idpool_destroy(struct p9_idpool *p) |
@@ -92,7 +92,7 @@ int p9_idpool_get(struct p9_idpool *p) | |||
92 | unsigned long flags; | 92 | unsigned long flags; |
93 | 93 | ||
94 | retry: | 94 | retry: |
95 | if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) | 95 | if (idr_pre_get(&p->pool, GFP_NOFS) == 0) |
96 | return 0; | 96 | return 0; |
97 | 97 | ||
98 | spin_lock_irqsave(&p->lock, flags); | 98 | spin_lock_irqsave(&p->lock, flags); |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 3d4f4b043406..956a5302002a 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1051,13 +1051,17 @@ static int atalk_release(struct socket *sock) | |||
1051 | { | 1051 | { |
1052 | struct sock *sk = sock->sk; | 1052 | struct sock *sk = sock->sk; |
1053 | 1053 | ||
1054 | lock_sock(sk); | ||
1055 | if (sk) { | 1054 | if (sk) { |
1055 | sock_hold(sk); | ||
1056 | lock_sock(sk); | ||
1057 | |||
1056 | sock_orphan(sk); | 1058 | sock_orphan(sk); |
1057 | sock->sk = NULL; | 1059 | sock->sk = NULL; |
1058 | atalk_destroy_socket(sk); | 1060 | atalk_destroy_socket(sk); |
1061 | |||
1062 | release_sock(sk); | ||
1063 | sock_put(sk); | ||
1059 | } | 1064 | } |
1060 | release_sock(sk); | ||
1061 | return 0; | 1065 | return 0; |
1062 | } | 1066 | } |
1063 | 1067 | ||
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fce2eae8d476..2252c2085dac 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -509,7 +509,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
509 | write_lock_irq(&devs_lock); | 509 | write_lock_irq(&devs_lock); |
510 | net_dev = br2684_find_dev(&be.ifspec); | 510 | net_dev = br2684_find_dev(&be.ifspec); |
511 | if (net_dev == NULL) { | 511 | if (net_dev == NULL) { |
512 | pr_err("tried to attach to non-existant device\n"); | 512 | pr_err("tried to attach to non-existent device\n"); |
513 | err = -ENXIO; | 513 | err = -ENXIO; |
514 | goto error; | 514 | goto error; |
515 | } | 515 | } |
diff --git a/net/atm/common.c b/net/atm/common.c index 1b9c52a02cd3..22b963d06a10 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -252,6 +252,7 @@ void atm_dev_release_vccs(struct atm_dev *dev) | |||
252 | } | 252 | } |
253 | write_unlock_irq(&vcc_sklist_lock); | 253 | write_unlock_irq(&vcc_sklist_lock); |
254 | } | 254 | } |
255 | EXPORT_SYMBOL(atm_dev_release_vccs); | ||
255 | 256 | ||
256 | static int adjust_tp(struct atm_trafprm *tp, unsigned char aal) | 257 | static int adjust_tp(struct atm_trafprm *tp, unsigned char aal) |
257 | { | 258 | { |
diff --git a/net/atm/lec.h b/net/atm/lec.h index 9d14d196cc1d..dfc071966463 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h | |||
@@ -35,7 +35,7 @@ struct lecdatahdr_8025 { | |||
35 | * Operations that LANE2 capable device can do. Two first functions | 35 | * Operations that LANE2 capable device can do. Two first functions |
36 | * are used to make the device do things. See spec 3.1.3 and 3.1.4. | 36 | * are used to make the device do things. See spec 3.1.3 and 3.1.4. |
37 | * | 37 | * |
38 | * The third function is intented for the MPOA component sitting on | 38 | * The third function is intended for the MPOA component sitting on |
39 | * top of the LANE device. The MPOA component assigns it's own function | 39 | * top of the LANE device. The MPOA component assigns it's own function |
40 | * to (*associate_indicator)() and the LANE device will use that | 40 | * to (*associate_indicator)() and the LANE device will use that |
41 | * function to tell about TLVs it sees floating through. | 41 | * function to tell about TLVs it sees floating through. |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9ed26140a269..824e1f6e50f2 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -474,7 +474,7 @@ void interface_rx(struct net_device *soft_iface, | |||
474 | goto dropped; | 474 | goto dropped; |
475 | skb->protocol = eth_type_trans(skb, soft_iface); | 475 | skb->protocol = eth_type_trans(skb, soft_iface); |
476 | 476 | ||
477 | /* should not be neccesary anymore as we use skb_pull_rcsum() | 477 | /* should not be necessary anymore as we use skb_pull_rcsum() |
478 | * TODO: please verify this and remove this TODO | 478 | * TODO: please verify this and remove this TODO |
479 | * -- Dec 21st 2009, Simon Wunderlich */ | 479 | * -- Dec 21st 2009, Simon Wunderlich */ |
480 | 480 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b372fb8bcdcf..b5a8afc2be33 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -186,6 +186,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | |||
186 | BT_DBG("%s %ld", hdev->name, opt); | 186 | BT_DBG("%s %ld", hdev->name, opt); |
187 | 187 | ||
188 | /* Reset device */ | 188 | /* Reset device */ |
189 | set_bit(HCI_RESET, &hdev->flags); | ||
189 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); | 190 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); |
190 | } | 191 | } |
191 | 192 | ||
@@ -213,8 +214,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
213 | /* Mandatory initialization */ | 214 | /* Mandatory initialization */ |
214 | 215 | ||
215 | /* Reset */ | 216 | /* Reset */ |
216 | if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) | 217 | if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) { |
218 | set_bit(HCI_RESET, &hdev->flags); | ||
217 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); | 219 | hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); |
220 | } | ||
218 | 221 | ||
219 | /* Read Local Supported Features */ | 222 | /* Read Local Supported Features */ |
220 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 223 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
@@ -585,6 +588,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
585 | hci_req_lock(hdev); | 588 | hci_req_lock(hdev); |
586 | 589 | ||
587 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { | 590 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { |
591 | del_timer_sync(&hdev->cmd_timer); | ||
588 | hci_req_unlock(hdev); | 592 | hci_req_unlock(hdev); |
589 | return 0; | 593 | return 0; |
590 | } | 594 | } |
@@ -1074,6 +1078,7 @@ static void hci_cmd_timer(unsigned long arg) | |||
1074 | 1078 | ||
1075 | BT_ERR("%s command tx timeout", hdev->name); | 1079 | BT_ERR("%s command tx timeout", hdev->name); |
1076 | atomic_set(&hdev->cmd_cnt, 1); | 1080 | atomic_set(&hdev->cmd_cnt, 1); |
1081 | clear_bit(HCI_RESET, &hdev->flags); | ||
1077 | tasklet_schedule(&hdev->cmd_task); | 1082 | tasklet_schedule(&hdev->cmd_task); |
1078 | } | 1083 | } |
1079 | 1084 | ||
@@ -1877,7 +1882,7 @@ static void hci_tx_task(unsigned long arg) | |||
1877 | read_unlock(&hci_task_lock); | 1882 | read_unlock(&hci_task_lock); |
1878 | } | 1883 | } |
1879 | 1884 | ||
1880 | /* ----- HCI RX task (incoming data proccessing) ----- */ | 1885 | /* ----- HCI RX task (incoming data processing) ----- */ |
1881 | 1886 | ||
1882 | /* ACL data packet */ | 1887 | /* ACL data packet */ |
1883 | static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | 1888 | static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3fbfa50c2bff..b2570159a044 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -183,6 +183,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
183 | 183 | ||
184 | BT_DBG("%s status 0x%x", hdev->name, status); | 184 | BT_DBG("%s status 0x%x", hdev->name, status); |
185 | 185 | ||
186 | clear_bit(HCI_RESET, &hdev->flags); | ||
187 | |||
186 | hci_req_complete(hdev, HCI_OP_RESET, status); | 188 | hci_req_complete(hdev, HCI_OP_RESET, status); |
187 | } | 189 | } |
188 | 190 | ||
@@ -1847,7 +1849,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1847 | if (ev->opcode != HCI_OP_NOP) | 1849 | if (ev->opcode != HCI_OP_NOP) |
1848 | del_timer(&hdev->cmd_timer); | 1850 | del_timer(&hdev->cmd_timer); |
1849 | 1851 | ||
1850 | if (ev->ncmd) { | 1852 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
1851 | atomic_set(&hdev->cmd_cnt, 1); | 1853 | atomic_set(&hdev->cmd_cnt, 1); |
1852 | if (!skb_queue_empty(&hdev->cmd_q)) | 1854 | if (!skb_queue_empty(&hdev->cmd_q)) |
1853 | tasklet_schedule(&hdev->cmd_task); | 1855 | tasklet_schedule(&hdev->cmd_task); |
@@ -2385,8 +2387,6 @@ static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *s | |||
2385 | if (!conn) | 2387 | if (!conn) |
2386 | goto unlock; | 2388 | goto unlock; |
2387 | 2389 | ||
2388 | hci_conn_hold(conn); | ||
2389 | |||
2390 | conn->remote_cap = ev->capability; | 2390 | conn->remote_cap = ev->capability; |
2391 | conn->remote_oob = ev->oob_data; | 2391 | conn->remote_oob = ev->oob_data; |
2392 | conn->remote_auth = ev->authentication; | 2392 | conn->remote_auth = ev->authentication; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index c9f9cecca527..2c8dd4494c63 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1051,6 +1051,7 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq) | |||
1051 | tx_skb = skb_clone(skb, GFP_ATOMIC); | 1051 | tx_skb = skb_clone(skb, GFP_ATOMIC); |
1052 | bt_cb(skb)->retries++; | 1052 | bt_cb(skb)->retries++; |
1053 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); | 1053 | control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE); |
1054 | control &= L2CAP_CTRL_SAR; | ||
1054 | 1055 | ||
1055 | if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { | 1056 | if (pi->conn_state & L2CAP_CONN_SEND_FBIT) { |
1056 | control |= L2CAP_CTRL_FINAL; | 1057 | control |= L2CAP_CTRL_FINAL; |
@@ -1116,7 +1117,9 @@ int l2cap_ertm_send(struct sock *sk) | |||
1116 | bt_cb(skb)->tx_seq = pi->next_tx_seq; | 1117 | bt_cb(skb)->tx_seq = pi->next_tx_seq; |
1117 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; | 1118 | pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; |
1118 | 1119 | ||
1119 | pi->unacked_frames++; | 1120 | if (bt_cb(skb)->retries == 1) |
1121 | pi->unacked_frames++; | ||
1122 | |||
1120 | pi->frames_sent++; | 1123 | pi->frames_sent++; |
1121 | 1124 | ||
1122 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) | 1125 | if (skb_queue_is_last(TX_QUEUE(sk), skb)) |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index fc85e7ae33c7..299fe56a9668 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -679,7 +679,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
679 | 679 | ||
680 | if (opt == BT_FLUSHABLE_OFF) { | 680 | if (opt == BT_FLUSHABLE_OFF) { |
681 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; | 681 | struct l2cap_conn *conn = l2cap_pi(sk)->conn; |
682 | /* proceed futher only when we have l2cap_conn and | 682 | /* proceed further only when we have l2cap_conn and |
683 | No Flush support in the LM */ | 683 | No Flush support in the LM */ |
684 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { | 684 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { |
685 | err = -EINVAL; | 685 | err = -EINVAL; |
@@ -923,8 +923,9 @@ void __l2cap_sock_close(struct sock *sk, int reason) | |||
923 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); | 923 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
924 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, | 924 | l2cap_send_cmd(conn, l2cap_pi(sk)->ident, |
925 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 925 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
926 | } else | 926 | } |
927 | l2cap_chan_del(sk, reason); | 927 | |
928 | l2cap_chan_del(sk, reason); | ||
928 | break; | 929 | break; |
929 | 930 | ||
930 | case BT_CONNECT: | 931 | case BT_CONNECT: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0054c74e27b7..4476d8e3c0f2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1230,6 +1230,8 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1230 | if (!hdev) | 1230 | if (!hdev) |
1231 | return cmd_status(sk, index, mgmt_op, ENODEV); | 1231 | return cmd_status(sk, index, mgmt_op, ENODEV); |
1232 | 1232 | ||
1233 | hci_dev_lock_bh(hdev); | ||
1234 | |||
1233 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1235 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1234 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); | 1236 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); |
1235 | goto failed; | 1237 | goto failed; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 88485cc74dc3..cc4d3c5ab1c6 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -169,7 +169,7 @@ void br_fdb_flush(struct net_bridge *br) | |||
169 | spin_unlock_bh(&br->hash_lock); | 169 | spin_unlock_bh(&br->hash_lock); |
170 | } | 170 | } |
171 | 171 | ||
172 | /* Flush all entries refering to a specific port. | 172 | /* Flush all entries referring to a specific port. |
173 | * if do_all is set also flush static entries | 173 | * if do_all is set also flush static entries |
174 | */ | 174 | */ |
175 | void br_fdb_delete_by_port(struct net_bridge *br, | 175 | void br_fdb_delete_by_port(struct net_bridge *br, |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index dce8f0009a12..718b60366dfe 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
389 | { | 389 | { |
390 | struct net_bridge_port *p; | 390 | struct net_bridge_port *p; |
391 | int err = 0; | 391 | int err = 0; |
392 | bool changed_addr; | ||
392 | 393 | ||
393 | /* Don't allow bridging non-ethernet like devices */ | 394 | /* Don't allow bridging non-ethernet like devices */ |
394 | if ((dev->flags & IFF_LOOPBACK) || | 395 | if ((dev->flags & IFF_LOOPBACK) || |
@@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
446 | list_add_rcu(&p->list, &br->port_list); | 447 | list_add_rcu(&p->list, &br->port_list); |
447 | 448 | ||
448 | spin_lock_bh(&br->lock); | 449 | spin_lock_bh(&br->lock); |
449 | br_stp_recalculate_bridge_id(br); | 450 | changed_addr = br_stp_recalculate_bridge_id(br); |
450 | br_features_recompute(br); | 451 | br_features_recompute(br); |
451 | 452 | ||
452 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
@@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
456 | 457 | ||
457 | br_ifinfo_notify(RTM_NEWLINK, p); | 458 | br_ifinfo_notify(RTM_NEWLINK, p); |
458 | 459 | ||
460 | if (changed_addr) | ||
461 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
462 | |||
459 | dev_set_mtu(br->dev, br_min_mtu(br)); | 463 | dev_set_mtu(br->dev, br_min_mtu(br)); |
460 | 464 | ||
461 | kobject_uevent(&p->kobj, KOBJ_ADD); | 465 | kobject_uevent(&p->kobj, KOBJ_ADD); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e2160792e1bc..0c7badad62af 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -164,7 +164,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) | |||
164 | goto drop; | 164 | goto drop; |
165 | 165 | ||
166 | /* If STP is turned off, then forward */ | 166 | /* If STP is turned off, then forward */ |
167 | if (p->br->stp_enabled == BR_NO_STP) | 167 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) |
168 | goto forward; | 168 | goto forward; |
169 | 169 | ||
170 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 170 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index cb43312b846e..3d9fca0e3370 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -106,7 +106,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | |||
106 | /* | 106 | /* |
107 | * Legacy ioctl's through SIOCDEVPRIVATE | 107 | * Legacy ioctl's through SIOCDEVPRIVATE |
108 | * This interface is deprecated because it was too difficult to | 108 | * This interface is deprecated because it was too difficult to |
109 | * to do the translation for 32/64bit ioctl compatability. | 109 | * to do the translation for 32/64bit ioctl compatibility. |
110 | */ | 110 | */ |
111 | static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 111 | static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
112 | { | 112 | { |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 030a002ff8ee..59660c909a7c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -445,9 +445,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
445 | ip6h->payload_len = htons(8 + sizeof(*mldq)); | 445 | ip6h->payload_len = htons(8 + sizeof(*mldq)); |
446 | ip6h->nexthdr = IPPROTO_HOPOPTS; | 446 | ip6h->nexthdr = IPPROTO_HOPOPTS; |
447 | ip6h->hop_limit = 1; | 447 | ip6h->hop_limit = 1; |
448 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | ||
448 | ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, | 449 | ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, |
449 | &ip6h->saddr); | 450 | &ip6h->saddr); |
450 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | ||
451 | ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); | 451 | ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); |
452 | 452 | ||
453 | hopopt = (u8 *)(ip6h + 1); | 453 | hopopt = (u8 *)(ip6h + 1); |
@@ -1475,7 +1475,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1475 | ip6h->payload_len == 0) | 1475 | ip6h->payload_len == 0) |
1476 | return 0; | 1476 | return 0; |
1477 | 1477 | ||
1478 | len = ntohs(ip6h->payload_len); | 1478 | len = ntohs(ip6h->payload_len) + sizeof(*ip6h); |
1479 | if (skb->len < len) | 1479 | if (skb->len < len) |
1480 | return -EINVAL; | 1480 | return -EINVAL; |
1481 | 1481 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index f97af5590ba1..74ef4d4846a4 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -249,11 +249,9 @@ static int br_parse_ip_options(struct sk_buff *skb) | |||
249 | goto drop; | 249 | goto drop; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Zero out the CB buffer if no options present */ | 252 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
253 | if (iph->ihl == 5) { | 253 | if (iph->ihl == 5) |
254 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | ||
255 | return 0; | 254 | return 0; |
256 | } | ||
257 | 255 | ||
258 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); | 256 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); |
259 | if (ip_options_compile(dev_net(dev), opt, skb)) | 257 | if (ip_options_compile(dev_net(dev), opt, skb)) |
@@ -739,6 +737,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
739 | nf_bridge->mask |= BRNF_PKT_TYPE; | 737 | nf_bridge->mask |= BRNF_PKT_TYPE; |
740 | } | 738 | } |
741 | 739 | ||
740 | if (pf == PF_INET && br_parse_ip_options(skb)) | ||
741 | return NF_DROP; | ||
742 | |||
742 | /* The physdev module checks on this */ | 743 | /* The physdev module checks on this */ |
743 | nf_bridge->mask |= BRNF_BRIDGED; | 744 | nf_bridge->mask |= BRNF_BRIDGED; |
744 | nf_bridge->physoutdev = skb->dev; | 745 | nf_bridge->physoutdev = skb->dev; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 19e2f46ed086..387013d33745 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); | |||
497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); | 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); |
498 | extern void br_stp_enable_port(struct net_bridge_port *p); | 498 | extern void br_stp_enable_port(struct net_bridge_port *p); |
499 | extern void br_stp_disable_port(struct net_bridge_port *p); | 499 | extern void br_stp_disable_port(struct net_bridge_port *p); |
500 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); | 500 | extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); |
501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); |
502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
503 | u16 newprio); | 503 | u16 newprio); |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 79372d4a4055..9b61d09de9b9 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; |
205 | 205 | ||
206 | /* called under bridge lock */ | 206 | /* called under bridge lock */ |
207 | void br_stp_recalculate_bridge_id(struct net_bridge *br) | 207 | bool br_stp_recalculate_bridge_id(struct net_bridge *br) |
208 | { | 208 | { |
209 | const unsigned char *br_mac_zero = | 209 | const unsigned char *br_mac_zero = |
210 | (const unsigned char *)br_mac_zero_aligned; | 210 | (const unsigned char *)br_mac_zero_aligned; |
@@ -213,7 +213,7 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
213 | 213 | ||
214 | /* user has chosen a value so keep it */ | 214 | /* user has chosen a value so keep it */ |
215 | if (br->flags & BR_SET_MAC_ADDR) | 215 | if (br->flags & BR_SET_MAC_ADDR) |
216 | return; | 216 | return false; |
217 | 217 | ||
218 | list_for_each_entry(p, &br->port_list, list) { | 218 | list_for_each_entry(p, &br->port_list, list) { |
219 | if (addr == br_mac_zero || | 219 | if (addr == br_mac_zero || |
@@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
222 | 222 | ||
223 | } | 223 | } |
224 | 224 | ||
225 | if (compare_ether_addr(br->bridge_id.addr, addr)) | 225 | if (compare_ether_addr(br->bridge_id.addr, addr) == 0) |
226 | br_stp_change_bridge_id(br, addr); | 226 | return false; /* no change */ |
227 | |||
228 | br_stp_change_bridge_id(br, addr); | ||
229 | return true; | ||
227 | } | 230 | } |
228 | 231 | ||
229 | /* called under bridge lock */ | 232 | /* called under bridge lock */ |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 893669caa8de..1a92b369c820 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info, | |||
1766 | 1766 | ||
1767 | newinfo->entries_size = size; | 1767 | newinfo->entries_size = size; |
1768 | 1768 | ||
1769 | xt_compat_init_offsets(AF_INET, info->nentries); | 1769 | xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); |
1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, | 1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
1771 | entries, newinfo); | 1771 | entries, newinfo); |
1772 | } | 1772 | } |
@@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1882 | struct xt_match *match; | 1882 | struct xt_match *match; |
1883 | struct xt_target *wt; | 1883 | struct xt_target *wt; |
1884 | void *dst = NULL; | 1884 | void *dst = NULL; |
1885 | int off, pad = 0, ret = 0; | 1885 | int off, pad = 0; |
1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; | 1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; |
1887 | 1887 | ||
1888 | strlcpy(name, mwt->u.name, sizeof(name)); | 1888 | strlcpy(name, mwt->u.name, sizeof(name)); |
@@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1935 | break; | 1935 | break; |
1936 | } | 1936 | } |
1937 | 1937 | ||
1938 | if (!dst) { | ||
1939 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, | ||
1940 | off + ebt_compat_entry_padsize()); | ||
1941 | if (ret < 0) | ||
1942 | return ret; | ||
1943 | } | ||
1944 | |||
1945 | state->buf_kern_offset += match_size + off; | 1938 | state->buf_kern_offset += match_size + off; |
1946 | state->buf_user_offset += match_size; | 1939 | state->buf_user_offset += match_size; |
1947 | pad = XT_ALIGN(size_kern) - size_kern; | 1940 | pad = XT_ALIGN(size_kern) - size_kern; |
@@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, | |||
2016 | return growth; | 2009 | return growth; |
2017 | } | 2010 | } |
2018 | 2011 | ||
2019 | #define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ | ||
2020 | ({ \ | ||
2021 | unsigned int __i; \ | ||
2022 | int __ret = 0; \ | ||
2023 | struct compat_ebt_entry_mwt *__watcher; \ | ||
2024 | \ | ||
2025 | for (__i = e->watchers_offset; \ | ||
2026 | __i < (e)->target_offset; \ | ||
2027 | __i += __watcher->watcher_size + \ | ||
2028 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
2029 | __watcher = (void *)(e) + __i; \ | ||
2030 | __ret = fn(__watcher , ## args); \ | ||
2031 | if (__ret != 0) \ | ||
2032 | break; \ | ||
2033 | } \ | ||
2034 | if (__ret == 0) { \ | ||
2035 | if (__i != (e)->target_offset) \ | ||
2036 | __ret = -EINVAL; \ | ||
2037 | } \ | ||
2038 | __ret; \ | ||
2039 | }) | ||
2040 | |||
2041 | #define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ | ||
2042 | ({ \ | ||
2043 | unsigned int __i; \ | ||
2044 | int __ret = 0; \ | ||
2045 | struct compat_ebt_entry_mwt *__match; \ | ||
2046 | \ | ||
2047 | for (__i = sizeof(struct ebt_entry); \ | ||
2048 | __i < (e)->watchers_offset; \ | ||
2049 | __i += __match->match_size + \ | ||
2050 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
2051 | __match = (void *)(e) + __i; \ | ||
2052 | __ret = fn(__match , ## args); \ | ||
2053 | if (__ret != 0) \ | ||
2054 | break; \ | ||
2055 | } \ | ||
2056 | if (__ret == 0) { \ | ||
2057 | if (__i != (e)->watchers_offset) \ | ||
2058 | __ret = -EINVAL; \ | ||
2059 | } \ | ||
2060 | __ret; \ | ||
2061 | }) | ||
2062 | |||
2063 | /* called for all ebt_entry structures. */ | 2012 | /* called for all ebt_entry structures. */ |
2064 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | 2013 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, |
2065 | unsigned int *total, | 2014 | unsigned int *total, |
@@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
2132 | } | 2081 | } |
2133 | } | 2082 | } |
2134 | 2083 | ||
2084 | if (state->buf_kern_start == NULL) { | ||
2085 | unsigned int offset = buf_start - (char *) base; | ||
2086 | |||
2087 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset); | ||
2088 | if (ret < 0) | ||
2089 | return ret; | ||
2090 | } | ||
2091 | |||
2135 | startoff = state->buf_user_offset - startoff; | 2092 | startoff = state->buf_user_offset - startoff; |
2136 | 2093 | ||
2137 | BUG_ON(*total < startoff); | 2094 | BUG_ON(*total < startoff); |
@@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
2240 | 2197 | ||
2241 | xt_compat_lock(NFPROTO_BRIDGE); | 2198 | xt_compat_lock(NFPROTO_BRIDGE); |
2242 | 2199 | ||
2200 | xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | ||
2243 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2201 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
2244 | if (ret < 0) | 2202 | if (ret < 0) |
2245 | goto out_unlock; | 2203 | goto out_unlock; |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 8184c031d028..37a4034dfc29 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -852,7 +852,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
852 | sock->state = SS_CONNECTING; | 852 | sock->state = SS_CONNECTING; |
853 | sk->sk_state = CAIF_CONNECTING; | 853 | sk->sk_state = CAIF_CONNECTING; |
854 | 854 | ||
855 | /* Check priority value comming from socket */ | 855 | /* Check priority value coming from socket */ |
856 | /* if priority value is out of range it will be ajusted */ | 856 | /* if priority value is out of range it will be ajusted */ |
857 | if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) | 857 | if (cf_sk->sk.sk_priority > CAIF_PRIO_MAX) |
858 | cf_sk->conn_req.priority = CAIF_PRIO_MAX; | 858 | cf_sk->conn_req.priority = CAIF_PRIO_MAX; |
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c index 27dab26ad3b8..054fdb5aeb88 100644 --- a/net/caif/cfdgml.c +++ b/net/caif/cfdgml.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <net/caif/cfsrvl.h> | 13 | #include <net/caif/cfsrvl.h> |
14 | #include <net/caif/cfpkt.h> | 14 | #include <net/caif/cfpkt.h> |
15 | 15 | ||
16 | |||
16 | #define container_obj(layr) ((struct cfsrvl *) layr) | 17 | #define container_obj(layr) ((struct cfsrvl *) layr) |
17 | 18 | ||
18 | #define DGM_CMD_BIT 0x80 | 19 | #define DGM_CMD_BIT 0x80 |
@@ -83,6 +84,7 @@ static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt) | |||
83 | 84 | ||
84 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | 85 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) |
85 | { | 86 | { |
87 | u8 packet_type; | ||
86 | u32 zero = 0; | 88 | u32 zero = 0; |
87 | struct caif_payload_info *info; | 89 | struct caif_payload_info *info; |
88 | struct cfsrvl *service = container_obj(layr); | 90 | struct cfsrvl *service = container_obj(layr); |
@@ -94,7 +96,9 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
94 | if (cfpkt_getlen(pkt) > DGM_MTU) | 96 | if (cfpkt_getlen(pkt) > DGM_MTU) |
95 | return -EMSGSIZE; | 97 | return -EMSGSIZE; |
96 | 98 | ||
97 | cfpkt_add_head(pkt, &zero, 4); | 99 | cfpkt_add_head(pkt, &zero, 3); |
100 | packet_type = 0x08; /* B9 set - UNCLASSIFIED */ | ||
101 | cfpkt_add_head(pkt, &packet_type, 1); | ||
98 | 102 | ||
99 | /* Add info for MUX-layer to route the packet out. */ | 103 | /* Add info for MUX-layer to route the packet out. */ |
100 | info = cfpkt_info(pkt); | 104 | info = cfpkt_info(pkt); |
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 46f34b2e0478..24f1ffa74b06 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c | |||
@@ -244,9 +244,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
244 | int phyid) | 244 | int phyid) |
245 | { | 245 | { |
246 | struct cfmuxl *muxl = container_obj(layr); | 246 | struct cfmuxl *muxl = container_obj(layr); |
247 | struct list_head *node; | 247 | struct list_head *node, *next; |
248 | struct cflayer *layer; | 248 | struct cflayer *layer; |
249 | list_for_each(node, &muxl->srvl_list) { | 249 | list_for_each_safe(node, next, &muxl->srvl_list) { |
250 | layer = list_entry(node, struct cflayer, node); | 250 | layer = list_entry(node, struct cflayer, node); |
251 | if (cfsrvl_phyid_match(layer, phyid)) | 251 | if (cfsrvl_phyid_match(layer, phyid)) |
252 | layer->ctrlcmd(layer, ctrl, phyid); | 252 | layer->ctrlcmd(layer, ctrl, phyid); |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 702be5a2c956..733d66f1b05a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ | |||
95 | * af_can socket functions | 95 | * af_can socket functions |
96 | */ | 96 | */ |
97 | 97 | ||
98 | static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 98 | int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
99 | { | 99 | { |
100 | struct sock *sk = sock->sk; | 100 | struct sock *sk = sock->sk; |
101 | 101 | ||
@@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
108 | return -ENOIOCTLCMD; | 108 | return -ENOIOCTLCMD; |
109 | } | 109 | } |
110 | } | 110 | } |
111 | EXPORT_SYMBOL(can_ioctl); | ||
111 | 112 | ||
112 | static void can_sock_destruct(struct sock *sk) | 113 | static void can_sock_destruct(struct sock *sk) |
113 | { | 114 | { |
@@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp) | |||
698 | printk(KERN_ERR "can: protocol %d already registered\n", | 699 | printk(KERN_ERR "can: protocol %d already registered\n", |
699 | proto); | 700 | proto); |
700 | err = -EBUSY; | 701 | err = -EBUSY; |
701 | } else { | 702 | } else |
702 | proto_tab[proto] = cp; | 703 | proto_tab[proto] = cp; |
703 | 704 | ||
704 | /* use generic ioctl function if not defined by module */ | ||
705 | if (!cp->ops->ioctl) | ||
706 | cp->ops->ioctl = can_ioctl; | ||
707 | } | ||
708 | spin_unlock(&proto_tab_lock); | 705 | spin_unlock(&proto_tab_lock); |
709 | 706 | ||
710 | if (err < 0) | 707 | if (err < 0) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 092dc88a7c64..8a6a05e7c3c8 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -387,7 +387,7 @@ static void bcm_tx_timeout_tsklet(unsigned long data) | |||
387 | } | 387 | } |
388 | 388 | ||
389 | /* | 389 | /* |
390 | * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions | 390 | * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions |
391 | */ | 391 | */ |
392 | static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) | 392 | static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) |
393 | { | 393 | { |
@@ -1427,9 +1427,14 @@ static int bcm_init(struct sock *sk) | |||
1427 | static int bcm_release(struct socket *sock) | 1427 | static int bcm_release(struct socket *sock) |
1428 | { | 1428 | { |
1429 | struct sock *sk = sock->sk; | 1429 | struct sock *sk = sock->sk; |
1430 | struct bcm_sock *bo = bcm_sk(sk); | 1430 | struct bcm_sock *bo; |
1431 | struct bcm_op *op, *next; | 1431 | struct bcm_op *op, *next; |
1432 | 1432 | ||
1433 | if (sk == NULL) | ||
1434 | return 0; | ||
1435 | |||
1436 | bo = bcm_sk(sk); | ||
1437 | |||
1433 | /* remove bcm_ops, timer, rx_unregister(), etc. */ | 1438 | /* remove bcm_ops, timer, rx_unregister(), etc. */ |
1434 | 1439 | ||
1435 | unregister_netdevice_notifier(&bo->notifier); | 1440 | unregister_netdevice_notifier(&bo->notifier); |
@@ -1569,7 +1574,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1569 | return size; | 1574 | return size; |
1570 | } | 1575 | } |
1571 | 1576 | ||
1572 | static struct proto_ops bcm_ops __read_mostly = { | 1577 | static const struct proto_ops bcm_ops = { |
1573 | .family = PF_CAN, | 1578 | .family = PF_CAN, |
1574 | .release = bcm_release, | 1579 | .release = bcm_release, |
1575 | .bind = sock_no_bind, | 1580 | .bind = sock_no_bind, |
@@ -1578,7 +1583,7 @@ static struct proto_ops bcm_ops __read_mostly = { | |||
1578 | .accept = sock_no_accept, | 1583 | .accept = sock_no_accept, |
1579 | .getname = sock_no_getname, | 1584 | .getname = sock_no_getname, |
1580 | .poll = datagram_poll, | 1585 | .poll = datagram_poll, |
1581 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 1586 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
1582 | .listen = sock_no_listen, | 1587 | .listen = sock_no_listen, |
1583 | .shutdown = sock_no_shutdown, | 1588 | .shutdown = sock_no_shutdown, |
1584 | .setsockopt = sock_no_setsockopt, | 1589 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/can/raw.c b/net/can/raw.c index 883e9d74fddf..0eb39a7fdf64 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk) | |||
305 | static int raw_release(struct socket *sock) | 305 | static int raw_release(struct socket *sock) |
306 | { | 306 | { |
307 | struct sock *sk = sock->sk; | 307 | struct sock *sk = sock->sk; |
308 | struct raw_sock *ro = raw_sk(sk); | 308 | struct raw_sock *ro; |
309 | |||
310 | if (!sk) | ||
311 | return 0; | ||
312 | |||
313 | ro = raw_sk(sk); | ||
309 | 314 | ||
310 | unregister_netdevice_notifier(&ro->notifier); | 315 | unregister_netdevice_notifier(&ro->notifier); |
311 | 316 | ||
@@ -742,7 +747,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
742 | return size; | 747 | return size; |
743 | } | 748 | } |
744 | 749 | ||
745 | static struct proto_ops raw_ops __read_mostly = { | 750 | static const struct proto_ops raw_ops = { |
746 | .family = PF_CAN, | 751 | .family = PF_CAN, |
747 | .release = raw_release, | 752 | .release = raw_release, |
748 | .bind = raw_bind, | 753 | .bind = raw_bind, |
@@ -751,7 +756,7 @@ static struct proto_ops raw_ops __read_mostly = { | |||
751 | .accept = sock_no_accept, | 756 | .accept = sock_no_accept, |
752 | .getname = raw_getname, | 757 | .getname = raw_getname, |
753 | .poll = datagram_poll, | 758 | .poll = datagram_poll, |
754 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 759 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
755 | .listen = sock_no_listen, | 760 | .listen = sock_no_listen, |
756 | .shutdown = sock_no_shutdown, | 761 | .shutdown = sock_no_shutdown, |
757 | .setsockopt = raw_setsockopt, | 762 | .setsockopt = raw_setsockopt, |
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index ad424049b0cf..be683f2d401f 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig | |||
@@ -4,6 +4,7 @@ config CEPH_LIB | |||
4 | select LIBCRC32C | 4 | select LIBCRC32C |
5 | select CRYPTO_AES | 5 | select CRYPTO_AES |
6 | select CRYPTO | 6 | select CRYPTO |
7 | select KEYS | ||
7 | default n | 8 | default n |
8 | help | 9 | help |
9 | Choose Y or M here to include cephlib, which provides the | 10 | Choose Y or M here to include cephlib, which provides the |
diff --git a/net/ceph/armor.c b/net/ceph/armor.c index eb2a666b0be7..1fc1ee11dfa2 100644 --- a/net/ceph/armor.c +++ b/net/ceph/armor.c | |||
@@ -78,8 +78,10 @@ int ceph_unarmor(char *dst, const char *src, const char *end) | |||
78 | while (src < end) { | 78 | while (src < end) { |
79 | int a, b, c, d; | 79 | int a, b, c, d; |
80 | 80 | ||
81 | if (src < end && src[0] == '\n') | 81 | if (src[0] == '\n') { |
82 | src++; | 82 | src++; |
83 | continue; | ||
84 | } | ||
83 | if (src + 4 > end) | 85 | if (src + 4 > end) |
84 | return -EINVAL; | 86 | return -EINVAL; |
85 | a = decode_bits(src[0]); | 87 | a = decode_bits(src[0]); |
diff --git a/net/ceph/auth.c b/net/ceph/auth.c index 549c1f43e1d5..b4bf4ac090f1 100644 --- a/net/ceph/auth.c +++ b/net/ceph/auth.c | |||
@@ -35,12 +35,12 @@ static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol) | |||
35 | /* | 35 | /* |
36 | * setup, teardown. | 36 | * setup, teardown. |
37 | */ | 37 | */ |
38 | struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | 38 | struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key) |
39 | { | 39 | { |
40 | struct ceph_auth_client *ac; | 40 | struct ceph_auth_client *ac; |
41 | int ret; | 41 | int ret; |
42 | 42 | ||
43 | dout("auth_init name '%s' secret '%s'\n", name, secret); | 43 | dout("auth_init name '%s'\n", name); |
44 | 44 | ||
45 | ret = -ENOMEM; | 45 | ret = -ENOMEM; |
46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); | 46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); |
@@ -52,8 +52,8 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | |||
52 | ac->name = name; | 52 | ac->name = name; |
53 | else | 53 | else |
54 | ac->name = CEPH_AUTH_NAME_DEFAULT; | 54 | ac->name = CEPH_AUTH_NAME_DEFAULT; |
55 | dout("auth_init name %s secret %s\n", ac->name, secret); | 55 | dout("auth_init name %s\n", ac->name); |
56 | ac->secret = secret; | 56 | ac->key = key; |
57 | return ac; | 57 | return ac; |
58 | 58 | ||
59 | out: | 59 | out: |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 7fd5dfcf6e18..1587dc6010c6 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -662,14 +662,16 @@ int ceph_x_init(struct ceph_auth_client *ac) | |||
662 | goto out; | 662 | goto out; |
663 | 663 | ||
664 | ret = -EINVAL; | 664 | ret = -EINVAL; |
665 | if (!ac->secret) { | 665 | if (!ac->key) { |
666 | pr_err("no secret set (for auth_x protocol)\n"); | 666 | pr_err("no secret set (for auth_x protocol)\n"); |
667 | goto out_nomem; | 667 | goto out_nomem; |
668 | } | 668 | } |
669 | 669 | ||
670 | ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret); | 670 | ret = ceph_crypto_key_clone(&xi->secret, ac->key); |
671 | if (ret) | 671 | if (ret < 0) { |
672 | pr_err("cannot clone key: %d\n", ret); | ||
672 | goto out_nomem; | 673 | goto out_nomem; |
674 | } | ||
673 | 675 | ||
674 | xi->starting = true; | 676 | xi->starting = true; |
675 | xi->ticket_handlers = RB_ROOT; | 677 | xi->ticket_handlers = RB_ROOT; |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index f3e4a13fea0c..132963abc266 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
6 | #include <linux/inet.h> | 6 | #include <linux/inet.h> |
7 | #include <linux/in6.h> | 7 | #include <linux/in6.h> |
8 | #include <linux/key.h> | ||
9 | #include <keys/ceph-type.h> | ||
8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
9 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
10 | #include <linux/parser.h> | 12 | #include <linux/parser.h> |
@@ -20,6 +22,7 @@ | |||
20 | #include <linux/ceph/decode.h> | 22 | #include <linux/ceph/decode.h> |
21 | #include <linux/ceph/mon_client.h> | 23 | #include <linux/ceph/mon_client.h> |
22 | #include <linux/ceph/auth.h> | 24 | #include <linux/ceph/auth.h> |
25 | #include "crypto.h" | ||
23 | 26 | ||
24 | 27 | ||
25 | 28 | ||
@@ -62,6 +65,7 @@ const char *ceph_msg_type_name(int type) | |||
62 | case CEPH_MSG_OSD_MAP: return "osd_map"; | 65 | case CEPH_MSG_OSD_MAP: return "osd_map"; |
63 | case CEPH_MSG_OSD_OP: return "osd_op"; | 66 | case CEPH_MSG_OSD_OP: return "osd_op"; |
64 | case CEPH_MSG_OSD_OPREPLY: return "osd_opreply"; | 67 | case CEPH_MSG_OSD_OPREPLY: return "osd_opreply"; |
68 | case CEPH_MSG_WATCH_NOTIFY: return "watch_notify"; | ||
65 | default: return "unknown"; | 69 | default: return "unknown"; |
66 | } | 70 | } |
67 | } | 71 | } |
@@ -116,9 +120,29 @@ int ceph_compare_options(struct ceph_options *new_opt, | |||
116 | if (ret) | 120 | if (ret) |
117 | return ret; | 121 | return ret; |
118 | 122 | ||
119 | ret = strcmp_null(opt1->secret, opt2->secret); | 123 | if (opt1->key && !opt2->key) |
120 | if (ret) | 124 | return -1; |
121 | return ret; | 125 | if (!opt1->key && opt2->key) |
126 | return 1; | ||
127 | if (opt1->key && opt2->key) { | ||
128 | if (opt1->key->type != opt2->key->type) | ||
129 | return -1; | ||
130 | if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) | ||
131 | return -1; | ||
132 | if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) | ||
133 | return -1; | ||
134 | if (opt1->key->len != opt2->key->len) | ||
135 | return -1; | ||
136 | if (opt1->key->key && !opt2->key->key) | ||
137 | return -1; | ||
138 | if (!opt1->key->key && opt2->key->key) | ||
139 | return 1; | ||
140 | if (opt1->key->key && opt2->key->key) { | ||
141 | ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | } | ||
145 | } | ||
122 | 146 | ||
123 | /* any matching mon ip implies a match */ | 147 | /* any matching mon ip implies a match */ |
124 | for (i = 0; i < opt1->num_mon; i++) { | 148 | for (i = 0; i < opt1->num_mon; i++) { |
@@ -175,6 +199,7 @@ enum { | |||
175 | Opt_fsid, | 199 | Opt_fsid, |
176 | Opt_name, | 200 | Opt_name, |
177 | Opt_secret, | 201 | Opt_secret, |
202 | Opt_key, | ||
178 | Opt_ip, | 203 | Opt_ip, |
179 | Opt_last_string, | 204 | Opt_last_string, |
180 | /* string args above */ | 205 | /* string args above */ |
@@ -191,6 +216,7 @@ static match_table_t opt_tokens = { | |||
191 | {Opt_fsid, "fsid=%s"}, | 216 | {Opt_fsid, "fsid=%s"}, |
192 | {Opt_name, "name=%s"}, | 217 | {Opt_name, "name=%s"}, |
193 | {Opt_secret, "secret=%s"}, | 218 | {Opt_secret, "secret=%s"}, |
219 | {Opt_key, "key=%s"}, | ||
194 | {Opt_ip, "ip=%s"}, | 220 | {Opt_ip, "ip=%s"}, |
195 | /* string args above */ | 221 | /* string args above */ |
196 | {Opt_noshare, "noshare"}, | 222 | {Opt_noshare, "noshare"}, |
@@ -202,11 +228,56 @@ void ceph_destroy_options(struct ceph_options *opt) | |||
202 | { | 228 | { |
203 | dout("destroy_options %p\n", opt); | 229 | dout("destroy_options %p\n", opt); |
204 | kfree(opt->name); | 230 | kfree(opt->name); |
205 | kfree(opt->secret); | 231 | if (opt->key) { |
232 | ceph_crypto_key_destroy(opt->key); | ||
233 | kfree(opt->key); | ||
234 | } | ||
206 | kfree(opt); | 235 | kfree(opt); |
207 | } | 236 | } |
208 | EXPORT_SYMBOL(ceph_destroy_options); | 237 | EXPORT_SYMBOL(ceph_destroy_options); |
209 | 238 | ||
239 | /* get secret from key store */ | ||
240 | static int get_secret(struct ceph_crypto_key *dst, const char *name) { | ||
241 | struct key *ukey; | ||
242 | int key_err; | ||
243 | int err = 0; | ||
244 | struct ceph_crypto_key *ckey; | ||
245 | |||
246 | ukey = request_key(&key_type_ceph, name, NULL); | ||
247 | if (!ukey || IS_ERR(ukey)) { | ||
248 | /* request_key errors don't map nicely to mount(2) | ||
249 | errors; don't even try, but still printk */ | ||
250 | key_err = PTR_ERR(ukey); | ||
251 | switch (key_err) { | ||
252 | case -ENOKEY: | ||
253 | pr_warning("ceph: Mount failed due to key not found: %s\n", name); | ||
254 | break; | ||
255 | case -EKEYEXPIRED: | ||
256 | pr_warning("ceph: Mount failed due to expired key: %s\n", name); | ||
257 | break; | ||
258 | case -EKEYREVOKED: | ||
259 | pr_warning("ceph: Mount failed due to revoked key: %s\n", name); | ||
260 | break; | ||
261 | default: | ||
262 | pr_warning("ceph: Mount failed due to unknown key error" | ||
263 | " %d: %s\n", key_err, name); | ||
264 | } | ||
265 | err = -EPERM; | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | ckey = ukey->payload.data; | ||
270 | err = ceph_crypto_key_clone(dst, ckey); | ||
271 | if (err) | ||
272 | goto out_key; | ||
273 | /* pass through, err is 0 */ | ||
274 | |||
275 | out_key: | ||
276 | key_put(ukey); | ||
277 | out: | ||
278 | return err; | ||
279 | } | ||
280 | |||
210 | int ceph_parse_options(struct ceph_options **popt, char *options, | 281 | int ceph_parse_options(struct ceph_options **popt, char *options, |
211 | const char *dev_name, const char *dev_name_end, | 282 | const char *dev_name, const char *dev_name_end, |
212 | int (*parse_extra_token)(char *c, void *private), | 283 | int (*parse_extra_token)(char *c, void *private), |
@@ -294,9 +365,24 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
294 | GFP_KERNEL); | 365 | GFP_KERNEL); |
295 | break; | 366 | break; |
296 | case Opt_secret: | 367 | case Opt_secret: |
297 | opt->secret = kstrndup(argstr[0].from, | 368 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
298 | argstr[0].to-argstr[0].from, | 369 | if (!opt->key) { |
299 | GFP_KERNEL); | 370 | err = -ENOMEM; |
371 | goto out; | ||
372 | } | ||
373 | err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); | ||
374 | if (err < 0) | ||
375 | goto out; | ||
376 | break; | ||
377 | case Opt_key: | ||
378 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); | ||
379 | if (!opt->key) { | ||
380 | err = -ENOMEM; | ||
381 | goto out; | ||
382 | } | ||
383 | err = get_secret(opt->key, argstr[0].from); | ||
384 | if (err < 0) | ||
385 | goto out; | ||
300 | break; | 386 | break; |
301 | 387 | ||
302 | /* misc */ | 388 | /* misc */ |
@@ -393,8 +479,8 @@ void ceph_destroy_client(struct ceph_client *client) | |||
393 | ceph_osdc_stop(&client->osdc); | 479 | ceph_osdc_stop(&client->osdc); |
394 | 480 | ||
395 | /* | 481 | /* |
396 | * make sure mds and osd connections close out before destroying | 482 | * make sure osd connections close out before destroying the |
397 | * the auth module, which is needed to free those connections' | 483 | * auth module, which is needed to free those connections' |
398 | * ceph_authorizers. | 484 | * ceph_authorizers. |
399 | */ | 485 | */ |
400 | ceph_msgr_flush(); | 486 | ceph_msgr_flush(); |
@@ -495,10 +581,14 @@ static int __init init_ceph_lib(void) | |||
495 | if (ret < 0) | 581 | if (ret < 0) |
496 | goto out; | 582 | goto out; |
497 | 583 | ||
498 | ret = ceph_msgr_init(); | 584 | ret = ceph_crypto_init(); |
499 | if (ret < 0) | 585 | if (ret < 0) |
500 | goto out_debugfs; | 586 | goto out_debugfs; |
501 | 587 | ||
588 | ret = ceph_msgr_init(); | ||
589 | if (ret < 0) | ||
590 | goto out_crypto; | ||
591 | |||
502 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", | 592 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", |
503 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, | 593 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, |
504 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, | 594 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, |
@@ -506,6 +596,8 @@ static int __init init_ceph_lib(void) | |||
506 | 596 | ||
507 | return 0; | 597 | return 0; |
508 | 598 | ||
599 | out_crypto: | ||
600 | ceph_crypto_shutdown(); | ||
509 | out_debugfs: | 601 | out_debugfs: |
510 | ceph_debugfs_cleanup(); | 602 | ceph_debugfs_cleanup(); |
511 | out: | 603 | out: |
@@ -516,6 +608,7 @@ static void __exit exit_ceph_lib(void) | |||
516 | { | 608 | { |
517 | dout("exit_ceph_lib\n"); | 609 | dout("exit_ceph_lib\n"); |
518 | ceph_msgr_exit(); | 610 | ceph_msgr_exit(); |
611 | ceph_crypto_shutdown(); | ||
519 | ceph_debugfs_cleanup(); | 612 | ceph_debugfs_cleanup(); |
520 | } | 613 | } |
521 | 614 | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 7b505b0c983f..5a8009c9e0cd 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -5,10 +5,23 @@ | |||
5 | #include <linux/scatterlist.h> | 5 | #include <linux/scatterlist.h> |
6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
7 | #include <crypto/hash.h> | 7 | #include <crypto/hash.h> |
8 | #include <linux/key-type.h> | ||
8 | 9 | ||
10 | #include <keys/ceph-type.h> | ||
9 | #include <linux/ceph/decode.h> | 11 | #include <linux/ceph/decode.h> |
10 | #include "crypto.h" | 12 | #include "crypto.h" |
11 | 13 | ||
14 | int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
15 | const struct ceph_crypto_key *src) | ||
16 | { | ||
17 | memcpy(dst, src, sizeof(struct ceph_crypto_key)); | ||
18 | dst->key = kmalloc(src->len, GFP_NOFS); | ||
19 | if (!dst->key) | ||
20 | return -ENOMEM; | ||
21 | memcpy(dst->key, src->key, src->len); | ||
22 | return 0; | ||
23 | } | ||
24 | |||
12 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) | 25 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) |
13 | { | 26 | { |
14 | if (*p + sizeof(u16) + sizeof(key->created) + | 27 | if (*p + sizeof(u16) + sizeof(key->created) + |
@@ -410,3 +423,63 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, | |||
410 | return -EINVAL; | 423 | return -EINVAL; |
411 | } | 424 | } |
412 | } | 425 | } |
426 | |||
427 | int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
428 | { | ||
429 | struct ceph_crypto_key *ckey; | ||
430 | int ret; | ||
431 | void *p; | ||
432 | |||
433 | ret = -EINVAL; | ||
434 | if (datalen <= 0 || datalen > 32767 || !data) | ||
435 | goto err; | ||
436 | |||
437 | ret = key_payload_reserve(key, datalen); | ||
438 | if (ret < 0) | ||
439 | goto err; | ||
440 | |||
441 | ret = -ENOMEM; | ||
442 | ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); | ||
443 | if (!ckey) | ||
444 | goto err; | ||
445 | |||
446 | /* TODO ceph_crypto_key_decode should really take const input */ | ||
447 | p = (void*)data; | ||
448 | ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); | ||
449 | if (ret < 0) | ||
450 | goto err_ckey; | ||
451 | |||
452 | key->payload.data = ckey; | ||
453 | return 0; | ||
454 | |||
455 | err_ckey: | ||
456 | kfree(ckey); | ||
457 | err: | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | int ceph_key_match(const struct key *key, const void *description) | ||
462 | { | ||
463 | return strcmp(key->description, description) == 0; | ||
464 | } | ||
465 | |||
466 | void ceph_key_destroy(struct key *key) { | ||
467 | struct ceph_crypto_key *ckey = key->payload.data; | ||
468 | |||
469 | ceph_crypto_key_destroy(ckey); | ||
470 | } | ||
471 | |||
472 | struct key_type key_type_ceph = { | ||
473 | .name = "ceph", | ||
474 | .instantiate = ceph_key_instantiate, | ||
475 | .match = ceph_key_match, | ||
476 | .destroy = ceph_key_destroy, | ||
477 | }; | ||
478 | |||
479 | int ceph_crypto_init(void) { | ||
480 | return register_key_type(&key_type_ceph); | ||
481 | } | ||
482 | |||
483 | void ceph_crypto_shutdown(void) { | ||
484 | unregister_key_type(&key_type_ceph); | ||
485 | } | ||
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index f9eccace592b..1919d1550d75 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h | |||
@@ -19,6 +19,8 @@ static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) | |||
19 | kfree(key->key); | 19 | kfree(key->key); |
20 | } | 20 | } |
21 | 21 | ||
22 | extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
23 | const struct ceph_crypto_key *src); | ||
22 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, | 24 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, |
23 | void **p, void *end); | 25 | void **p, void *end); |
24 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, | 26 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, |
@@ -40,6 +42,8 @@ extern int ceph_encrypt2(struct ceph_crypto_key *secret, | |||
40 | void *dst, size_t *dst_len, | 42 | void *dst, size_t *dst_len, |
41 | const void *src1, size_t src1_len, | 43 | const void *src1, size_t src1_len, |
42 | const void *src2, size_t src2_len); | 44 | const void *src2, size_t src2_len); |
45 | extern int ceph_crypto_init(void); | ||
46 | extern void ceph_crypto_shutdown(void); | ||
43 | 47 | ||
44 | /* armor.c */ | 48 | /* armor.c */ |
45 | extern int ceph_armor(char *dst, const char *src, const char *end); | 49 | extern int ceph_armor(char *dst, const char *src, const char *end); |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 05f357828a2f..e15a82ccc05f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -2267,6 +2267,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | |||
2267 | m->more_to_follow = false; | 2267 | m->more_to_follow = false; |
2268 | m->pool = NULL; | 2268 | m->pool = NULL; |
2269 | 2269 | ||
2270 | /* middle */ | ||
2271 | m->middle = NULL; | ||
2272 | |||
2273 | /* data */ | ||
2274 | m->nr_pages = 0; | ||
2275 | m->page_alignment = 0; | ||
2276 | m->pages = NULL; | ||
2277 | m->pagelist = NULL; | ||
2278 | m->bio = NULL; | ||
2279 | m->bio_iter = NULL; | ||
2280 | m->bio_seg = 0; | ||
2281 | m->trail = NULL; | ||
2282 | |||
2270 | /* front */ | 2283 | /* front */ |
2271 | if (front_len) { | 2284 | if (front_len) { |
2272 | if (front_len > PAGE_CACHE_SIZE) { | 2285 | if (front_len > PAGE_CACHE_SIZE) { |
@@ -2286,19 +2299,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags) | |||
2286 | } | 2299 | } |
2287 | m->front.iov_len = front_len; | 2300 | m->front.iov_len = front_len; |
2288 | 2301 | ||
2289 | /* middle */ | ||
2290 | m->middle = NULL; | ||
2291 | |||
2292 | /* data */ | ||
2293 | m->nr_pages = 0; | ||
2294 | m->page_alignment = 0; | ||
2295 | m->pages = NULL; | ||
2296 | m->pagelist = NULL; | ||
2297 | m->bio = NULL; | ||
2298 | m->bio_iter = NULL; | ||
2299 | m->bio_seg = 0; | ||
2300 | m->trail = NULL; | ||
2301 | |||
2302 | dout("ceph_msg_new %p front %d\n", m, front_len); | 2302 | dout("ceph_msg_new %p front %d\n", m, front_len); |
2303 | return m; | 2303 | return m; |
2304 | 2304 | ||
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 8a079399174a..cbe31fa45508 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -759,7 +759,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
759 | 759 | ||
760 | /* authentication */ | 760 | /* authentication */ |
761 | monc->auth = ceph_auth_init(cl->options->name, | 761 | monc->auth = ceph_auth_init(cl->options->name, |
762 | cl->options->secret); | 762 | cl->options->key); |
763 | if (IS_ERR(monc->auth)) | 763 | if (IS_ERR(monc->auth)) |
764 | return PTR_ERR(monc->auth); | 764 | return PTR_ERR(monc->auth); |
765 | monc->auth->want_keys = | 765 | monc->auth->want_keys = |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 3e20a122ffa2..6b5dda1cb5df 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -22,10 +22,15 @@ | |||
22 | #define OSD_OPREPLY_FRONT_LEN 512 | 22 | #define OSD_OPREPLY_FRONT_LEN 512 |
23 | 23 | ||
24 | static const struct ceph_connection_operations osd_con_ops; | 24 | static const struct ceph_connection_operations osd_con_ops; |
25 | static int __kick_requests(struct ceph_osd_client *osdc, | ||
26 | struct ceph_osd *kickosd); | ||
27 | 25 | ||
28 | static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd); | 26 | static void send_queued(struct ceph_osd_client *osdc); |
27 | static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd); | ||
28 | static void __register_request(struct ceph_osd_client *osdc, | ||
29 | struct ceph_osd_request *req); | ||
30 | static void __unregister_linger_request(struct ceph_osd_client *osdc, | ||
31 | struct ceph_osd_request *req); | ||
32 | static int __send_request(struct ceph_osd_client *osdc, | ||
33 | struct ceph_osd_request *req); | ||
29 | 34 | ||
30 | static int op_needs_trail(int op) | 35 | static int op_needs_trail(int op) |
31 | { | 36 | { |
@@ -34,6 +39,7 @@ static int op_needs_trail(int op) | |||
34 | case CEPH_OSD_OP_SETXATTR: | 39 | case CEPH_OSD_OP_SETXATTR: |
35 | case CEPH_OSD_OP_CMPXATTR: | 40 | case CEPH_OSD_OP_CMPXATTR: |
36 | case CEPH_OSD_OP_CALL: | 41 | case CEPH_OSD_OP_CALL: |
42 | case CEPH_OSD_OP_NOTIFY: | ||
37 | return 1; | 43 | return 1; |
38 | default: | 44 | default: |
39 | return 0; | 45 | return 0; |
@@ -209,6 +215,8 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
209 | init_completion(&req->r_completion); | 215 | init_completion(&req->r_completion); |
210 | init_completion(&req->r_safe_completion); | 216 | init_completion(&req->r_safe_completion); |
211 | INIT_LIST_HEAD(&req->r_unsafe_item); | 217 | INIT_LIST_HEAD(&req->r_unsafe_item); |
218 | INIT_LIST_HEAD(&req->r_linger_item); | ||
219 | INIT_LIST_HEAD(&req->r_linger_osd); | ||
212 | req->r_flags = flags; | 220 | req->r_flags = flags; |
213 | 221 | ||
214 | WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0); | 222 | WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0); |
@@ -315,6 +323,24 @@ static void osd_req_encode_op(struct ceph_osd_request *req, | |||
315 | break; | 323 | break; |
316 | case CEPH_OSD_OP_STARTSYNC: | 324 | case CEPH_OSD_OP_STARTSYNC: |
317 | break; | 325 | break; |
326 | case CEPH_OSD_OP_NOTIFY: | ||
327 | { | ||
328 | __le32 prot_ver = cpu_to_le32(src->watch.prot_ver); | ||
329 | __le32 timeout = cpu_to_le32(src->watch.timeout); | ||
330 | |||
331 | BUG_ON(!req->r_trail); | ||
332 | |||
333 | ceph_pagelist_append(req->r_trail, | ||
334 | &prot_ver, sizeof(prot_ver)); | ||
335 | ceph_pagelist_append(req->r_trail, | ||
336 | &timeout, sizeof(timeout)); | ||
337 | } | ||
338 | case CEPH_OSD_OP_NOTIFY_ACK: | ||
339 | case CEPH_OSD_OP_WATCH: | ||
340 | dst->watch.cookie = cpu_to_le64(src->watch.cookie); | ||
341 | dst->watch.ver = cpu_to_le64(src->watch.ver); | ||
342 | dst->watch.flag = src->watch.flag; | ||
343 | break; | ||
318 | default: | 344 | default: |
319 | pr_err("unrecognized osd opcode %d\n", dst->op); | 345 | pr_err("unrecognized osd opcode %d\n", dst->op); |
320 | WARN_ON(1); | 346 | WARN_ON(1); |
@@ -444,8 +470,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
444 | snapc, ops, | 470 | snapc, ops, |
445 | use_mempool, | 471 | use_mempool, |
446 | GFP_NOFS, NULL, NULL); | 472 | GFP_NOFS, NULL, NULL); |
447 | if (IS_ERR(req)) | 473 | if (!req) |
448 | return req; | 474 | return NULL; |
449 | 475 | ||
450 | /* calculate max write size */ | 476 | /* calculate max write size */ |
451 | calc_layout(osdc, vino, layout, off, plen, req, ops); | 477 | calc_layout(osdc, vino, layout, off, plen, req, ops); |
@@ -529,6 +555,51 @@ __lookup_request_ge(struct ceph_osd_client *osdc, | |||
529 | return NULL; | 555 | return NULL; |
530 | } | 556 | } |
531 | 557 | ||
558 | /* | ||
559 | * Resubmit requests pending on the given osd. | ||
560 | */ | ||
561 | static void __kick_osd_requests(struct ceph_osd_client *osdc, | ||
562 | struct ceph_osd *osd) | ||
563 | { | ||
564 | struct ceph_osd_request *req, *nreq; | ||
565 | int err; | ||
566 | |||
567 | dout("__kick_osd_requests osd%d\n", osd->o_osd); | ||
568 | err = __reset_osd(osdc, osd); | ||
569 | if (err == -EAGAIN) | ||
570 | return; | ||
571 | |||
572 | list_for_each_entry(req, &osd->o_requests, r_osd_item) { | ||
573 | list_move(&req->r_req_lru_item, &osdc->req_unsent); | ||
574 | dout("requeued %p tid %llu osd%d\n", req, req->r_tid, | ||
575 | osd->o_osd); | ||
576 | if (!req->r_linger) | ||
577 | req->r_flags |= CEPH_OSD_FLAG_RETRY; | ||
578 | } | ||
579 | |||
580 | list_for_each_entry_safe(req, nreq, &osd->o_linger_requests, | ||
581 | r_linger_osd) { | ||
582 | /* | ||
583 | * reregister request prior to unregistering linger so | ||
584 | * that r_osd is preserved. | ||
585 | */ | ||
586 | BUG_ON(!list_empty(&req->r_req_lru_item)); | ||
587 | __register_request(osdc, req); | ||
588 | list_add(&req->r_req_lru_item, &osdc->req_unsent); | ||
589 | list_add(&req->r_osd_item, &req->r_osd->o_requests); | ||
590 | __unregister_linger_request(osdc, req); | ||
591 | dout("requeued lingering %p tid %llu osd%d\n", req, req->r_tid, | ||
592 | osd->o_osd); | ||
593 | } | ||
594 | } | ||
595 | |||
596 | static void kick_osd_requests(struct ceph_osd_client *osdc, | ||
597 | struct ceph_osd *kickosd) | ||
598 | { | ||
599 | mutex_lock(&osdc->request_mutex); | ||
600 | __kick_osd_requests(osdc, kickosd); | ||
601 | mutex_unlock(&osdc->request_mutex); | ||
602 | } | ||
532 | 603 | ||
533 | /* | 604 | /* |
534 | * If the osd connection drops, we need to resubmit all requests. | 605 | * If the osd connection drops, we need to resubmit all requests. |
@@ -543,7 +614,8 @@ static void osd_reset(struct ceph_connection *con) | |||
543 | dout("osd_reset osd%d\n", osd->o_osd); | 614 | dout("osd_reset osd%d\n", osd->o_osd); |
544 | osdc = osd->o_osdc; | 615 | osdc = osd->o_osdc; |
545 | down_read(&osdc->map_sem); | 616 | down_read(&osdc->map_sem); |
546 | kick_requests(osdc, osd); | 617 | kick_osd_requests(osdc, osd); |
618 | send_queued(osdc); | ||
547 | up_read(&osdc->map_sem); | 619 | up_read(&osdc->map_sem); |
548 | } | 620 | } |
549 | 621 | ||
@@ -561,6 +633,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) | |||
561 | atomic_set(&osd->o_ref, 1); | 633 | atomic_set(&osd->o_ref, 1); |
562 | osd->o_osdc = osdc; | 634 | osd->o_osdc = osdc; |
563 | INIT_LIST_HEAD(&osd->o_requests); | 635 | INIT_LIST_HEAD(&osd->o_requests); |
636 | INIT_LIST_HEAD(&osd->o_linger_requests); | ||
564 | INIT_LIST_HEAD(&osd->o_osd_lru); | 637 | INIT_LIST_HEAD(&osd->o_osd_lru); |
565 | osd->o_incarnation = 1; | 638 | osd->o_incarnation = 1; |
566 | 639 | ||
@@ -650,7 +723,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) | |||
650 | int ret = 0; | 723 | int ret = 0; |
651 | 724 | ||
652 | dout("__reset_osd %p osd%d\n", osd, osd->o_osd); | 725 | dout("__reset_osd %p osd%d\n", osd, osd->o_osd); |
653 | if (list_empty(&osd->o_requests)) { | 726 | if (list_empty(&osd->o_requests) && |
727 | list_empty(&osd->o_linger_requests)) { | ||
654 | __remove_osd(osdc, osd); | 728 | __remove_osd(osdc, osd); |
655 | } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], | 729 | } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], |
656 | &osd->o_con.peer_addr, | 730 | &osd->o_con.peer_addr, |
@@ -723,15 +797,14 @@ static void __cancel_osd_timeout(struct ceph_osd_client *osdc) | |||
723 | * Register request, assign tid. If this is the first request, set up | 797 | * Register request, assign tid. If this is the first request, set up |
724 | * the timeout event. | 798 | * the timeout event. |
725 | */ | 799 | */ |
726 | static void register_request(struct ceph_osd_client *osdc, | 800 | static void __register_request(struct ceph_osd_client *osdc, |
727 | struct ceph_osd_request *req) | 801 | struct ceph_osd_request *req) |
728 | { | 802 | { |
729 | mutex_lock(&osdc->request_mutex); | ||
730 | req->r_tid = ++osdc->last_tid; | 803 | req->r_tid = ++osdc->last_tid; |
731 | req->r_request->hdr.tid = cpu_to_le64(req->r_tid); | 804 | req->r_request->hdr.tid = cpu_to_le64(req->r_tid); |
732 | INIT_LIST_HEAD(&req->r_req_lru_item); | 805 | INIT_LIST_HEAD(&req->r_req_lru_item); |
733 | 806 | ||
734 | dout("register_request %p tid %lld\n", req, req->r_tid); | 807 | dout("__register_request %p tid %lld\n", req, req->r_tid); |
735 | __insert_request(osdc, req); | 808 | __insert_request(osdc, req); |
736 | ceph_osdc_get_request(req); | 809 | ceph_osdc_get_request(req); |
737 | osdc->num_requests++; | 810 | osdc->num_requests++; |
@@ -740,6 +813,13 @@ static void register_request(struct ceph_osd_client *osdc, | |||
740 | dout(" first request, scheduling timeout\n"); | 813 | dout(" first request, scheduling timeout\n"); |
741 | __schedule_osd_timeout(osdc); | 814 | __schedule_osd_timeout(osdc); |
742 | } | 815 | } |
816 | } | ||
817 | |||
818 | static void register_request(struct ceph_osd_client *osdc, | ||
819 | struct ceph_osd_request *req) | ||
820 | { | ||
821 | mutex_lock(&osdc->request_mutex); | ||
822 | __register_request(osdc, req); | ||
743 | mutex_unlock(&osdc->request_mutex); | 823 | mutex_unlock(&osdc->request_mutex); |
744 | } | 824 | } |
745 | 825 | ||
@@ -758,9 +838,13 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
758 | ceph_con_revoke(&req->r_osd->o_con, req->r_request); | 838 | ceph_con_revoke(&req->r_osd->o_con, req->r_request); |
759 | 839 | ||
760 | list_del_init(&req->r_osd_item); | 840 | list_del_init(&req->r_osd_item); |
761 | if (list_empty(&req->r_osd->o_requests)) | 841 | if (list_empty(&req->r_osd->o_requests) && |
842 | list_empty(&req->r_osd->o_linger_requests)) { | ||
843 | dout("moving osd to %p lru\n", req->r_osd); | ||
762 | __move_osd_to_lru(osdc, req->r_osd); | 844 | __move_osd_to_lru(osdc, req->r_osd); |
763 | req->r_osd = NULL; | 845 | } |
846 | if (list_empty(&req->r_linger_item)) | ||
847 | req->r_osd = NULL; | ||
764 | } | 848 | } |
765 | 849 | ||
766 | ceph_osdc_put_request(req); | 850 | ceph_osdc_put_request(req); |
@@ -781,20 +865,73 @@ static void __cancel_request(struct ceph_osd_request *req) | |||
781 | ceph_con_revoke(&req->r_osd->o_con, req->r_request); | 865 | ceph_con_revoke(&req->r_osd->o_con, req->r_request); |
782 | req->r_sent = 0; | 866 | req->r_sent = 0; |
783 | } | 867 | } |
784 | list_del_init(&req->r_req_lru_item); | ||
785 | } | 868 | } |
786 | 869 | ||
870 | static void __register_linger_request(struct ceph_osd_client *osdc, | ||
871 | struct ceph_osd_request *req) | ||
872 | { | ||
873 | dout("__register_linger_request %p\n", req); | ||
874 | list_add_tail(&req->r_linger_item, &osdc->req_linger); | ||
875 | list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests); | ||
876 | } | ||
877 | |||
878 | static void __unregister_linger_request(struct ceph_osd_client *osdc, | ||
879 | struct ceph_osd_request *req) | ||
880 | { | ||
881 | dout("__unregister_linger_request %p\n", req); | ||
882 | if (req->r_osd) { | ||
883 | list_del_init(&req->r_linger_item); | ||
884 | list_del_init(&req->r_linger_osd); | ||
885 | |||
886 | if (list_empty(&req->r_osd->o_requests) && | ||
887 | list_empty(&req->r_osd->o_linger_requests)) { | ||
888 | dout("moving osd to %p lru\n", req->r_osd); | ||
889 | __move_osd_to_lru(osdc, req->r_osd); | ||
890 | } | ||
891 | if (list_empty(&req->r_osd_item)) | ||
892 | req->r_osd = NULL; | ||
893 | } | ||
894 | } | ||
895 | |||
896 | void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc, | ||
897 | struct ceph_osd_request *req) | ||
898 | { | ||
899 | mutex_lock(&osdc->request_mutex); | ||
900 | if (req->r_linger) { | ||
901 | __unregister_linger_request(osdc, req); | ||
902 | ceph_osdc_put_request(req); | ||
903 | } | ||
904 | mutex_unlock(&osdc->request_mutex); | ||
905 | } | ||
906 | EXPORT_SYMBOL(ceph_osdc_unregister_linger_request); | ||
907 | |||
908 | void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc, | ||
909 | struct ceph_osd_request *req) | ||
910 | { | ||
911 | if (!req->r_linger) { | ||
912 | dout("set_request_linger %p\n", req); | ||
913 | req->r_linger = 1; | ||
914 | /* | ||
915 | * caller is now responsible for calling | ||
916 | * unregister_linger_request | ||
917 | */ | ||
918 | ceph_osdc_get_request(req); | ||
919 | } | ||
920 | } | ||
921 | EXPORT_SYMBOL(ceph_osdc_set_request_linger); | ||
922 | |||
787 | /* | 923 | /* |
788 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct | 924 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct |
789 | * (as needed), and set the request r_osd appropriately. If there is | 925 | * (as needed), and set the request r_osd appropriately. If there is |
790 | * no up osd, set r_osd to NULL. | 926 | * no up osd, set r_osd to NULL. Move the request to the appropriate list |
927 | * (unsent, homeless) or leave on in-flight lru. | ||
791 | * | 928 | * |
792 | * Return 0 if unchanged, 1 if changed, or negative on error. | 929 | * Return 0 if unchanged, 1 if changed, or negative on error. |
793 | * | 930 | * |
794 | * Caller should hold map_sem for read and request_mutex. | 931 | * Caller should hold map_sem for read and request_mutex. |
795 | */ | 932 | */ |
796 | static int __map_osds(struct ceph_osd_client *osdc, | 933 | static int __map_request(struct ceph_osd_client *osdc, |
797 | struct ceph_osd_request *req) | 934 | struct ceph_osd_request *req) |
798 | { | 935 | { |
799 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; | 936 | struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; |
800 | struct ceph_pg pgid; | 937 | struct ceph_pg pgid; |
@@ -802,11 +939,13 @@ static int __map_osds(struct ceph_osd_client *osdc, | |||
802 | int o = -1, num = 0; | 939 | int o = -1, num = 0; |
803 | int err; | 940 | int err; |
804 | 941 | ||
805 | dout("map_osds %p tid %lld\n", req, req->r_tid); | 942 | dout("map_request %p tid %lld\n", req, req->r_tid); |
806 | err = ceph_calc_object_layout(&reqhead->layout, req->r_oid, | 943 | err = ceph_calc_object_layout(&reqhead->layout, req->r_oid, |
807 | &req->r_file_layout, osdc->osdmap); | 944 | &req->r_file_layout, osdc->osdmap); |
808 | if (err) | 945 | if (err) { |
946 | list_move(&req->r_req_lru_item, &osdc->req_notarget); | ||
809 | return err; | 947 | return err; |
948 | } | ||
810 | pgid = reqhead->layout.ol_pgid; | 949 | pgid = reqhead->layout.ol_pgid; |
811 | req->r_pgid = pgid; | 950 | req->r_pgid = pgid; |
812 | 951 | ||
@@ -823,7 +962,7 @@ static int __map_osds(struct ceph_osd_client *osdc, | |||
823 | (req->r_osd == NULL && o == -1)) | 962 | (req->r_osd == NULL && o == -1)) |
824 | return 0; /* no change */ | 963 | return 0; /* no change */ |
825 | 964 | ||
826 | dout("map_osds tid %llu pgid %d.%x osd%d (was osd%d)\n", | 965 | dout("map_request tid %llu pgid %d.%x osd%d (was osd%d)\n", |
827 | req->r_tid, le32_to_cpu(pgid.pool), le16_to_cpu(pgid.ps), o, | 966 | req->r_tid, le32_to_cpu(pgid.pool), le16_to_cpu(pgid.ps), o, |
828 | req->r_osd ? req->r_osd->o_osd : -1); | 967 | req->r_osd ? req->r_osd->o_osd : -1); |
829 | 968 | ||
@@ -841,10 +980,12 @@ static int __map_osds(struct ceph_osd_client *osdc, | |||
841 | if (!req->r_osd && o >= 0) { | 980 | if (!req->r_osd && o >= 0) { |
842 | err = -ENOMEM; | 981 | err = -ENOMEM; |
843 | req->r_osd = create_osd(osdc); | 982 | req->r_osd = create_osd(osdc); |
844 | if (!req->r_osd) | 983 | if (!req->r_osd) { |
984 | list_move(&req->r_req_lru_item, &osdc->req_notarget); | ||
845 | goto out; | 985 | goto out; |
986 | } | ||
846 | 987 | ||
847 | dout("map_osds osd %p is osd%d\n", req->r_osd, o); | 988 | dout("map_request osd %p is osd%d\n", req->r_osd, o); |
848 | req->r_osd->o_osd = o; | 989 | req->r_osd->o_osd = o; |
849 | req->r_osd->o_con.peer_name.num = cpu_to_le64(o); | 990 | req->r_osd->o_con.peer_name.num = cpu_to_le64(o); |
850 | __insert_osd(osdc, req->r_osd); | 991 | __insert_osd(osdc, req->r_osd); |
@@ -855,6 +996,9 @@ static int __map_osds(struct ceph_osd_client *osdc, | |||
855 | if (req->r_osd) { | 996 | if (req->r_osd) { |
856 | __remove_osd_from_lru(req->r_osd); | 997 | __remove_osd_from_lru(req->r_osd); |
857 | list_add(&req->r_osd_item, &req->r_osd->o_requests); | 998 | list_add(&req->r_osd_item, &req->r_osd->o_requests); |
999 | list_move(&req->r_req_lru_item, &osdc->req_unsent); | ||
1000 | } else { | ||
1001 | list_move(&req->r_req_lru_item, &osdc->req_notarget); | ||
858 | } | 1002 | } |
859 | err = 1; /* osd or pg changed */ | 1003 | err = 1; /* osd or pg changed */ |
860 | 1004 | ||
@@ -869,16 +1013,6 @@ static int __send_request(struct ceph_osd_client *osdc, | |||
869 | struct ceph_osd_request *req) | 1013 | struct ceph_osd_request *req) |
870 | { | 1014 | { |
871 | struct ceph_osd_request_head *reqhead; | 1015 | struct ceph_osd_request_head *reqhead; |
872 | int err; | ||
873 | |||
874 | err = __map_osds(osdc, req); | ||
875 | if (err < 0) | ||
876 | return err; | ||
877 | if (req->r_osd == NULL) { | ||
878 | dout("send_request %p no up osds in pg\n", req); | ||
879 | ceph_monc_request_next_osdmap(&osdc->client->monc); | ||
880 | return 0; | ||
881 | } | ||
882 | 1016 | ||
883 | dout("send_request %p tid %llu to osd%d flags %d\n", | 1017 | dout("send_request %p tid %llu to osd%d flags %d\n", |
884 | req, req->r_tid, req->r_osd->o_osd, req->r_flags); | 1018 | req, req->r_tid, req->r_osd->o_osd, req->r_flags); |
@@ -898,6 +1032,21 @@ static int __send_request(struct ceph_osd_client *osdc, | |||
898 | } | 1032 | } |
899 | 1033 | ||
900 | /* | 1034 | /* |
1035 | * Send any requests in the queue (req_unsent). | ||
1036 | */ | ||
1037 | static void send_queued(struct ceph_osd_client *osdc) | ||
1038 | { | ||
1039 | struct ceph_osd_request *req, *tmp; | ||
1040 | |||
1041 | dout("send_queued\n"); | ||
1042 | mutex_lock(&osdc->request_mutex); | ||
1043 | list_for_each_entry_safe(req, tmp, &osdc->req_unsent, r_req_lru_item) { | ||
1044 | __send_request(osdc, req); | ||
1045 | } | ||
1046 | mutex_unlock(&osdc->request_mutex); | ||
1047 | } | ||
1048 | |||
1049 | /* | ||
901 | * Timeout callback, called every N seconds when 1 or more osd | 1050 | * Timeout callback, called every N seconds when 1 or more osd |
902 | * requests has been active for more than N seconds. When this | 1051 | * requests has been active for more than N seconds. When this |
903 | * happens, we ping all OSDs with requests who have timed out to | 1052 | * happens, we ping all OSDs with requests who have timed out to |
@@ -916,30 +1065,13 @@ static void handle_timeout(struct work_struct *work) | |||
916 | unsigned long keepalive = | 1065 | unsigned long keepalive = |
917 | osdc->client->options->osd_keepalive_timeout * HZ; | 1066 | osdc->client->options->osd_keepalive_timeout * HZ; |
918 | unsigned long last_stamp = 0; | 1067 | unsigned long last_stamp = 0; |
919 | struct rb_node *p; | ||
920 | struct list_head slow_osds; | 1068 | struct list_head slow_osds; |
921 | |||
922 | dout("timeout\n"); | 1069 | dout("timeout\n"); |
923 | down_read(&osdc->map_sem); | 1070 | down_read(&osdc->map_sem); |
924 | 1071 | ||
925 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1072 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
926 | 1073 | ||
927 | mutex_lock(&osdc->request_mutex); | 1074 | mutex_lock(&osdc->request_mutex); |
928 | for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { | ||
929 | req = rb_entry(p, struct ceph_osd_request, r_node); | ||
930 | |||
931 | if (req->r_resend) { | ||
932 | int err; | ||
933 | |||
934 | dout("osdc resending prev failed %lld\n", req->r_tid); | ||
935 | err = __send_request(osdc, req); | ||
936 | if (err) | ||
937 | dout("osdc failed again on %lld\n", req->r_tid); | ||
938 | else | ||
939 | req->r_resend = false; | ||
940 | continue; | ||
941 | } | ||
942 | } | ||
943 | 1075 | ||
944 | /* | 1076 | /* |
945 | * reset osds that appear to be _really_ unresponsive. this | 1077 | * reset osds that appear to be _really_ unresponsive. this |
@@ -963,7 +1095,7 @@ static void handle_timeout(struct work_struct *work) | |||
963 | BUG_ON(!osd); | 1095 | BUG_ON(!osd); |
964 | pr_warning(" tid %llu timed out on osd%d, will reset osd\n", | 1096 | pr_warning(" tid %llu timed out on osd%d, will reset osd\n", |
965 | req->r_tid, osd->o_osd); | 1097 | req->r_tid, osd->o_osd); |
966 | __kick_requests(osdc, osd); | 1098 | __kick_osd_requests(osdc, osd); |
967 | } | 1099 | } |
968 | 1100 | ||
969 | /* | 1101 | /* |
@@ -991,7 +1123,7 @@ static void handle_timeout(struct work_struct *work) | |||
991 | 1123 | ||
992 | __schedule_osd_timeout(osdc); | 1124 | __schedule_osd_timeout(osdc); |
993 | mutex_unlock(&osdc->request_mutex); | 1125 | mutex_unlock(&osdc->request_mutex); |
994 | 1126 | send_queued(osdc); | |
995 | up_read(&osdc->map_sem); | 1127 | up_read(&osdc->map_sem); |
996 | } | 1128 | } |
997 | 1129 | ||
@@ -1035,7 +1167,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
1035 | numops * sizeof(struct ceph_osd_op)) | 1167 | numops * sizeof(struct ceph_osd_op)) |
1036 | goto bad; | 1168 | goto bad; |
1037 | dout("handle_reply %p tid %llu result %d\n", msg, tid, (int)result); | 1169 | dout("handle_reply %p tid %llu result %d\n", msg, tid, (int)result); |
1038 | |||
1039 | /* lookup */ | 1170 | /* lookup */ |
1040 | mutex_lock(&osdc->request_mutex); | 1171 | mutex_lock(&osdc->request_mutex); |
1041 | req = __lookup_request(osdc, tid); | 1172 | req = __lookup_request(osdc, tid); |
@@ -1079,6 +1210,9 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
1079 | 1210 | ||
1080 | dout("handle_reply tid %llu flags %d\n", tid, flags); | 1211 | dout("handle_reply tid %llu flags %d\n", tid, flags); |
1081 | 1212 | ||
1213 | if (req->r_linger && (flags & CEPH_OSD_FLAG_ONDISK)) | ||
1214 | __register_linger_request(osdc, req); | ||
1215 | |||
1082 | /* either this is a read, or we got the safe response */ | 1216 | /* either this is a read, or we got the safe response */ |
1083 | if (result < 0 || | 1217 | if (result < 0 || |
1084 | (flags & CEPH_OSD_FLAG_ONDISK) || | 1218 | (flags & CEPH_OSD_FLAG_ONDISK) || |
@@ -1099,6 +1233,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
1099 | } | 1233 | } |
1100 | 1234 | ||
1101 | done: | 1235 | done: |
1236 | dout("req=%p req->r_linger=%d\n", req, req->r_linger); | ||
1102 | ceph_osdc_put_request(req); | 1237 | ceph_osdc_put_request(req); |
1103 | return; | 1238 | return; |
1104 | 1239 | ||
@@ -1109,108 +1244,83 @@ bad: | |||
1109 | ceph_msg_dump(msg); | 1244 | ceph_msg_dump(msg); |
1110 | } | 1245 | } |
1111 | 1246 | ||
1112 | 1247 | static void reset_changed_osds(struct ceph_osd_client *osdc) | |
1113 | static int __kick_requests(struct ceph_osd_client *osdc, | ||
1114 | struct ceph_osd *kickosd) | ||
1115 | { | 1248 | { |
1116 | struct ceph_osd_request *req; | ||
1117 | struct rb_node *p, *n; | 1249 | struct rb_node *p, *n; |
1118 | int needmap = 0; | ||
1119 | int err; | ||
1120 | 1250 | ||
1121 | dout("kick_requests osd%d\n", kickosd ? kickosd->o_osd : -1); | 1251 | for (p = rb_first(&osdc->osds); p; p = n) { |
1122 | if (kickosd) { | 1252 | struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node); |
1123 | err = __reset_osd(osdc, kickosd); | 1253 | |
1124 | if (err == -EAGAIN) | 1254 | n = rb_next(p); |
1125 | return 1; | 1255 | if (!ceph_osd_is_up(osdc->osdmap, osd->o_osd) || |
1126 | } else { | 1256 | memcmp(&osd->o_con.peer_addr, |
1127 | for (p = rb_first(&osdc->osds); p; p = n) { | 1257 | ceph_osd_addr(osdc->osdmap, |
1128 | struct ceph_osd *osd = | 1258 | osd->o_osd), |
1129 | rb_entry(p, struct ceph_osd, o_node); | 1259 | sizeof(struct ceph_entity_addr)) != 0) |
1130 | 1260 | __reset_osd(osdc, osd); | |
1131 | n = rb_next(p); | ||
1132 | if (!ceph_osd_is_up(osdc->osdmap, osd->o_osd) || | ||
1133 | memcmp(&osd->o_con.peer_addr, | ||
1134 | ceph_osd_addr(osdc->osdmap, | ||
1135 | osd->o_osd), | ||
1136 | sizeof(struct ceph_entity_addr)) != 0) | ||
1137 | __reset_osd(osdc, osd); | ||
1138 | } | ||
1139 | } | 1261 | } |
1262 | } | ||
1263 | |||
1264 | /* | ||
1265 | * Requeue requests whose mapping to an OSD has changed. If requests map to | ||
1266 | * no osd, request a new map. | ||
1267 | * | ||
1268 | * Caller should hold map_sem for read and request_mutex. | ||
1269 | */ | ||
1270 | static void kick_requests(struct ceph_osd_client *osdc) | ||
1271 | { | ||
1272 | struct ceph_osd_request *req, *nreq; | ||
1273 | struct rb_node *p; | ||
1274 | int needmap = 0; | ||
1275 | int err; | ||
1140 | 1276 | ||
1277 | dout("kick_requests\n"); | ||
1278 | mutex_lock(&osdc->request_mutex); | ||
1141 | for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { | 1279 | for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { |
1142 | req = rb_entry(p, struct ceph_osd_request, r_node); | 1280 | req = rb_entry(p, struct ceph_osd_request, r_node); |
1143 | 1281 | err = __map_request(osdc, req); | |
1144 | if (req->r_resend) { | 1282 | if (err < 0) |
1145 | dout(" r_resend set on tid %llu\n", req->r_tid); | 1283 | continue; /* error */ |
1146 | __cancel_request(req); | 1284 | if (req->r_osd == NULL) { |
1147 | goto kick; | 1285 | dout("%p tid %llu maps to no osd\n", req, req->r_tid); |
1148 | } | 1286 | needmap++; /* request a newer map */ |
1149 | if (req->r_osd && kickosd == req->r_osd) { | 1287 | } else if (err > 0) { |
1150 | __cancel_request(req); | 1288 | dout("%p tid %llu requeued on osd%d\n", req, req->r_tid, |
1151 | goto kick; | 1289 | req->r_osd ? req->r_osd->o_osd : -1); |
1290 | if (!req->r_linger) | ||
1291 | req->r_flags |= CEPH_OSD_FLAG_RETRY; | ||
1152 | } | 1292 | } |
1293 | } | ||
1153 | 1294 | ||
1154 | err = __map_osds(osdc, req); | 1295 | list_for_each_entry_safe(req, nreq, &osdc->req_linger, |
1296 | r_linger_item) { | ||
1297 | dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); | ||
1298 | |||
1299 | err = __map_request(osdc, req); | ||
1155 | if (err == 0) | 1300 | if (err == 0) |
1156 | continue; /* no change */ | 1301 | continue; /* no change and no osd was specified */ |
1157 | if (err < 0) { | 1302 | if (err < 0) |
1158 | /* | 1303 | continue; /* hrm! */ |
1159 | * FIXME: really, we should set the request | ||
1160 | * error and fail if this isn't a 'nofail' | ||
1161 | * request, but that's a fair bit more | ||
1162 | * complicated to do. So retry! | ||
1163 | */ | ||
1164 | dout(" setting r_resend on %llu\n", req->r_tid); | ||
1165 | req->r_resend = true; | ||
1166 | continue; | ||
1167 | } | ||
1168 | if (req->r_osd == NULL) { | 1304 | if (req->r_osd == NULL) { |
1169 | dout("tid %llu maps to no valid osd\n", req->r_tid); | 1305 | dout("tid %llu maps to no valid osd\n", req->r_tid); |
1170 | needmap++; /* request a newer map */ | 1306 | needmap++; /* request a newer map */ |
1171 | continue; | 1307 | continue; |
1172 | } | 1308 | } |
1173 | 1309 | ||
1174 | kick: | 1310 | dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, |
1175 | dout("kicking %p tid %llu osd%d\n", req, req->r_tid, | ||
1176 | req->r_osd ? req->r_osd->o_osd : -1); | 1311 | req->r_osd ? req->r_osd->o_osd : -1); |
1177 | req->r_flags |= CEPH_OSD_FLAG_RETRY; | 1312 | __unregister_linger_request(osdc, req); |
1178 | err = __send_request(osdc, req); | 1313 | __register_request(osdc, req); |
1179 | if (err) { | ||
1180 | dout(" setting r_resend on %llu\n", req->r_tid); | ||
1181 | req->r_resend = true; | ||
1182 | } | ||
1183 | } | 1314 | } |
1184 | |||
1185 | return needmap; | ||
1186 | } | ||
1187 | |||
1188 | /* | ||
1189 | * Resubmit osd requests whose osd or osd address has changed. Request | ||
1190 | * a new osd map if osds are down, or we are otherwise unable to determine | ||
1191 | * how to direct a request. | ||
1192 | * | ||
1193 | * Close connections to down osds. | ||
1194 | * | ||
1195 | * If @who is specified, resubmit requests for that specific osd. | ||
1196 | * | ||
1197 | * Caller should hold map_sem for read and request_mutex. | ||
1198 | */ | ||
1199 | static void kick_requests(struct ceph_osd_client *osdc, | ||
1200 | struct ceph_osd *kickosd) | ||
1201 | { | ||
1202 | int needmap; | ||
1203 | |||
1204 | mutex_lock(&osdc->request_mutex); | ||
1205 | needmap = __kick_requests(osdc, kickosd); | ||
1206 | mutex_unlock(&osdc->request_mutex); | 1315 | mutex_unlock(&osdc->request_mutex); |
1207 | 1316 | ||
1208 | if (needmap) { | 1317 | if (needmap) { |
1209 | dout("%d requests for down osds, need new map\n", needmap); | 1318 | dout("%d requests for down osds, need new map\n", needmap); |
1210 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1319 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
1211 | } | 1320 | } |
1212 | |||
1213 | } | 1321 | } |
1322 | |||
1323 | |||
1214 | /* | 1324 | /* |
1215 | * Process updated osd map. | 1325 | * Process updated osd map. |
1216 | * | 1326 | * |
@@ -1263,6 +1373,8 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1263 | ceph_osdmap_destroy(osdc->osdmap); | 1373 | ceph_osdmap_destroy(osdc->osdmap); |
1264 | osdc->osdmap = newmap; | 1374 | osdc->osdmap = newmap; |
1265 | } | 1375 | } |
1376 | kick_requests(osdc); | ||
1377 | reset_changed_osds(osdc); | ||
1266 | } else { | 1378 | } else { |
1267 | dout("ignoring incremental map %u len %d\n", | 1379 | dout("ignoring incremental map %u len %d\n", |
1268 | epoch, maplen); | 1380 | epoch, maplen); |
@@ -1300,6 +1412,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1300 | osdc->osdmap = newmap; | 1412 | osdc->osdmap = newmap; |
1301 | if (oldmap) | 1413 | if (oldmap) |
1302 | ceph_osdmap_destroy(oldmap); | 1414 | ceph_osdmap_destroy(oldmap); |
1415 | kick_requests(osdc); | ||
1303 | } | 1416 | } |
1304 | p += maplen; | 1417 | p += maplen; |
1305 | nr_maps--; | 1418 | nr_maps--; |
@@ -1308,8 +1421,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1308 | done: | 1421 | done: |
1309 | downgrade_write(&osdc->map_sem); | 1422 | downgrade_write(&osdc->map_sem); |
1310 | ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch); | 1423 | ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch); |
1311 | if (newmap) | 1424 | send_queued(osdc); |
1312 | kick_requests(osdc, NULL); | ||
1313 | up_read(&osdc->map_sem); | 1425 | up_read(&osdc->map_sem); |
1314 | wake_up_all(&osdc->client->auth_wq); | 1426 | wake_up_all(&osdc->client->auth_wq); |
1315 | return; | 1427 | return; |
@@ -1322,6 +1434,223 @@ bad: | |||
1322 | } | 1434 | } |
1323 | 1435 | ||
1324 | /* | 1436 | /* |
1437 | * watch/notify callback event infrastructure | ||
1438 | * | ||
1439 | * These callbacks are used both for watch and notify operations. | ||
1440 | */ | ||
1441 | static void __release_event(struct kref *kref) | ||
1442 | { | ||
1443 | struct ceph_osd_event *event = | ||
1444 | container_of(kref, struct ceph_osd_event, kref); | ||
1445 | |||
1446 | dout("__release_event %p\n", event); | ||
1447 | kfree(event); | ||
1448 | } | ||
1449 | |||
1450 | static void get_event(struct ceph_osd_event *event) | ||
1451 | { | ||
1452 | kref_get(&event->kref); | ||
1453 | } | ||
1454 | |||
1455 | void ceph_osdc_put_event(struct ceph_osd_event *event) | ||
1456 | { | ||
1457 | kref_put(&event->kref, __release_event); | ||
1458 | } | ||
1459 | EXPORT_SYMBOL(ceph_osdc_put_event); | ||
1460 | |||
1461 | static void __insert_event(struct ceph_osd_client *osdc, | ||
1462 | struct ceph_osd_event *new) | ||
1463 | { | ||
1464 | struct rb_node **p = &osdc->event_tree.rb_node; | ||
1465 | struct rb_node *parent = NULL; | ||
1466 | struct ceph_osd_event *event = NULL; | ||
1467 | |||
1468 | while (*p) { | ||
1469 | parent = *p; | ||
1470 | event = rb_entry(parent, struct ceph_osd_event, node); | ||
1471 | if (new->cookie < event->cookie) | ||
1472 | p = &(*p)->rb_left; | ||
1473 | else if (new->cookie > event->cookie) | ||
1474 | p = &(*p)->rb_right; | ||
1475 | else | ||
1476 | BUG(); | ||
1477 | } | ||
1478 | |||
1479 | rb_link_node(&new->node, parent, p); | ||
1480 | rb_insert_color(&new->node, &osdc->event_tree); | ||
1481 | } | ||
1482 | |||
1483 | static struct ceph_osd_event *__find_event(struct ceph_osd_client *osdc, | ||
1484 | u64 cookie) | ||
1485 | { | ||
1486 | struct rb_node **p = &osdc->event_tree.rb_node; | ||
1487 | struct rb_node *parent = NULL; | ||
1488 | struct ceph_osd_event *event = NULL; | ||
1489 | |||
1490 | while (*p) { | ||
1491 | parent = *p; | ||
1492 | event = rb_entry(parent, struct ceph_osd_event, node); | ||
1493 | if (cookie < event->cookie) | ||
1494 | p = &(*p)->rb_left; | ||
1495 | else if (cookie > event->cookie) | ||
1496 | p = &(*p)->rb_right; | ||
1497 | else | ||
1498 | return event; | ||
1499 | } | ||
1500 | return NULL; | ||
1501 | } | ||
1502 | |||
1503 | static void __remove_event(struct ceph_osd_event *event) | ||
1504 | { | ||
1505 | struct ceph_osd_client *osdc = event->osdc; | ||
1506 | |||
1507 | if (!RB_EMPTY_NODE(&event->node)) { | ||
1508 | dout("__remove_event removed %p\n", event); | ||
1509 | rb_erase(&event->node, &osdc->event_tree); | ||
1510 | ceph_osdc_put_event(event); | ||
1511 | } else { | ||
1512 | dout("__remove_event didn't remove %p\n", event); | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | int ceph_osdc_create_event(struct ceph_osd_client *osdc, | ||
1517 | void (*event_cb)(u64, u64, u8, void *), | ||
1518 | int one_shot, void *data, | ||
1519 | struct ceph_osd_event **pevent) | ||
1520 | { | ||
1521 | struct ceph_osd_event *event; | ||
1522 | |||
1523 | event = kmalloc(sizeof(*event), GFP_NOIO); | ||
1524 | if (!event) | ||
1525 | return -ENOMEM; | ||
1526 | |||
1527 | dout("create_event %p\n", event); | ||
1528 | event->cb = event_cb; | ||
1529 | event->one_shot = one_shot; | ||
1530 | event->data = data; | ||
1531 | event->osdc = osdc; | ||
1532 | INIT_LIST_HEAD(&event->osd_node); | ||
1533 | kref_init(&event->kref); /* one ref for us */ | ||
1534 | kref_get(&event->kref); /* one ref for the caller */ | ||
1535 | init_completion(&event->completion); | ||
1536 | |||
1537 | spin_lock(&osdc->event_lock); | ||
1538 | event->cookie = ++osdc->event_count; | ||
1539 | __insert_event(osdc, event); | ||
1540 | spin_unlock(&osdc->event_lock); | ||
1541 | |||
1542 | *pevent = event; | ||
1543 | return 0; | ||
1544 | } | ||
1545 | EXPORT_SYMBOL(ceph_osdc_create_event); | ||
1546 | |||
1547 | void ceph_osdc_cancel_event(struct ceph_osd_event *event) | ||
1548 | { | ||
1549 | struct ceph_osd_client *osdc = event->osdc; | ||
1550 | |||
1551 | dout("cancel_event %p\n", event); | ||
1552 | spin_lock(&osdc->event_lock); | ||
1553 | __remove_event(event); | ||
1554 | spin_unlock(&osdc->event_lock); | ||
1555 | ceph_osdc_put_event(event); /* caller's */ | ||
1556 | } | ||
1557 | EXPORT_SYMBOL(ceph_osdc_cancel_event); | ||
1558 | |||
1559 | |||
1560 | static void do_event_work(struct work_struct *work) | ||
1561 | { | ||
1562 | struct ceph_osd_event_work *event_work = | ||
1563 | container_of(work, struct ceph_osd_event_work, work); | ||
1564 | struct ceph_osd_event *event = event_work->event; | ||
1565 | u64 ver = event_work->ver; | ||
1566 | u64 notify_id = event_work->notify_id; | ||
1567 | u8 opcode = event_work->opcode; | ||
1568 | |||
1569 | dout("do_event_work completing %p\n", event); | ||
1570 | event->cb(ver, notify_id, opcode, event->data); | ||
1571 | complete(&event->completion); | ||
1572 | dout("do_event_work completed %p\n", event); | ||
1573 | ceph_osdc_put_event(event); | ||
1574 | kfree(event_work); | ||
1575 | } | ||
1576 | |||
1577 | |||
1578 | /* | ||
1579 | * Process osd watch notifications | ||
1580 | */ | ||
1581 | void handle_watch_notify(struct ceph_osd_client *osdc, struct ceph_msg *msg) | ||
1582 | { | ||
1583 | void *p, *end; | ||
1584 | u8 proto_ver; | ||
1585 | u64 cookie, ver, notify_id; | ||
1586 | u8 opcode; | ||
1587 | struct ceph_osd_event *event; | ||
1588 | struct ceph_osd_event_work *event_work; | ||
1589 | |||
1590 | p = msg->front.iov_base; | ||
1591 | end = p + msg->front.iov_len; | ||
1592 | |||
1593 | ceph_decode_8_safe(&p, end, proto_ver, bad); | ||
1594 | ceph_decode_8_safe(&p, end, opcode, bad); | ||
1595 | ceph_decode_64_safe(&p, end, cookie, bad); | ||
1596 | ceph_decode_64_safe(&p, end, ver, bad); | ||
1597 | ceph_decode_64_safe(&p, end, notify_id, bad); | ||
1598 | |||
1599 | spin_lock(&osdc->event_lock); | ||
1600 | event = __find_event(osdc, cookie); | ||
1601 | if (event) { | ||
1602 | get_event(event); | ||
1603 | if (event->one_shot) | ||
1604 | __remove_event(event); | ||
1605 | } | ||
1606 | spin_unlock(&osdc->event_lock); | ||
1607 | dout("handle_watch_notify cookie %lld ver %lld event %p\n", | ||
1608 | cookie, ver, event); | ||
1609 | if (event) { | ||
1610 | event_work = kmalloc(sizeof(*event_work), GFP_NOIO); | ||
1611 | if (!event_work) { | ||
1612 | dout("ERROR: could not allocate event_work\n"); | ||
1613 | goto done_err; | ||
1614 | } | ||
1615 | INIT_WORK(&event_work->work, do_event_work); | ||
1616 | event_work->event = event; | ||
1617 | event_work->ver = ver; | ||
1618 | event_work->notify_id = notify_id; | ||
1619 | event_work->opcode = opcode; | ||
1620 | if (!queue_work(osdc->notify_wq, &event_work->work)) { | ||
1621 | dout("WARNING: failed to queue notify event work\n"); | ||
1622 | goto done_err; | ||
1623 | } | ||
1624 | } | ||
1625 | |||
1626 | return; | ||
1627 | |||
1628 | done_err: | ||
1629 | complete(&event->completion); | ||
1630 | ceph_osdc_put_event(event); | ||
1631 | return; | ||
1632 | |||
1633 | bad: | ||
1634 | pr_err("osdc handle_watch_notify corrupt msg\n"); | ||
1635 | return; | ||
1636 | } | ||
1637 | |||
1638 | int ceph_osdc_wait_event(struct ceph_osd_event *event, unsigned long timeout) | ||
1639 | { | ||
1640 | int err; | ||
1641 | |||
1642 | dout("wait_event %p\n", event); | ||
1643 | err = wait_for_completion_interruptible_timeout(&event->completion, | ||
1644 | timeout * HZ); | ||
1645 | ceph_osdc_put_event(event); | ||
1646 | if (err > 0) | ||
1647 | err = 0; | ||
1648 | dout("wait_event %p returns %d\n", event, err); | ||
1649 | return err; | ||
1650 | } | ||
1651 | EXPORT_SYMBOL(ceph_osdc_wait_event); | ||
1652 | |||
1653 | /* | ||
1325 | * Register request, send initial attempt. | 1654 | * Register request, send initial attempt. |
1326 | */ | 1655 | */ |
1327 | int ceph_osdc_start_request(struct ceph_osd_client *osdc, | 1656 | int ceph_osdc_start_request(struct ceph_osd_client *osdc, |
@@ -1347,18 +1676,27 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1347 | * the request still han't been touched yet. | 1676 | * the request still han't been touched yet. |
1348 | */ | 1677 | */ |
1349 | if (req->r_sent == 0) { | 1678 | if (req->r_sent == 0) { |
1350 | rc = __send_request(osdc, req); | 1679 | rc = __map_request(osdc, req); |
1351 | if (rc) { | 1680 | if (rc < 0) |
1352 | if (nofail) { | 1681 | goto out_unlock; |
1353 | dout("osdc_start_request failed send, " | 1682 | if (req->r_osd == NULL) { |
1354 | " marking %lld\n", req->r_tid); | 1683 | dout("send_request %p no up osds in pg\n", req); |
1355 | req->r_resend = true; | 1684 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
1356 | rc = 0; | 1685 | } else { |
1357 | } else { | 1686 | rc = __send_request(osdc, req); |
1358 | __unregister_request(osdc, req); | 1687 | if (rc) { |
1688 | if (nofail) { | ||
1689 | dout("osdc_start_request failed send, " | ||
1690 | " will retry %lld\n", req->r_tid); | ||
1691 | rc = 0; | ||
1692 | } else { | ||
1693 | __unregister_request(osdc, req); | ||
1694 | } | ||
1359 | } | 1695 | } |
1360 | } | 1696 | } |
1361 | } | 1697 | } |
1698 | |||
1699 | out_unlock: | ||
1362 | mutex_unlock(&osdc->request_mutex); | 1700 | mutex_unlock(&osdc->request_mutex); |
1363 | up_read(&osdc->map_sem); | 1701 | up_read(&osdc->map_sem); |
1364 | return rc; | 1702 | return rc; |
@@ -1441,9 +1779,15 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) | |||
1441 | INIT_LIST_HEAD(&osdc->osd_lru); | 1779 | INIT_LIST_HEAD(&osdc->osd_lru); |
1442 | osdc->requests = RB_ROOT; | 1780 | osdc->requests = RB_ROOT; |
1443 | INIT_LIST_HEAD(&osdc->req_lru); | 1781 | INIT_LIST_HEAD(&osdc->req_lru); |
1782 | INIT_LIST_HEAD(&osdc->req_unsent); | ||
1783 | INIT_LIST_HEAD(&osdc->req_notarget); | ||
1784 | INIT_LIST_HEAD(&osdc->req_linger); | ||
1444 | osdc->num_requests = 0; | 1785 | osdc->num_requests = 0; |
1445 | INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout); | 1786 | INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout); |
1446 | INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout); | 1787 | INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout); |
1788 | spin_lock_init(&osdc->event_lock); | ||
1789 | osdc->event_tree = RB_ROOT; | ||
1790 | osdc->event_count = 0; | ||
1447 | 1791 | ||
1448 | schedule_delayed_work(&osdc->osds_timeout_work, | 1792 | schedule_delayed_work(&osdc->osds_timeout_work, |
1449 | round_jiffies_relative(osdc->client->options->osd_idle_ttl * HZ)); | 1793 | round_jiffies_relative(osdc->client->options->osd_idle_ttl * HZ)); |
@@ -1463,6 +1807,13 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) | |||
1463 | "osd_op_reply"); | 1807 | "osd_op_reply"); |
1464 | if (err < 0) | 1808 | if (err < 0) |
1465 | goto out_msgpool; | 1809 | goto out_msgpool; |
1810 | |||
1811 | osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify"); | ||
1812 | if (IS_ERR(osdc->notify_wq)) { | ||
1813 | err = PTR_ERR(osdc->notify_wq); | ||
1814 | osdc->notify_wq = NULL; | ||
1815 | goto out_msgpool; | ||
1816 | } | ||
1466 | return 0; | 1817 | return 0; |
1467 | 1818 | ||
1468 | out_msgpool: | 1819 | out_msgpool: |
@@ -1476,6 +1827,8 @@ EXPORT_SYMBOL(ceph_osdc_init); | |||
1476 | 1827 | ||
1477 | void ceph_osdc_stop(struct ceph_osd_client *osdc) | 1828 | void ceph_osdc_stop(struct ceph_osd_client *osdc) |
1478 | { | 1829 | { |
1830 | flush_workqueue(osdc->notify_wq); | ||
1831 | destroy_workqueue(osdc->notify_wq); | ||
1479 | cancel_delayed_work_sync(&osdc->timeout_work); | 1832 | cancel_delayed_work_sync(&osdc->timeout_work); |
1480 | cancel_delayed_work_sync(&osdc->osds_timeout_work); | 1833 | cancel_delayed_work_sync(&osdc->osds_timeout_work); |
1481 | if (osdc->osdmap) { | 1834 | if (osdc->osdmap) { |
@@ -1483,6 +1836,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc) | |||
1483 | osdc->osdmap = NULL; | 1836 | osdc->osdmap = NULL; |
1484 | } | 1837 | } |
1485 | remove_old_osds(osdc, 1); | 1838 | remove_old_osds(osdc, 1); |
1839 | WARN_ON(!RB_EMPTY_ROOT(&osdc->osds)); | ||
1486 | mempool_destroy(osdc->req_mempool); | 1840 | mempool_destroy(osdc->req_mempool); |
1487 | ceph_msgpool_destroy(&osdc->msgpool_op); | 1841 | ceph_msgpool_destroy(&osdc->msgpool_op); |
1488 | ceph_msgpool_destroy(&osdc->msgpool_op_reply); | 1842 | ceph_msgpool_destroy(&osdc->msgpool_op_reply); |
@@ -1591,6 +1945,9 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) | |||
1591 | case CEPH_MSG_OSD_OPREPLY: | 1945 | case CEPH_MSG_OSD_OPREPLY: |
1592 | handle_reply(osdc, msg, con); | 1946 | handle_reply(osdc, msg, con); |
1593 | break; | 1947 | break; |
1948 | case CEPH_MSG_WATCH_NOTIFY: | ||
1949 | handle_watch_notify(osdc, msg); | ||
1950 | break; | ||
1594 | 1951 | ||
1595 | default: | 1952 | default: |
1596 | pr_err("received unknown message type %d %s\n", type, | 1953 | pr_err("received unknown message type %d %s\n", type, |
@@ -1684,6 +2041,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, | |||
1684 | 2041 | ||
1685 | switch (type) { | 2042 | switch (type) { |
1686 | case CEPH_MSG_OSD_MAP: | 2043 | case CEPH_MSG_OSD_MAP: |
2044 | case CEPH_MSG_WATCH_NOTIFY: | ||
1687 | return ceph_msg_new(type, front, GFP_NOFS); | 2045 | return ceph_msg_new(type, front, GFP_NOFS); |
1688 | case CEPH_MSG_OSD_OPREPLY: | 2046 | case CEPH_MSG_OSD_OPREPLY: |
1689 | return get_reply(con, hdr, skip); | 2047 | return get_reply(con, hdr, skip); |
diff --git a/net/core/dev.c b/net/core/dev.c index 0b88eba97dab..b624fe4d9bd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev) | |||
1140 | 1140 | ||
1141 | ASSERT_RTNL(); | 1141 | ASSERT_RTNL(); |
1142 | 1142 | ||
1143 | /* | ||
1144 | * Is it even present? | ||
1145 | */ | ||
1146 | if (!netif_device_present(dev)) | 1143 | if (!netif_device_present(dev)) |
1147 | return -ENODEV; | 1144 | return -ENODEV; |
1148 | 1145 | ||
@@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev) | |||
1151 | if (ret) | 1148 | if (ret) |
1152 | return ret; | 1149 | return ret; |
1153 | 1150 | ||
1154 | /* | ||
1155 | * Call device private open method | ||
1156 | */ | ||
1157 | set_bit(__LINK_STATE_START, &dev->state); | 1151 | set_bit(__LINK_STATE_START, &dev->state); |
1158 | 1152 | ||
1159 | if (ops->ndo_validate_addr) | 1153 | if (ops->ndo_validate_addr) |
@@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev) | |||
1162 | if (!ret && ops->ndo_open) | 1156 | if (!ret && ops->ndo_open) |
1163 | ret = ops->ndo_open(dev); | 1157 | ret = ops->ndo_open(dev); |
1164 | 1158 | ||
1165 | /* | ||
1166 | * If it went open OK then: | ||
1167 | */ | ||
1168 | |||
1169 | if (ret) | 1159 | if (ret) |
1170 | clear_bit(__LINK_STATE_START, &dev->state); | 1160 | clear_bit(__LINK_STATE_START, &dev->state); |
1171 | else { | 1161 | else { |
1172 | /* | ||
1173 | * Set the flags. | ||
1174 | */ | ||
1175 | dev->flags |= IFF_UP; | 1162 | dev->flags |= IFF_UP; |
1176 | |||
1177 | /* | ||
1178 | * Enable NET_DMA | ||
1179 | */ | ||
1180 | net_dmaengine_get(); | 1163 | net_dmaengine_get(); |
1181 | |||
1182 | /* | ||
1183 | * Initialize multicasting status | ||
1184 | */ | ||
1185 | dev_set_rx_mode(dev); | 1164 | dev_set_rx_mode(dev); |
1186 | |||
1187 | /* | ||
1188 | * Wakeup transmit queue engine | ||
1189 | */ | ||
1190 | dev_activate(dev); | 1165 | dev_activate(dev); |
1191 | } | 1166 | } |
1192 | 1167 | ||
@@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev) | |||
1209 | { | 1184 | { |
1210 | int ret; | 1185 | int ret; |
1211 | 1186 | ||
1212 | /* | ||
1213 | * Is it already up? | ||
1214 | */ | ||
1215 | if (dev->flags & IFF_UP) | 1187 | if (dev->flags & IFF_UP) |
1216 | return 0; | 1188 | return 0; |
1217 | 1189 | ||
1218 | /* | ||
1219 | * Open device | ||
1220 | */ | ||
1221 | ret = __dev_open(dev); | 1190 | ret = __dev_open(dev); |
1222 | if (ret < 0) | 1191 | if (ret < 0) |
1223 | return ret; | 1192 | return ret; |
1224 | 1193 | ||
1225 | /* | ||
1226 | * ... and announce new interface. | ||
1227 | */ | ||
1228 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1194 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
1229 | call_netdevice_notifiers(NETDEV_UP, dev); | 1195 | call_netdevice_notifiers(NETDEV_UP, dev); |
1230 | 1196 | ||
@@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head) | |||
1240 | might_sleep(); | 1206 | might_sleep(); |
1241 | 1207 | ||
1242 | list_for_each_entry(dev, head, unreg_list) { | 1208 | list_for_each_entry(dev, head, unreg_list) { |
1243 | /* | ||
1244 | * Tell people we are going down, so that they can | ||
1245 | * prepare to death, when device is still operating. | ||
1246 | */ | ||
1247 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); | 1209 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); |
1248 | 1210 | ||
1249 | clear_bit(__LINK_STATE_START, &dev->state); | 1211 | clear_bit(__LINK_STATE_START, &dev->state); |
@@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head) | |||
1272 | if (ops->ndo_stop) | 1234 | if (ops->ndo_stop) |
1273 | ops->ndo_stop(dev); | 1235 | ops->ndo_stop(dev); |
1274 | 1236 | ||
1275 | /* | ||
1276 | * Device is now down. | ||
1277 | */ | ||
1278 | |||
1279 | dev->flags &= ~IFF_UP; | 1237 | dev->flags &= ~IFF_UP; |
1280 | |||
1281 | /* | ||
1282 | * Shutdown NET_DMA | ||
1283 | */ | ||
1284 | net_dmaengine_put(); | 1238 | net_dmaengine_put(); |
1285 | } | 1239 | } |
1286 | 1240 | ||
@@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head) | |||
1309 | 1263 | ||
1310 | __dev_close_many(head); | 1264 | __dev_close_many(head); |
1311 | 1265 | ||
1312 | /* | ||
1313 | * Tell people we are down | ||
1314 | */ | ||
1315 | list_for_each_entry(dev, head, unreg_list) { | 1266 | list_for_each_entry(dev, head, unreg_list) { |
1316 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1267 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
1317 | call_netdevice_notifiers(NETDEV_DOWN, dev); | 1268 | call_netdevice_notifiers(NETDEV_DOWN, dev); |
@@ -1333,11 +1284,13 @@ static int dev_close_many(struct list_head *head) | |||
1333 | */ | 1284 | */ |
1334 | int dev_close(struct net_device *dev) | 1285 | int dev_close(struct net_device *dev) |
1335 | { | 1286 | { |
1336 | LIST_HEAD(single); | 1287 | if (dev->flags & IFF_UP) { |
1288 | LIST_HEAD(single); | ||
1337 | 1289 | ||
1338 | list_add(&dev->unreg_list, &single); | 1290 | list_add(&dev->unreg_list, &single); |
1339 | dev_close_many(&single); | 1291 | dev_close_many(&single); |
1340 | list_del(&single); | 1292 | list_del(&single); |
1293 | } | ||
1341 | return 0; | 1294 | return 0; |
1342 | } | 1295 | } |
1343 | EXPORT_SYMBOL(dev_close); | 1296 | EXPORT_SYMBOL(dev_close); |
@@ -1353,14 +1306,17 @@ EXPORT_SYMBOL(dev_close); | |||
1353 | */ | 1306 | */ |
1354 | void dev_disable_lro(struct net_device *dev) | 1307 | void dev_disable_lro(struct net_device *dev) |
1355 | { | 1308 | { |
1356 | if (dev->ethtool_ops && dev->ethtool_ops->get_flags && | 1309 | u32 flags; |
1357 | dev->ethtool_ops->set_flags) { | 1310 | |
1358 | u32 flags = dev->ethtool_ops->get_flags(dev); | 1311 | if (dev->ethtool_ops && dev->ethtool_ops->get_flags) |
1359 | if (flags & ETH_FLAG_LRO) { | 1312 | flags = dev->ethtool_ops->get_flags(dev); |
1360 | flags &= ~ETH_FLAG_LRO; | 1313 | else |
1361 | dev->ethtool_ops->set_flags(dev, flags); | 1314 | flags = ethtool_op_get_flags(dev); |
1362 | } | 1315 | |
1363 | } | 1316 | if (!(flags & ETH_FLAG_LRO)) |
1317 | return; | ||
1318 | |||
1319 | __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO); | ||
1364 | WARN_ON(dev->features & NETIF_F_LRO); | 1320 | WARN_ON(dev->features & NETIF_F_LRO); |
1365 | } | 1321 | } |
1366 | EXPORT_SYMBOL(dev_disable_lro); | 1322 | EXPORT_SYMBOL(dev_disable_lro); |
@@ -1368,11 +1324,6 @@ EXPORT_SYMBOL(dev_disable_lro); | |||
1368 | 1324 | ||
1369 | static int dev_boot_phase = 1; | 1325 | static int dev_boot_phase = 1; |
1370 | 1326 | ||
1371 | /* | ||
1372 | * Device change register/unregister. These are not inline or static | ||
1373 | * as we export them to the world. | ||
1374 | */ | ||
1375 | |||
1376 | /** | 1327 | /** |
1377 | * register_netdevice_notifier - register a network notifier block | 1328 | * register_netdevice_notifier - register a network notifier block |
1378 | * @nb: notifier | 1329 | * @nb: notifier |
@@ -1474,6 +1425,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev) | |||
1474 | ASSERT_RTNL(); | 1425 | ASSERT_RTNL(); |
1475 | return raw_notifier_call_chain(&netdev_chain, val, dev); | 1426 | return raw_notifier_call_chain(&netdev_chain, val, dev); |
1476 | } | 1427 | } |
1428 | EXPORT_SYMBOL(call_netdevice_notifiers); | ||
1477 | 1429 | ||
1478 | /* When > 0 there are consumers of rx skb time stamps */ | 1430 | /* When > 0 there are consumers of rx skb time stamps */ |
1479 | static atomic_t netstamp_needed = ATOMIC_INIT(0); | 1431 | static atomic_t netstamp_needed = ATOMIC_INIT(0); |
@@ -1504,6 +1456,27 @@ static inline void net_timestamp_check(struct sk_buff *skb) | |||
1504 | __net_timestamp(skb); | 1456 | __net_timestamp(skb); |
1505 | } | 1457 | } |
1506 | 1458 | ||
1459 | static inline bool is_skb_forwardable(struct net_device *dev, | ||
1460 | struct sk_buff *skb) | ||
1461 | { | ||
1462 | unsigned int len; | ||
1463 | |||
1464 | if (!(dev->flags & IFF_UP)) | ||
1465 | return false; | ||
1466 | |||
1467 | len = dev->mtu + dev->hard_header_len + VLAN_HLEN; | ||
1468 | if (skb->len <= len) | ||
1469 | return true; | ||
1470 | |||
1471 | /* if TSO is enabled, we don't care about the length as the packet | ||
1472 | * could be forwarded without being segmented before | ||
1473 | */ | ||
1474 | if (skb_is_gso(skb)) | ||
1475 | return true; | ||
1476 | |||
1477 | return false; | ||
1478 | } | ||
1479 | |||
1507 | /** | 1480 | /** |
1508 | * dev_forward_skb - loopback an skb to another netif | 1481 | * dev_forward_skb - loopback an skb to another netif |
1509 | * | 1482 | * |
@@ -1527,8 +1500,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | |||
1527 | skb_orphan(skb); | 1500 | skb_orphan(skb); |
1528 | nf_reset(skb); | 1501 | nf_reset(skb); |
1529 | 1502 | ||
1530 | if (unlikely(!(dev->flags & IFF_UP) || | 1503 | if (unlikely(!is_skb_forwardable(dev, skb))) { |
1531 | (skb->len > (dev->mtu + dev->hard_header_len + VLAN_HLEN)))) { | ||
1532 | atomic_long_inc(&dev->rx_dropped); | 1504 | atomic_long_inc(&dev->rx_dropped); |
1533 | kfree_skb(skb); | 1505 | kfree_skb(skb); |
1534 | return NET_RX_DROP; | 1506 | return NET_RX_DROP; |
@@ -2121,7 +2093,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
2121 | u32 features; | 2093 | u32 features; |
2122 | 2094 | ||
2123 | /* | 2095 | /* |
2124 | * If device doesnt need skb->dst, release it right now while | 2096 | * If device doesn't need skb->dst, release it right now while |
2125 | * its hot in this cpu cache | 2097 | * its hot in this cpu cache |
2126 | */ | 2098 | */ |
2127 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 2099 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
@@ -2181,7 +2153,7 @@ gso: | |||
2181 | nskb->next = NULL; | 2153 | nskb->next = NULL; |
2182 | 2154 | ||
2183 | /* | 2155 | /* |
2184 | * If device doesnt need nskb->dst, release it right now while | 2156 | * If device doesn't need nskb->dst, release it right now while |
2185 | * its hot in this cpu cache | 2157 | * its hot in this cpu cache |
2186 | */ | 2158 | */ |
2187 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 2159 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
@@ -3000,8 +2972,8 @@ EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); | |||
3000 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 2972 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
3001 | * a compare and 2 stores extra right now if we dont have it on | 2973 | * a compare and 2 stores extra right now if we dont have it on |
3002 | * but have CONFIG_NET_CLS_ACT | 2974 | * but have CONFIG_NET_CLS_ACT |
3003 | * NOTE: This doesnt stop any functionality; if you dont have | 2975 | * NOTE: This doesn't stop any functionality; if you dont have |
3004 | * the ingress scheduler, you just cant add policies on ingress. | 2976 | * the ingress scheduler, you just can't add policies on ingress. |
3005 | * | 2977 | * |
3006 | */ | 2978 | */ |
3007 | static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq) | 2979 | static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq) |
@@ -3830,7 +3802,7 @@ static void net_rx_action(struct softirq_action *h) | |||
3830 | * with netpoll's poll_napi(). Only the entity which | 3802 | * with netpoll's poll_napi(). Only the entity which |
3831 | * obtains the lock and sees NAPI_STATE_SCHED set will | 3803 | * obtains the lock and sees NAPI_STATE_SCHED set will |
3832 | * actually make the ->poll() call. Therefore we avoid | 3804 | * actually make the ->poll() call. Therefore we avoid |
3833 | * accidently calling ->poll() when NAPI is not scheduled. | 3805 | * accidentally calling ->poll() when NAPI is not scheduled. |
3834 | */ | 3806 | */ |
3835 | work = 0; | 3807 | work = 0; |
3836 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | 3808 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { |
@@ -4803,7 +4775,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm | |||
4803 | * is never reached | 4775 | * is never reached |
4804 | */ | 4776 | */ |
4805 | WARN_ON(1); | 4777 | WARN_ON(1); |
4806 | err = -EINVAL; | 4778 | err = -ENOTTY; |
4807 | break; | 4779 | break; |
4808 | 4780 | ||
4809 | } | 4781 | } |
@@ -5071,7 +5043,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5071 | /* Set the per device memory buffer space. | 5043 | /* Set the per device memory buffer space. |
5072 | * Not applicable in our case */ | 5044 | * Not applicable in our case */ |
5073 | case SIOCSIFLINK: | 5045 | case SIOCSIFLINK: |
5074 | return -EINVAL; | 5046 | return -ENOTTY; |
5075 | 5047 | ||
5076 | /* | 5048 | /* |
5077 | * Unknown or private ioctl. | 5049 | * Unknown or private ioctl. |
@@ -5092,7 +5064,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5092 | /* Take care of Wireless Extensions */ | 5064 | /* Take care of Wireless Extensions */ |
5093 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) | 5065 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) |
5094 | return wext_handle_ioctl(net, &ifr, cmd, arg); | 5066 | return wext_handle_ioctl(net, &ifr, cmd, arg); |
5095 | return -EINVAL; | 5067 | return -ENOTTY; |
5096 | } | 5068 | } |
5097 | } | 5069 | } |
5098 | 5070 | ||
@@ -5214,33 +5186,37 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5214 | /* Fix illegal checksum combinations */ | 5186 | /* Fix illegal checksum combinations */ |
5215 | if ((features & NETIF_F_HW_CSUM) && | 5187 | if ((features & NETIF_F_HW_CSUM) && |
5216 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5188 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5217 | netdev_info(dev, "mixed HW and IP checksum settings.\n"); | 5189 | netdev_warn(dev, "mixed HW and IP checksum settings.\n"); |
5218 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); | 5190 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM); |
5219 | } | 5191 | } |
5220 | 5192 | ||
5221 | if ((features & NETIF_F_NO_CSUM) && | 5193 | if ((features & NETIF_F_NO_CSUM) && |
5222 | (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5194 | (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5223 | netdev_info(dev, "mixed no checksumming and other settings.\n"); | 5195 | netdev_warn(dev, "mixed no checksumming and other settings.\n"); |
5224 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); | 5196 | features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); |
5225 | } | 5197 | } |
5226 | 5198 | ||
5227 | /* Fix illegal SG+CSUM combinations. */ | 5199 | /* Fix illegal SG+CSUM combinations. */ |
5228 | if ((features & NETIF_F_SG) && | 5200 | if ((features & NETIF_F_SG) && |
5229 | !(features & NETIF_F_ALL_CSUM)) { | 5201 | !(features & NETIF_F_ALL_CSUM)) { |
5230 | netdev_info(dev, | 5202 | netdev_dbg(dev, |
5231 | "Dropping NETIF_F_SG since no checksum feature.\n"); | 5203 | "Dropping NETIF_F_SG since no checksum feature.\n"); |
5232 | features &= ~NETIF_F_SG; | 5204 | features &= ~NETIF_F_SG; |
5233 | } | 5205 | } |
5234 | 5206 | ||
5235 | /* TSO requires that SG is present as well. */ | 5207 | /* TSO requires that SG is present as well. */ |
5236 | if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) { | 5208 | if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { |
5237 | netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n"); | 5209 | netdev_dbg(dev, "Dropping TSO features since no SG feature.\n"); |
5238 | features &= ~NETIF_F_TSO; | 5210 | features &= ~NETIF_F_ALL_TSO; |
5239 | } | 5211 | } |
5240 | 5212 | ||
5213 | /* TSO ECN requires that TSO is present as well. */ | ||
5214 | if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN) | ||
5215 | features &= ~NETIF_F_TSO_ECN; | ||
5216 | |||
5241 | /* Software GSO depends on SG. */ | 5217 | /* Software GSO depends on SG. */ |
5242 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { | 5218 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { |
5243 | netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); | 5219 | netdev_dbg(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); |
5244 | features &= ~NETIF_F_GSO; | 5220 | features &= ~NETIF_F_GSO; |
5245 | } | 5221 | } |
5246 | 5222 | ||
@@ -5250,13 +5226,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5250 | if (!((features & NETIF_F_GEN_CSUM) || | 5226 | if (!((features & NETIF_F_GEN_CSUM) || |
5251 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) | 5227 | (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)) |
5252 | == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { | 5228 | == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) { |
5253 | netdev_info(dev, | 5229 | netdev_dbg(dev, |
5254 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); | 5230 | "Dropping NETIF_F_UFO since no checksum offload features.\n"); |
5255 | features &= ~NETIF_F_UFO; | 5231 | features &= ~NETIF_F_UFO; |
5256 | } | 5232 | } |
5257 | 5233 | ||
5258 | if (!(features & NETIF_F_SG)) { | 5234 | if (!(features & NETIF_F_SG)) { |
5259 | netdev_info(dev, | 5235 | netdev_dbg(dev, |
5260 | "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n"); | 5236 | "Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n"); |
5261 | features &= ~NETIF_F_UFO; | 5237 | features &= ~NETIF_F_UFO; |
5262 | } | 5238 | } |
@@ -5438,12 +5414,6 @@ int register_netdevice(struct net_device *dev) | |||
5438 | dev->features |= NETIF_F_SOFT_FEATURES; | 5414 | dev->features |= NETIF_F_SOFT_FEATURES; |
5439 | dev->wanted_features = dev->features & dev->hw_features; | 5415 | dev->wanted_features = dev->features & dev->hw_features; |
5440 | 5416 | ||
5441 | /* Avoid warning from netdev_fix_features() for GSO without SG */ | ||
5442 | if (!(dev->wanted_features & NETIF_F_SG)) { | ||
5443 | dev->wanted_features &= ~NETIF_F_GSO; | ||
5444 | dev->features &= ~NETIF_F_GSO; | ||
5445 | } | ||
5446 | |||
5447 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, | 5417 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, |
5448 | * vlan_dev_init() will do the dev->features check, so these features | 5418 | * vlan_dev_init() will do the dev->features check, so these features |
5449 | * are enabled only if supported by underlying device. | 5419 | * are enabled only if supported by underlying device. |
@@ -6366,7 +6336,7 @@ static void __net_exit default_device_exit(struct net *net) | |||
6366 | if (dev->rtnl_link_ops) | 6336 | if (dev->rtnl_link_ops) |
6367 | continue; | 6337 | continue; |
6368 | 6338 | ||
6369 | /* Push remaing network devices to init_net */ | 6339 | /* Push remaining network devices to init_net */ |
6370 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); | 6340 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); |
6371 | err = dev_change_net_namespace(dev, &init_net, fb_name); | 6341 | err = dev_change_net_namespace(dev, &init_net, fb_name); |
6372 | if (err) { | 6342 | if (err) { |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 36e603c78ce9..706502ff64aa 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -350,7 +350,7 @@ static int __init init_net_drop_monitor(void) | |||
350 | struct per_cpu_dm_data *data; | 350 | struct per_cpu_dm_data *data; |
351 | int cpu, rc; | 351 | int cpu, rc; |
352 | 352 | ||
353 | printk(KERN_INFO "Initalizing network drop monitor service\n"); | 353 | printk(KERN_INFO "Initializing network drop monitor service\n"); |
354 | 354 | ||
355 | if (sizeof(void *) > 8) { | 355 | if (sizeof(void *) > 8) { |
356 | printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n"); | 356 | printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n"); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index c1a71bb738da..74ead9eca126 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(ethtool_op_get_flags); | 142 | EXPORT_SYMBOL(ethtool_op_get_flags); |
143 | 143 | ||
144 | /* Check if device can enable (or disable) particular feature coded in "data" | ||
145 | * argument. Flags "supported" describe features that can be toggled by device. | ||
146 | * If feature can not be toggled, it state (enabled or disabled) must match | ||
147 | * hardcoded device features state, otherwise flags are marked as invalid. | ||
148 | */ | ||
149 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported) | ||
150 | { | ||
151 | u32 features = dev->features & flags_dup_features; | ||
152 | /* "data" can contain only flags_dup_features bits, | ||
153 | * see __ethtool_set_flags */ | ||
154 | |||
155 | return (features & ~supported) != (data & ~supported); | ||
156 | } | ||
157 | EXPORT_SYMBOL(ethtool_invalid_flags); | ||
158 | |||
144 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) | 159 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) |
145 | { | 160 | { |
146 | if (data & ~supported) | 161 | if (ethtool_invalid_flags(dev, data, supported)) |
147 | return -EINVAL; | 162 | return -EINVAL; |
148 | 163 | ||
149 | dev->features = ((dev->features & ~flags_dup_features) | | 164 | dev->features = ((dev->features & ~flags_dup_features) | |
@@ -513,7 +528,7 @@ static int ethtool_set_one_feature(struct net_device *dev, | |||
513 | } | 528 | } |
514 | } | 529 | } |
515 | 530 | ||
516 | static int __ethtool_set_flags(struct net_device *dev, u32 data) | 531 | int __ethtool_set_flags(struct net_device *dev, u32 data) |
517 | { | 532 | { |
518 | u32 changed; | 533 | u32 changed; |
519 | 534 | ||
@@ -1457,6 +1472,9 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) | |||
1457 | { | 1472 | { |
1458 | int err; | 1473 | int err; |
1459 | 1474 | ||
1475 | if (!dev->ethtool_ops->set_sg) | ||
1476 | return -EOPNOTSUPP; | ||
1477 | |||
1460 | if (data && !(dev->features & NETIF_F_ALL_CSUM)) | 1478 | if (data && !(dev->features & NETIF_F_ALL_CSUM)) |
1461 | return -EINVAL; | 1479 | return -EINVAL; |
1462 | 1480 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 232b1873bb28..afb8afb066bb 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -425,7 +425,7 @@ EXPORT_SYMBOL(sk_run_filter); | |||
425 | * As we dont want to clear mem[] array for each packet going through | 425 | * As we dont want to clear mem[] array for each packet going through |
426 | * sk_run_filter(), we check that filter loaded by user never try to read | 426 | * sk_run_filter(), we check that filter loaded by user never try to read |
427 | * a cell if not previously written, and we check all branches to be sure | 427 | * a cell if not previously written, and we check all branches to be sure |
428 | * a malicious user doesnt try to abuse us. | 428 | * a malicious user doesn't try to abuse us. |
429 | */ | 429 | */ |
430 | static int check_load_and_stores(struct sock_filter *filter, int flen) | 430 | static int check_load_and_stores(struct sock_filter *filter, int flen) |
431 | { | 431 | { |
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 01a1101b5936..a7b342131869 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c | |||
@@ -129,7 +129,7 @@ static void linkwatch_schedule_work(int urgent) | |||
129 | if (!cancel_delayed_work(&linkwatch_work)) | 129 | if (!cancel_delayed_work(&linkwatch_work)) |
130 | return; | 130 | return; |
131 | 131 | ||
132 | /* Otherwise we reschedule it again for immediate exection. */ | 132 | /* Otherwise we reschedule it again for immediate execution. */ |
133 | schedule_delayed_work(&linkwatch_work, 0); | 133 | schedule_delayed_work(&linkwatch_work, 0); |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 0c55eaa70e39..aeeece72b72f 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -3761,7 +3761,10 @@ static int __init pktgen_create_thread(int cpu) | |||
3761 | list_add_tail(&t->th_list, &pktgen_threads); | 3761 | list_add_tail(&t->th_list, &pktgen_threads); |
3762 | init_completion(&t->start_done); | 3762 | init_completion(&t->start_done); |
3763 | 3763 | ||
3764 | p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu); | 3764 | p = kthread_create_on_node(pktgen_thread_worker, |
3765 | t, | ||
3766 | cpu_to_node(cpu), | ||
3767 | "kpktgend_%d", cpu); | ||
3765 | if (IS_ERR(p)) { | 3768 | if (IS_ERR(p)) { |
3766 | pr_err("kernel_thread() failed for cpu %d\n", t->cpu); | 3769 | pr_err("kernel_thread() failed for cpu %d\n", t->cpu); |
3767 | list_del(&t->th_list); | 3770 | list_del(&t->th_list); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49f7ea5b4c75..d7c4bb4b1820 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(__rtnl_register); | |||
196 | * as failure of this function is very unlikely, it can only happen due | 196 | * as failure of this function is very unlikely, it can only happen due |
197 | * to lack of memory when allocating the chain to store all message | 197 | * to lack of memory when allocating the chain to store all message |
198 | * handlers for a protocol. Meant for use in init functions where lack | 198 | * handlers for a protocol. Meant for use in init functions where lack |
199 | * of memory implies no sense in continueing. | 199 | * of memory implies no sense in continuing. |
200 | */ | 200 | */ |
201 | void rtnl_register(int protocol, int msgtype, | 201 | void rtnl_register(int protocol, int msgtype, |
202 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) | 202 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) |
@@ -1440,7 +1440,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
1440 | errout: | 1440 | errout: |
1441 | if (err < 0 && modified && net_ratelimit()) | 1441 | if (err < 0 && modified && net_ratelimit()) |
1442 | printk(KERN_WARNING "A link change request failed with " | 1442 | printk(KERN_WARNING "A link change request failed with " |
1443 | "some changes comitted already. Interface %s may " | 1443 | "some changes committed already. Interface %s may " |
1444 | "have been left with an inconsistent configuration, " | 1444 | "have been left with an inconsistent configuration, " |
1445 | "please check.\n", dev->name); | 1445 | "please check.\n", dev->name); |
1446 | 1446 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 801dd08908f9..7ebeed0a877c 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2267,7 +2267,7 @@ EXPORT_SYMBOL(skb_prepare_seq_read); | |||
2267 | * of bytes already consumed and the next call to | 2267 | * of bytes already consumed and the next call to |
2268 | * skb_seq_read() will return the remaining part of the block. | 2268 | * skb_seq_read() will return the remaining part of the block. |
2269 | * | 2269 | * |
2270 | * Note 1: The size of each block of data returned can be arbitary, | 2270 | * Note 1: The size of each block of data returned can be arbitrary, |
2271 | * this limitation is the cost for zerocopy seqeuental | 2271 | * this limitation is the cost for zerocopy seqeuental |
2272 | * reads of potentially non linear data. | 2272 | * reads of potentially non linear data. |
2273 | * | 2273 | * |
diff --git a/net/core/sock.c b/net/core/sock.c index 7dfed792434d..6e819780c232 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -215,7 +215,7 @@ __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; | |||
215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; | 215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; |
216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; | 216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; |
217 | 217 | ||
218 | /* Maximal space eaten by iovec or ancilliary data plus some space */ | 218 | /* Maximal space eaten by iovec or ancillary data plus some space */ |
219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); | 219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); |
220 | EXPORT_SYMBOL(sysctl_optmem_max); | 220 | EXPORT_SYMBOL(sysctl_optmem_max); |
221 | 221 | ||
@@ -1175,7 +1175,7 @@ static void __sk_free(struct sock *sk) | |||
1175 | void sk_free(struct sock *sk) | 1175 | void sk_free(struct sock *sk) |
1176 | { | 1176 | { |
1177 | /* | 1177 | /* |
1178 | * We substract one from sk_wmem_alloc and can know if | 1178 | * We subtract one from sk_wmem_alloc and can know if |
1179 | * some packets are still in some tx queue. | 1179 | * some packets are still in some tx queue. |
1180 | * If not null, sock_wfree() will call __sk_free(sk) later | 1180 | * If not null, sock_wfree() will call __sk_free(sk) later |
1181 | */ | 1181 | */ |
@@ -1185,10 +1185,10 @@ void sk_free(struct sock *sk) | |||
1185 | EXPORT_SYMBOL(sk_free); | 1185 | EXPORT_SYMBOL(sk_free); |
1186 | 1186 | ||
1187 | /* | 1187 | /* |
1188 | * Last sock_put should drop referrence to sk->sk_net. It has already | 1188 | * Last sock_put should drop reference to sk->sk_net. It has already |
1189 | * been dropped in sk_change_net. Taking referrence to stopping namespace | 1189 | * been dropped in sk_change_net. Taking reference to stopping namespace |
1190 | * is not an option. | 1190 | * is not an option. |
1191 | * Take referrence to a socket to remove it from hash _alive_ and after that | 1191 | * Take reference to a socket to remove it from hash _alive_ and after that |
1192 | * destroy it in the context of init_net. | 1192 | * destroy it in the context of init_net. |
1193 | */ | 1193 | */ |
1194 | void sk_release_kernel(struct sock *sk) | 1194 | void sk_release_kernel(struct sock *sk) |
diff --git a/net/dccp/options.c b/net/dccp/options.c index f06ffcfc8d71..4b2ab657ac8e 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -123,6 +123,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: | 123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: |
124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ | 124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ |
125 | break; | 125 | break; |
126 | if (len == 0) | ||
127 | goto out_invalid_option; | ||
126 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, | 128 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, |
127 | *value, value + 1, len - 1); | 129 | *value, value + 1, len - 1); |
128 | if (rc) | 130 | if (rc) |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 784d30210543..136d41cbcd02 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -143,7 +143,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
143 | } | 143 | } |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * dccp_determine_ccmps - Find out about CCID-specfic packet-size limits | 146 | * dccp_determine_ccmps - Find out about CCID-specific packet-size limits |
147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), | 147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), |
148 | * since the RX CCID is restricted to feedback packets (Acks), which are small | 148 | * since the RX CCID is restricted to feedback packets (Acks), which are small |
149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". | 149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". |
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 87bb5f4de0e8..c53ded2a98df 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig | |||
@@ -41,12 +41,12 @@ config NET_DSA_MV88E6XXX_NEED_PPU | |||
41 | default n | 41 | default n |
42 | 42 | ||
43 | config NET_DSA_MV88E6131 | 43 | config NET_DSA_MV88E6131 |
44 | bool "Marvell 88E6095/6095F/6131 ethernet switch chip support" | 44 | bool "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support" |
45 | select NET_DSA_MV88E6XXX | 45 | select NET_DSA_MV88E6XXX |
46 | select NET_DSA_MV88E6XXX_NEED_PPU | 46 | select NET_DSA_MV88E6XXX_NEED_PPU |
47 | select NET_DSA_TAG_DSA | 47 | select NET_DSA_TAG_DSA |
48 | ---help--- | 48 | ---help--- |
49 | This enables support for the Marvell 88E6095/6095F/6131 | 49 | This enables support for the Marvell 88E6085/6095/6095F/6131 |
50 | ethernet switch chips. | 50 | ethernet switch chips. |
51 | 51 | ||
52 | config NET_DSA_MV88E6123_61_65 | 52 | config NET_DSA_MV88E6123_61_65 |
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index bb2b41bc854e..45f7411e90ba 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c | |||
@@ -14,6 +14,13 @@ | |||
14 | #include "dsa_priv.h" | 14 | #include "dsa_priv.h" |
15 | #include "mv88e6xxx.h" | 15 | #include "mv88e6xxx.h" |
16 | 16 | ||
17 | /* | ||
18 | * Switch product IDs | ||
19 | */ | ||
20 | #define ID_6085 0x04a0 | ||
21 | #define ID_6095 0x0950 | ||
22 | #define ID_6131 0x1060 | ||
23 | |||
17 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | 24 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) |
18 | { | 25 | { |
19 | int ret; | 26 | int ret; |
@@ -21,9 +28,11 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | |||
21 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); | 28 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); |
22 | if (ret >= 0) { | 29 | if (ret >= 0) { |
23 | ret &= 0xfff0; | 30 | ret &= 0xfff0; |
24 | if (ret == 0x0950) | 31 | if (ret == ID_6085) |
32 | return "Marvell 88E6085"; | ||
33 | if (ret == ID_6095) | ||
25 | return "Marvell 88E6095/88E6095F"; | 34 | return "Marvell 88E6095/88E6095F"; |
26 | if (ret == 0x1060) | 35 | if (ret == ID_6131) |
27 | return "Marvell 88E6131"; | 36 | return "Marvell 88E6131"; |
28 | } | 37 | } |
29 | 38 | ||
@@ -124,7 +133,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
124 | * Ignore removed tag data on doubly tagged packets, disable | 133 | * Ignore removed tag data on doubly tagged packets, disable |
125 | * flow control messages, force flow control priority to the | 134 | * flow control messages, force flow control priority to the |
126 | * highest, and send all special multicast frames to the CPU | 135 | * highest, and send all special multicast frames to the CPU |
127 | * port at the higest priority. | 136 | * port at the highest priority. |
128 | */ | 137 | */ |
129 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); | 138 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); |
130 | 139 | ||
@@ -164,6 +173,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
164 | 173 | ||
165 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | 174 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) |
166 | { | 175 | { |
176 | struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); | ||
167 | int addr = REG_PORT(p); | 177 | int addr = REG_PORT(p); |
168 | u16 val; | 178 | u16 val; |
169 | 179 | ||
@@ -171,10 +181,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
171 | * MAC Forcing register: don't force link, speed, duplex | 181 | * MAC Forcing register: don't force link, speed, duplex |
172 | * or flow control state to any particular values on physical | 182 | * or flow control state to any particular values on physical |
173 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s | 183 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s |
174 | * full duplex. | 184 | * (100 Mb/s on 6085) full duplex. |
175 | */ | 185 | */ |
176 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) | 186 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) |
177 | REG_WRITE(addr, 0x01, 0x003e); | 187 | if (ps->id == ID_6085) |
188 | REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */ | ||
189 | else | ||
190 | REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */ | ||
178 | else | 191 | else |
179 | REG_WRITE(addr, 0x01, 0x0003); | 192 | REG_WRITE(addr, 0x01, 0x0003); |
180 | 193 | ||
@@ -194,8 +207,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
194 | * mode, but do not enable forwarding of unknown unicasts. | 207 | * mode, but do not enable forwarding of unknown unicasts. |
195 | */ | 208 | */ |
196 | val = 0x0433; | 209 | val = 0x0433; |
197 | if (p == dsa_upstream_port(ds)) | 210 | if (p == dsa_upstream_port(ds)) { |
198 | val |= 0x0104; | 211 | val |= 0x0104; |
212 | /* | ||
213 | * On 6085, unknown multicast forward is controlled | ||
214 | * here rather than in Port Control 2 register. | ||
215 | */ | ||
216 | if (ps->id == ID_6085) | ||
217 | val |= 0x0008; | ||
218 | } | ||
199 | if (ds->dsa_port_mask & (1 << p)) | 219 | if (ds->dsa_port_mask & (1 << p)) |
200 | val |= 0x0100; | 220 | val |= 0x0100; |
201 | REG_WRITE(addr, 0x04, val); | 221 | REG_WRITE(addr, 0x04, val); |
@@ -238,10 +258,19 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
238 | * If this is the upstream port for this switch, enable | 258 | * If this is the upstream port for this switch, enable |
239 | * forwarding of unknown multicast addresses. | 259 | * forwarding of unknown multicast addresses. |
240 | */ | 260 | */ |
241 | val = 0x0080 | dsa_upstream_port(ds); | 261 | if (ps->id == ID_6085) |
242 | if (p == dsa_upstream_port(ds)) | 262 | /* |
243 | val |= 0x0040; | 263 | * on 6085, bits 3:0 are reserved, bit 6 control ARP |
244 | REG_WRITE(addr, 0x08, val); | 264 | * mirroring, and multicast forward is handled in |
265 | * Port Control register. | ||
266 | */ | ||
267 | REG_WRITE(addr, 0x08, 0x0080); | ||
268 | else { | ||
269 | val = 0x0080 | dsa_upstream_port(ds); | ||
270 | if (p == dsa_upstream_port(ds)) | ||
271 | val |= 0x0040; | ||
272 | REG_WRITE(addr, 0x08, val); | ||
273 | } | ||
245 | 274 | ||
246 | /* | 275 | /* |
247 | * Rate Control: disable ingress rate limiting. | 276 | * Rate Control: disable ingress rate limiting. |
@@ -286,6 +315,8 @@ static int mv88e6131_setup(struct dsa_switch *ds) | |||
286 | mv88e6xxx_ppu_state_init(ds); | 315 | mv88e6xxx_ppu_state_init(ds); |
287 | mutex_init(&ps->stats_mutex); | 316 | mutex_init(&ps->stats_mutex); |
288 | 317 | ||
318 | ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0; | ||
319 | |||
289 | ret = mv88e6131_switch_reset(ds); | 320 | ret = mv88e6131_switch_reset(ds); |
290 | if (ret < 0) | 321 | if (ret < 0) |
291 | return ret; | 322 | return ret; |
diff --git a/net/dsa/mv88e6xxx.h b/net/dsa/mv88e6xxx.h index eb0e0aaa9f1b..61156ca26a0d 100644 --- a/net/dsa/mv88e6xxx.h +++ b/net/dsa/mv88e6xxx.h | |||
@@ -39,6 +39,8 @@ struct mv88e6xxx_priv_state { | |||
39 | * Hold this mutex over snapshot + dump sequences. | 39 | * Hold this mutex over snapshot + dump sequences. |
40 | */ | 40 | */ |
41 | struct mutex stats_mutex; | 41 | struct mutex stats_mutex; |
42 | |||
43 | int id; /* switch product id */ | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct mv88e6xxx_hw_stat { | 46 | struct mv88e6xxx_hw_stat { |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 0c2826337919..116d3fd3d669 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
435 | udpdest.sin_addr.s_addr = htonl(network | addr.station); | 435 | udpdest.sin_addr.s_addr = htonl(network | addr.station); |
436 | } | 436 | } |
437 | 437 | ||
438 | memset(&ah, 0, sizeof(ah)); | ||
438 | ah.port = port; | 439 | ah.port = port; |
439 | ah.cb = cb & 0x7f; | 440 | ah.cb = cb & 0x7f; |
440 | ah.code = 2; /* magic */ | 441 | ah.code = 2; /* magic */ |
441 | ah.pad = 0; | ||
442 | 442 | ||
443 | /* tack our header on the front of the iovec */ | 443 | /* tack our header on the front of the iovec */ |
444 | size = sizeof(struct aunhdr); | 444 | size = sizeof(struct aunhdr); |
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index ce2d33582859..5761185f884e 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -1,5 +1,3 @@ | |||
1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
2 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o | 2 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o |
3 | af_802154-y := af_ieee802154.o raw.o dgram.o | 3 | af_802154-y := af_ieee802154.o raw.o dgram.o |
4 | |||
5 | ccflags-y += -Wall -DDEBUG | ||
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 090d273d7865..1b74d3b64371 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) | |||
215 | case ARPHRD_INFINIBAND: | 215 | case ARPHRD_INFINIBAND: |
216 | ip_ib_mc_map(addr, dev->broadcast, haddr); | 216 | ip_ib_mc_map(addr, dev->broadcast, haddr); |
217 | return 0; | 217 | return 0; |
218 | case ARPHRD_IPGRE: | ||
219 | ip_ipgre_mc_map(addr, dev->broadcast, haddr); | ||
220 | return 0; | ||
218 | default: | 221 | default: |
219 | if (dir) { | 222 | if (dir) { |
220 | memcpy(haddr, dev->broadcast, dev->addr_len); | 223 | memcpy(haddr, dev->broadcast, dev->addr_len); |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 094e150c6260..a0af7ea87870 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -112,7 +112,7 @@ int cipso_v4_rbm_strictvalid = 1; | |||
112 | /* The maximum number of category ranges permitted in the ranged category tag | 112 | /* The maximum number of category ranges permitted in the ranged category tag |
113 | * (tag #5). You may note that the IETF draft states that the maximum number | 113 | * (tag #5). You may note that the IETF draft states that the maximum number |
114 | * of category ranges is 7, but if the low end of the last category range is | 114 | * of category ranges is 7, but if the low end of the last category range is |
115 | * zero then it is possibile to fit 8 category ranges because the zero should | 115 | * zero then it is possible to fit 8 category ranges because the zero should |
116 | * be omitted. */ | 116 | * be omitted. */ |
117 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 | 117 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 |
118 | 118 | ||
@@ -438,7 +438,7 @@ cache_add_failure: | |||
438 | * | 438 | * |
439 | * Description: | 439 | * Description: |
440 | * Search the DOI definition list for a DOI definition with a DOI value that | 440 | * Search the DOI definition list for a DOI definition with a DOI value that |
441 | * matches @doi. The caller is responsibile for calling rcu_read_[un]lock(). | 441 | * matches @doi. The caller is responsible for calling rcu_read_[un]lock(). |
442 | * Returns a pointer to the DOI definition on success and NULL on failure. | 442 | * Returns a pointer to the DOI definition on success and NULL on failure. |
443 | */ | 443 | */ |
444 | static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) | 444 | static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) |
@@ -1293,7 +1293,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | |||
1293 | return ret_val; | 1293 | return ret_val; |
1294 | 1294 | ||
1295 | /* This will send packets using the "optimized" format when | 1295 | /* This will send packets using the "optimized" format when |
1296 | * possibile as specified in section 3.4.2.6 of the | 1296 | * possible as specified in section 3.4.2.6 of the |
1297 | * CIPSO draft. */ | 1297 | * CIPSO draft. */ |
1298 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) | 1298 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) |
1299 | tag_len = 14; | 1299 | tag_len = 14; |
@@ -1752,7 +1752,7 @@ validate_return: | |||
1752 | } | 1752 | } |
1753 | 1753 | ||
1754 | /** | 1754 | /** |
1755 | * cipso_v4_error - Send the correct reponse for a bad packet | 1755 | * cipso_v4_error - Send the correct response for a bad packet |
1756 | * @skb: the packet | 1756 | * @skb: the packet |
1757 | * @error: the error code | 1757 | * @error: the error code |
1758 | * @gateway: CIPSO gateway flag | 1758 | * @gateway: CIPSO gateway flag |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 6d85800daeb7..cd9ca0811cfa 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -64,6 +64,8 @@ | |||
64 | #include <net/rtnetlink.h> | 64 | #include <net/rtnetlink.h> |
65 | #include <net/net_namespace.h> | 65 | #include <net/net_namespace.h> |
66 | 66 | ||
67 | #include "fib_lookup.h" | ||
68 | |||
67 | static struct ipv4_devconf ipv4_devconf = { | 69 | static struct ipv4_devconf ipv4_devconf = { |
68 | .data = { | 70 | .data = { |
69 | [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, | 71 | [IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1, |
@@ -151,6 +153,20 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) | |||
151 | break; | 153 | break; |
152 | } | 154 | } |
153 | } | 155 | } |
156 | if (!result) { | ||
157 | struct flowi4 fl4 = { .daddr = addr }; | ||
158 | struct fib_result res = { 0 }; | ||
159 | struct fib_table *local; | ||
160 | |||
161 | /* Fallback to FIB local table so that communication | ||
162 | * over loopback subnets work. | ||
163 | */ | ||
164 | local = fib_get_table(net, RT_TABLE_LOCAL); | ||
165 | if (local && | ||
166 | !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) && | ||
167 | res.type == RTN_LOCAL) | ||
168 | result = FIB_RES_DEV(res); | ||
169 | } | ||
154 | if (result && devref) | 170 | if (result && devref) |
155 | dev_hold(result); | 171 | dev_hold(result); |
156 | rcu_read_unlock(); | 172 | rcu_read_unlock(); |
@@ -345,6 +361,17 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
345 | } | 361 | } |
346 | } | 362 | } |
347 | 363 | ||
364 | /* On promotion all secondaries from subnet are changing | ||
365 | * the primary IP, we must remove all their routes silently | ||
366 | * and later to add them back with new prefsrc. Do this | ||
367 | * while all addresses are on the device list. | ||
368 | */ | ||
369 | for (ifa = promote; ifa; ifa = ifa->ifa_next) { | ||
370 | if (ifa1->ifa_mask == ifa->ifa_mask && | ||
371 | inet_ifa_match(ifa1->ifa_address, ifa)) | ||
372 | fib_del_ifaddr(ifa, ifa1); | ||
373 | } | ||
374 | |||
348 | /* 2. Unlink it */ | 375 | /* 2. Unlink it */ |
349 | 376 | ||
350 | *ifap = ifa1->ifa_next; | 377 | *ifap = ifa1->ifa_next; |
@@ -364,6 +391,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
364 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); | 391 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); |
365 | 392 | ||
366 | if (promote) { | 393 | if (promote) { |
394 | struct in_ifaddr *next_sec = promote->ifa_next; | ||
367 | 395 | ||
368 | if (prev_prom) { | 396 | if (prev_prom) { |
369 | prev_prom->ifa_next = promote->ifa_next; | 397 | prev_prom->ifa_next = promote->ifa_next; |
@@ -375,7 +403,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
375 | rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); | 403 | rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); |
376 | blocking_notifier_call_chain(&inetaddr_chain, | 404 | blocking_notifier_call_chain(&inetaddr_chain, |
377 | NETDEV_UP, promote); | 405 | NETDEV_UP, promote); |
378 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { | 406 | for (ifa = next_sec; ifa; ifa = ifa->ifa_next) { |
379 | if (ifa1->ifa_mask != ifa->ifa_mask || | 407 | if (ifa1->ifa_mask != ifa->ifa_mask || |
380 | !inet_ifa_match(ifa1->ifa_address, ifa)) | 408 | !inet_ifa_match(ifa1->ifa_address, ifa)) |
381 | continue; | 409 | continue; |
@@ -1652,7 +1680,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
1652 | return; | 1680 | return; |
1653 | 1681 | ||
1654 | cnf->sysctl = NULL; | 1682 | cnf->sysctl = NULL; |
1655 | unregister_sysctl_table(t->sysctl_header); | 1683 | unregister_net_sysctl_table(t->sysctl_header); |
1656 | kfree(t->dev_name); | 1684 | kfree(t->dev_name); |
1657 | kfree(t); | 1685 | kfree(t); |
1658 | } | 1686 | } |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index a373a259253c..451088330bbb 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -228,7 +228,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
228 | if (res.type != RTN_LOCAL || !accept_local) | 228 | if (res.type != RTN_LOCAL || !accept_local) |
229 | goto e_inval; | 229 | goto e_inval; |
230 | } | 230 | } |
231 | *spec_dst = FIB_RES_PREFSRC(res); | 231 | *spec_dst = FIB_RES_PREFSRC(net, res); |
232 | fib_combine_itag(itag, &res); | 232 | fib_combine_itag(itag, &res); |
233 | dev_match = false; | 233 | dev_match = false; |
234 | 234 | ||
@@ -258,7 +258,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
258 | ret = 0; | 258 | ret = 0; |
259 | if (fib_lookup(net, &fl4, &res) == 0) { | 259 | if (fib_lookup(net, &fl4, &res) == 0) { |
260 | if (res.type == RTN_UNICAST) { | 260 | if (res.type == RTN_UNICAST) { |
261 | *spec_dst = FIB_RES_PREFSRC(res); | 261 | *spec_dst = FIB_RES_PREFSRC(net, res); |
262 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; | 262 | ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; |
263 | } | 263 | } |
264 | } | 264 | } |
@@ -722,12 +722,17 @@ void fib_add_ifaddr(struct in_ifaddr *ifa) | |||
722 | } | 722 | } |
723 | } | 723 | } |
724 | 724 | ||
725 | static void fib_del_ifaddr(struct in_ifaddr *ifa) | 725 | /* Delete primary or secondary address. |
726 | * Optionally, on secondary address promotion consider the addresses | ||
727 | * from subnet iprim as deleted, even if they are in device list. | ||
728 | * In this case the secondary ifa can be in device list. | ||
729 | */ | ||
730 | void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) | ||
726 | { | 731 | { |
727 | struct in_device *in_dev = ifa->ifa_dev; | 732 | struct in_device *in_dev = ifa->ifa_dev; |
728 | struct net_device *dev = in_dev->dev; | 733 | struct net_device *dev = in_dev->dev; |
729 | struct in_ifaddr *ifa1; | 734 | struct in_ifaddr *ifa1; |
730 | struct in_ifaddr *prim = ifa; | 735 | struct in_ifaddr *prim = ifa, *prim1 = NULL; |
731 | __be32 brd = ifa->ifa_address | ~ifa->ifa_mask; | 736 | __be32 brd = ifa->ifa_address | ~ifa->ifa_mask; |
732 | __be32 any = ifa->ifa_address & ifa->ifa_mask; | 737 | __be32 any = ifa->ifa_address & ifa->ifa_mask; |
733 | #define LOCAL_OK 1 | 738 | #define LOCAL_OK 1 |
@@ -735,17 +740,26 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
735 | #define BRD0_OK 4 | 740 | #define BRD0_OK 4 |
736 | #define BRD1_OK 8 | 741 | #define BRD1_OK 8 |
737 | unsigned ok = 0; | 742 | unsigned ok = 0; |
743 | int subnet = 0; /* Primary network */ | ||
744 | int gone = 1; /* Address is missing */ | ||
745 | int same_prefsrc = 0; /* Another primary with same IP */ | ||
738 | 746 | ||
739 | if (!(ifa->ifa_flags & IFA_F_SECONDARY)) | 747 | if (ifa->ifa_flags & IFA_F_SECONDARY) { |
740 | fib_magic(RTM_DELROUTE, | ||
741 | dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, | ||
742 | any, ifa->ifa_prefixlen, prim); | ||
743 | else { | ||
744 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); | 748 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); |
745 | if (prim == NULL) { | 749 | if (prim == NULL) { |
746 | printk(KERN_WARNING "fib_del_ifaddr: bug: prim == NULL\n"); | 750 | printk(KERN_WARNING "fib_del_ifaddr: bug: prim == NULL\n"); |
747 | return; | 751 | return; |
748 | } | 752 | } |
753 | if (iprim && iprim != prim) { | ||
754 | printk(KERN_WARNING "fib_del_ifaddr: bug: iprim != prim\n"); | ||
755 | return; | ||
756 | } | ||
757 | } else if (!ipv4_is_zeronet(any) && | ||
758 | (any != ifa->ifa_local || ifa->ifa_prefixlen < 32)) { | ||
759 | fib_magic(RTM_DELROUTE, | ||
760 | dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST, | ||
761 | any, ifa->ifa_prefixlen, prim); | ||
762 | subnet = 1; | ||
749 | } | 763 | } |
750 | 764 | ||
751 | /* Deletion is more complicated than add. | 765 | /* Deletion is more complicated than add. |
@@ -755,6 +769,49 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
755 | */ | 769 | */ |
756 | 770 | ||
757 | for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { | 771 | for (ifa1 = in_dev->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { |
772 | if (ifa1 == ifa) { | ||
773 | /* promotion, keep the IP */ | ||
774 | gone = 0; | ||
775 | continue; | ||
776 | } | ||
777 | /* Ignore IFAs from our subnet */ | ||
778 | if (iprim && ifa1->ifa_mask == iprim->ifa_mask && | ||
779 | inet_ifa_match(ifa1->ifa_address, iprim)) | ||
780 | continue; | ||
781 | |||
782 | /* Ignore ifa1 if it uses different primary IP (prefsrc) */ | ||
783 | if (ifa1->ifa_flags & IFA_F_SECONDARY) { | ||
784 | /* Another address from our subnet? */ | ||
785 | if (ifa1->ifa_mask == prim->ifa_mask && | ||
786 | inet_ifa_match(ifa1->ifa_address, prim)) | ||
787 | prim1 = prim; | ||
788 | else { | ||
789 | /* We reached the secondaries, so | ||
790 | * same_prefsrc should be determined. | ||
791 | */ | ||
792 | if (!same_prefsrc) | ||
793 | continue; | ||
794 | /* Search new prim1 if ifa1 is not | ||
795 | * using the current prim1 | ||
796 | */ | ||
797 | if (!prim1 || | ||
798 | ifa1->ifa_mask != prim1->ifa_mask || | ||
799 | !inet_ifa_match(ifa1->ifa_address, prim1)) | ||
800 | prim1 = inet_ifa_byprefix(in_dev, | ||
801 | ifa1->ifa_address, | ||
802 | ifa1->ifa_mask); | ||
803 | if (!prim1) | ||
804 | continue; | ||
805 | if (prim1->ifa_local != prim->ifa_local) | ||
806 | continue; | ||
807 | } | ||
808 | } else { | ||
809 | if (prim->ifa_local != ifa1->ifa_local) | ||
810 | continue; | ||
811 | prim1 = ifa1; | ||
812 | if (prim != prim1) | ||
813 | same_prefsrc = 1; | ||
814 | } | ||
758 | if (ifa->ifa_local == ifa1->ifa_local) | 815 | if (ifa->ifa_local == ifa1->ifa_local) |
759 | ok |= LOCAL_OK; | 816 | ok |= LOCAL_OK; |
760 | if (ifa->ifa_broadcast == ifa1->ifa_broadcast) | 817 | if (ifa->ifa_broadcast == ifa1->ifa_broadcast) |
@@ -763,19 +820,37 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
763 | ok |= BRD1_OK; | 820 | ok |= BRD1_OK; |
764 | if (any == ifa1->ifa_broadcast) | 821 | if (any == ifa1->ifa_broadcast) |
765 | ok |= BRD0_OK; | 822 | ok |= BRD0_OK; |
823 | /* primary has network specific broadcasts */ | ||
824 | if (prim1 == ifa1 && ifa1->ifa_prefixlen < 31) { | ||
825 | __be32 brd1 = ifa1->ifa_address | ~ifa1->ifa_mask; | ||
826 | __be32 any1 = ifa1->ifa_address & ifa1->ifa_mask; | ||
827 | |||
828 | if (!ipv4_is_zeronet(any1)) { | ||
829 | if (ifa->ifa_broadcast == brd1 || | ||
830 | ifa->ifa_broadcast == any1) | ||
831 | ok |= BRD_OK; | ||
832 | if (brd == brd1 || brd == any1) | ||
833 | ok |= BRD1_OK; | ||
834 | if (any == brd1 || any == any1) | ||
835 | ok |= BRD0_OK; | ||
836 | } | ||
837 | } | ||
766 | } | 838 | } |
767 | 839 | ||
768 | if (!(ok & BRD_OK)) | 840 | if (!(ok & BRD_OK)) |
769 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); | 841 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32, prim); |
770 | if (!(ok & BRD1_OK)) | 842 | if (subnet && ifa->ifa_prefixlen < 31) { |
771 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim); | 843 | if (!(ok & BRD1_OK)) |
772 | if (!(ok & BRD0_OK)) | 844 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32, prim); |
773 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim); | 845 | if (!(ok & BRD0_OK)) |
846 | fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32, prim); | ||
847 | } | ||
774 | if (!(ok & LOCAL_OK)) { | 848 | if (!(ok & LOCAL_OK)) { |
775 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); | 849 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim); |
776 | 850 | ||
777 | /* Check, that this local address finally disappeared. */ | 851 | /* Check, that this local address finally disappeared. */ |
778 | if (inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) { | 852 | if (gone && |
853 | inet_addr_type(dev_net(dev), ifa->ifa_local) != RTN_LOCAL) { | ||
779 | /* And the last, but not the least thing. | 854 | /* And the last, but not the least thing. |
780 | * We must flush stray FIB entries. | 855 | * We must flush stray FIB entries. |
781 | * | 856 | * |
@@ -885,6 +960,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
885 | { | 960 | { |
886 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 961 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
887 | struct net_device *dev = ifa->ifa_dev->dev; | 962 | struct net_device *dev = ifa->ifa_dev->dev; |
963 | struct net *net = dev_net(dev); | ||
888 | 964 | ||
889 | switch (event) { | 965 | switch (event) { |
890 | case NETDEV_UP: | 966 | case NETDEV_UP: |
@@ -892,12 +968,12 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
892 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 968 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
893 | fib_sync_up(dev); | 969 | fib_sync_up(dev); |
894 | #endif | 970 | #endif |
895 | fib_update_nh_saddrs(dev); | 971 | atomic_inc(&net->ipv4.dev_addr_genid); |
896 | rt_cache_flush(dev_net(dev), -1); | 972 | rt_cache_flush(dev_net(dev), -1); |
897 | break; | 973 | break; |
898 | case NETDEV_DOWN: | 974 | case NETDEV_DOWN: |
899 | fib_del_ifaddr(ifa); | 975 | fib_del_ifaddr(ifa, NULL); |
900 | fib_update_nh_saddrs(dev); | 976 | atomic_inc(&net->ipv4.dev_addr_genid); |
901 | if (ifa->ifa_dev->ifa_list == NULL) { | 977 | if (ifa->ifa_dev->ifa_list == NULL) { |
902 | /* Last address was deleted from this interface. | 978 | /* Last address was deleted from this interface. |
903 | * Disable IP. | 979 | * Disable IP. |
@@ -915,6 +991,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
915 | { | 991 | { |
916 | struct net_device *dev = ptr; | 992 | struct net_device *dev = ptr; |
917 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 993 | struct in_device *in_dev = __in_dev_get_rtnl(dev); |
994 | struct net *net = dev_net(dev); | ||
918 | 995 | ||
919 | if (event == NETDEV_UNREGISTER) { | 996 | if (event == NETDEV_UNREGISTER) { |
920 | fib_disable_ip(dev, 2, -1); | 997 | fib_disable_ip(dev, 2, -1); |
@@ -932,6 +1009,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
932 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1009 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
933 | fib_sync_up(dev); | 1010 | fib_sync_up(dev); |
934 | #endif | 1011 | #endif |
1012 | atomic_inc(&net->ipv4.dev_addr_genid); | ||
935 | rt_cache_flush(dev_net(dev), -1); | 1013 | rt_cache_flush(dev_net(dev), -1); |
936 | break; | 1014 | break; |
937 | case NETDEV_DOWN: | 1015 | case NETDEV_DOWN: |
@@ -990,6 +1068,7 @@ static void ip_fib_net_exit(struct net *net) | |||
990 | fib4_rules_exit(net); | 1068 | fib4_rules_exit(net); |
991 | #endif | 1069 | #endif |
992 | 1070 | ||
1071 | rtnl_lock(); | ||
993 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) { | 1072 | for (i = 0; i < FIB_TABLE_HASHSZ; i++) { |
994 | struct fib_table *tb; | 1073 | struct fib_table *tb; |
995 | struct hlist_head *head; | 1074 | struct hlist_head *head; |
@@ -1002,6 +1081,7 @@ static void ip_fib_net_exit(struct net *net) | |||
1002 | fib_free_table(tb); | 1081 | fib_free_table(tb); |
1003 | } | 1082 | } |
1004 | } | 1083 | } |
1084 | rtnl_unlock(); | ||
1005 | kfree(net->ipv4.fib_table_hash); | 1085 | kfree(net->ipv4.fib_table_hash); |
1006 | } | 1086 | } |
1007 | 1087 | ||
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h index 4ec323875a02..af0f14aba169 100644 --- a/net/ipv4/fib_lookup.h +++ b/net/ipv4/fib_lookup.h | |||
@@ -10,7 +10,6 @@ struct fib_alias { | |||
10 | struct fib_info *fa_info; | 10 | struct fib_info *fa_info; |
11 | u8 fa_tos; | 11 | u8 fa_tos; |
12 | u8 fa_type; | 12 | u8 fa_type; |
13 | u8 fa_scope; | ||
14 | u8 fa_state; | 13 | u8 fa_state; |
15 | struct rcu_head rcu; | 14 | struct rcu_head rcu; |
16 | }; | 15 | }; |
@@ -29,7 +28,7 @@ extern void fib_release_info(struct fib_info *); | |||
29 | extern struct fib_info *fib_create_info(struct fib_config *cfg); | 28 | extern struct fib_info *fib_create_info(struct fib_config *cfg); |
30 | extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); | 29 | extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); |
31 | extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 30 | extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, |
32 | u32 tb_id, u8 type, u8 scope, __be32 dst, | 31 | u32 tb_id, u8 type, __be32 dst, |
33 | int dst_len, u8 tos, struct fib_info *fi, | 32 | int dst_len, u8 tos, struct fib_info *fi, |
34 | unsigned int); | 33 | unsigned int); |
35 | extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, | 34 | extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 622ac4c95026..641a5a2a9f9c 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -222,7 +222,7 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi) | |||
222 | unsigned int mask = (fib_info_hash_size - 1); | 222 | unsigned int mask = (fib_info_hash_size - 1); |
223 | unsigned int val = fi->fib_nhs; | 223 | unsigned int val = fi->fib_nhs; |
224 | 224 | ||
225 | val ^= fi->fib_protocol; | 225 | val ^= (fi->fib_protocol << 8) | fi->fib_scope; |
226 | val ^= (__force u32)fi->fib_prefsrc; | 226 | val ^= (__force u32)fi->fib_prefsrc; |
227 | val ^= fi->fib_priority; | 227 | val ^= fi->fib_priority; |
228 | for_nexthops(fi) { | 228 | for_nexthops(fi) { |
@@ -248,10 +248,11 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) | |||
248 | if (fi->fib_nhs != nfi->fib_nhs) | 248 | if (fi->fib_nhs != nfi->fib_nhs) |
249 | continue; | 249 | continue; |
250 | if (nfi->fib_protocol == fi->fib_protocol && | 250 | if (nfi->fib_protocol == fi->fib_protocol && |
251 | nfi->fib_scope == fi->fib_scope && | ||
251 | nfi->fib_prefsrc == fi->fib_prefsrc && | 252 | nfi->fib_prefsrc == fi->fib_prefsrc && |
252 | nfi->fib_priority == fi->fib_priority && | 253 | nfi->fib_priority == fi->fib_priority && |
253 | memcmp(nfi->fib_metrics, fi->fib_metrics, | 254 | memcmp(nfi->fib_metrics, fi->fib_metrics, |
254 | sizeof(fi->fib_metrics)) == 0 && | 255 | sizeof(u32) * RTAX_MAX) == 0 && |
255 | ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && | 256 | ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && |
256 | (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) | 257 | (nfi->fib_nhs == 0 || nh_comp(fi, nfi) == 0)) |
257 | return fi; | 258 | return fi; |
@@ -328,7 +329,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, | |||
328 | goto errout; | 329 | goto errout; |
329 | 330 | ||
330 | err = fib_dump_info(skb, info->pid, seq, event, tb_id, | 331 | err = fib_dump_info(skb, info->pid, seq, event, tb_id, |
331 | fa->fa_type, fa->fa_scope, key, dst_len, | 332 | fa->fa_type, key, dst_len, |
332 | fa->fa_tos, fa->fa_info, nlm_flags); | 333 | fa->fa_tos, fa->fa_info, nlm_flags); |
333 | if (err < 0) { | 334 | if (err < 0) { |
334 | /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ | 335 | /* -EMSGSIZE implies BUG in fib_nlmsg_size() */ |
@@ -695,6 +696,16 @@ static void fib_info_hash_move(struct hlist_head *new_info_hash, | |||
695 | fib_info_hash_free(old_laddrhash, bytes); | 696 | fib_info_hash_free(old_laddrhash, bytes); |
696 | } | 697 | } |
697 | 698 | ||
699 | __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh) | ||
700 | { | ||
701 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | ||
702 | nh->nh_gw, | ||
703 | nh->nh_parent->fib_scope); | ||
704 | nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); | ||
705 | |||
706 | return nh->nh_saddr; | ||
707 | } | ||
708 | |||
698 | struct fib_info *fib_create_info(struct fib_config *cfg) | 709 | struct fib_info *fib_create_info(struct fib_config *cfg) |
699 | { | 710 | { |
700 | int err; | 711 | int err; |
@@ -753,6 +764,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
753 | 764 | ||
754 | fi->fib_net = hold_net(net); | 765 | fi->fib_net = hold_net(net); |
755 | fi->fib_protocol = cfg->fc_protocol; | 766 | fi->fib_protocol = cfg->fc_protocol; |
767 | fi->fib_scope = cfg->fc_scope; | ||
756 | fi->fib_flags = cfg->fc_flags; | 768 | fi->fib_flags = cfg->fc_flags; |
757 | fi->fib_priority = cfg->fc_priority; | 769 | fi->fib_priority = cfg->fc_priority; |
758 | fi->fib_prefsrc = cfg->fc_prefsrc; | 770 | fi->fib_prefsrc = cfg->fc_prefsrc; |
@@ -854,10 +866,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) | |||
854 | } | 866 | } |
855 | 867 | ||
856 | change_nexthops(fi) { | 868 | change_nexthops(fi) { |
857 | nexthop_nh->nh_cfg_scope = cfg->fc_scope; | 869 | fib_info_update_nh_saddr(net, nexthop_nh); |
858 | nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev, | ||
859 | nexthop_nh->nh_gw, | ||
860 | nexthop_nh->nh_cfg_scope); | ||
861 | } endfor_nexthops(fi) | 870 | } endfor_nexthops(fi) |
862 | 871 | ||
863 | link_it: | 872 | link_it: |
@@ -906,7 +915,7 @@ failure: | |||
906 | } | 915 | } |
907 | 916 | ||
908 | int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | 917 | int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, |
909 | u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos, | 918 | u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos, |
910 | struct fib_info *fi, unsigned int flags) | 919 | struct fib_info *fi, unsigned int flags) |
911 | { | 920 | { |
912 | struct nlmsghdr *nlh; | 921 | struct nlmsghdr *nlh; |
@@ -928,7 +937,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, | |||
928 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); | 937 | NLA_PUT_U32(skb, RTA_TABLE, tb_id); |
929 | rtm->rtm_type = type; | 938 | rtm->rtm_type = type; |
930 | rtm->rtm_flags = fi->fib_flags; | 939 | rtm->rtm_flags = fi->fib_flags; |
931 | rtm->rtm_scope = scope; | 940 | rtm->rtm_scope = fi->fib_scope; |
932 | rtm->rtm_protocol = fi->fib_protocol; | 941 | rtm->rtm_protocol = fi->fib_protocol; |
933 | 942 | ||
934 | if (rtm->rtm_dst_len) | 943 | if (rtm->rtm_dst_len) |
@@ -1084,7 +1093,7 @@ void fib_select_default(struct fib_result *res) | |||
1084 | list_for_each_entry_rcu(fa, fa_head, fa_list) { | 1093 | list_for_each_entry_rcu(fa, fa_head, fa_list) { |
1085 | struct fib_info *next_fi = fa->fa_info; | 1094 | struct fib_info *next_fi = fa->fa_info; |
1086 | 1095 | ||
1087 | if (fa->fa_scope != res->scope || | 1096 | if (next_fi->fib_scope != res->scope || |
1088 | fa->fa_type != RTN_UNICAST) | 1097 | fa->fa_type != RTN_UNICAST) |
1089 | continue; | 1098 | continue; |
1090 | 1099 | ||
@@ -1128,24 +1137,6 @@ out: | |||
1128 | return; | 1137 | return; |
1129 | } | 1138 | } |
1130 | 1139 | ||
1131 | void fib_update_nh_saddrs(struct net_device *dev) | ||
1132 | { | ||
1133 | struct hlist_head *head; | ||
1134 | struct hlist_node *node; | ||
1135 | struct fib_nh *nh; | ||
1136 | unsigned int hash; | ||
1137 | |||
1138 | hash = fib_devindex_hashfn(dev->ifindex); | ||
1139 | head = &fib_info_devhash[hash]; | ||
1140 | hlist_for_each_entry(nh, node, head, nh_hash) { | ||
1141 | if (nh->nh_dev != dev) | ||
1142 | continue; | ||
1143 | nh->nh_saddr = inet_select_addr(nh->nh_dev, | ||
1144 | nh->nh_gw, | ||
1145 | nh->nh_cfg_scope); | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 1140 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
1150 | 1141 | ||
1151 | /* | 1142 | /* |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 3d28a35c2e1a..5fe9b8b41df3 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet | 13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet |
14 | * | 14 | * |
15 | * This work is based on the LPC-trie which is originally descibed in: | 15 | * This work is based on the LPC-trie which is originally described in: |
16 | * | 16 | * |
17 | * An experimental study of compression methods for dynamic tries | 17 | * An experimental study of compression methods for dynamic tries |
18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. | 18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. |
@@ -1245,7 +1245,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1245 | if (fa->fa_info->fib_priority != fi->fib_priority) | 1245 | if (fa->fa_info->fib_priority != fi->fib_priority) |
1246 | break; | 1246 | break; |
1247 | if (fa->fa_type == cfg->fc_type && | 1247 | if (fa->fa_type == cfg->fc_type && |
1248 | fa->fa_scope == cfg->fc_scope && | ||
1249 | fa->fa_info == fi) { | 1248 | fa->fa_info == fi) { |
1250 | fa_match = fa; | 1249 | fa_match = fa; |
1251 | break; | 1250 | break; |
@@ -1271,7 +1270,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1271 | new_fa->fa_tos = fa->fa_tos; | 1270 | new_fa->fa_tos = fa->fa_tos; |
1272 | new_fa->fa_info = fi; | 1271 | new_fa->fa_info = fi; |
1273 | new_fa->fa_type = cfg->fc_type; | 1272 | new_fa->fa_type = cfg->fc_type; |
1274 | new_fa->fa_scope = cfg->fc_scope; | ||
1275 | state = fa->fa_state; | 1273 | state = fa->fa_state; |
1276 | new_fa->fa_state = state & ~FA_S_ACCESSED; | 1274 | new_fa->fa_state = state & ~FA_S_ACCESSED; |
1277 | 1275 | ||
@@ -1308,7 +1306,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1308 | new_fa->fa_info = fi; | 1306 | new_fa->fa_info = fi; |
1309 | new_fa->fa_tos = tos; | 1307 | new_fa->fa_tos = tos; |
1310 | new_fa->fa_type = cfg->fc_type; | 1308 | new_fa->fa_type = cfg->fc_type; |
1311 | new_fa->fa_scope = cfg->fc_scope; | ||
1312 | new_fa->fa_state = 0; | 1309 | new_fa->fa_state = 0; |
1313 | /* | 1310 | /* |
1314 | * Insert new entry to the list. | 1311 | * Insert new entry to the list. |
@@ -1362,15 +1359,15 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
1362 | 1359 | ||
1363 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | 1360 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) |
1364 | continue; | 1361 | continue; |
1365 | if (fa->fa_scope < flp->flowi4_scope) | 1362 | if (fa->fa_info->fib_scope < flp->flowi4_scope) |
1366 | continue; | 1363 | continue; |
1367 | fib_alias_accessed(fa); | 1364 | fib_alias_accessed(fa); |
1368 | err = fib_props[fa->fa_type].error; | 1365 | err = fib_props[fa->fa_type].error; |
1369 | if (err) { | 1366 | if (err) { |
1370 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
1371 | t->stats.semantic_match_miss++; | 1368 | t->stats.semantic_match_passed++; |
1372 | #endif | 1369 | #endif |
1373 | return 1; | 1370 | return err; |
1374 | } | 1371 | } |
1375 | if (fi->fib_flags & RTNH_F_DEAD) | 1372 | if (fi->fib_flags & RTNH_F_DEAD) |
1376 | continue; | 1373 | continue; |
@@ -1388,7 +1385,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
1388 | res->prefixlen = plen; | 1385 | res->prefixlen = plen; |
1389 | res->nh_sel = nhsel; | 1386 | res->nh_sel = nhsel; |
1390 | res->type = fa->fa_type; | 1387 | res->type = fa->fa_type; |
1391 | res->scope = fa->fa_scope; | 1388 | res->scope = fa->fa_info->fib_scope; |
1392 | res->fi = fi; | 1389 | res->fi = fi; |
1393 | res->table = tb; | 1390 | res->table = tb; |
1394 | res->fa_head = &li->falh; | 1391 | res->fa_head = &li->falh; |
@@ -1664,7 +1661,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1664 | 1661 | ||
1665 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && | 1662 | if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && |
1666 | (cfg->fc_scope == RT_SCOPE_NOWHERE || | 1663 | (cfg->fc_scope == RT_SCOPE_NOWHERE || |
1667 | fa->fa_scope == cfg->fc_scope) && | 1664 | fa->fa_info->fib_scope == cfg->fc_scope) && |
1665 | (!cfg->fc_prefsrc || | ||
1666 | fi->fib_prefsrc == cfg->fc_prefsrc) && | ||
1668 | (!cfg->fc_protocol || | 1667 | (!cfg->fc_protocol || |
1669 | fi->fib_protocol == cfg->fc_protocol) && | 1668 | fi->fib_protocol == cfg->fc_protocol) && |
1670 | fib_nh_match(cfg, fi) == 0) { | 1669 | fib_nh_match(cfg, fi) == 0) { |
@@ -1861,7 +1860,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, | |||
1861 | RTM_NEWROUTE, | 1860 | RTM_NEWROUTE, |
1862 | tb->tb_id, | 1861 | tb->tb_id, |
1863 | fa->fa_type, | 1862 | fa->fa_type, |
1864 | fa->fa_scope, | ||
1865 | xkey, | 1863 | xkey, |
1866 | plen, | 1864 | plen, |
1867 | fa->fa_tos, | 1865 | fa->fa_tos, |
@@ -1980,9 +1978,6 @@ struct fib_table *fib_trie_table(u32 id) | |||
1980 | t = (struct trie *) tb->tb_data; | 1978 | t = (struct trie *) tb->tb_data; |
1981 | memset(t, 0, sizeof(*t)); | 1979 | memset(t, 0, sizeof(*t)); |
1982 | 1980 | ||
1983 | if (id == RT_TABLE_LOCAL) | ||
1984 | pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION); | ||
1985 | |||
1986 | return tb; | 1981 | return tb; |
1987 | } | 1982 | } |
1988 | 1983 | ||
@@ -2382,7 +2377,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2382 | seq_indent(seq, iter->depth+1); | 2377 | seq_indent(seq, iter->depth+1); |
2383 | seq_printf(seq, " /%d %s %s", li->plen, | 2378 | seq_printf(seq, " /%d %s %s", li->plen, |
2384 | rtn_scope(buf1, sizeof(buf1), | 2379 | rtn_scope(buf1, sizeof(buf1), |
2385 | fa->fa_scope), | 2380 | fa->fa_info->fib_scope), |
2386 | rtn_type(buf2, sizeof(buf2), | 2381 | rtn_type(buf2, sizeof(buf2), |
2387 | fa->fa_type)); | 2382 | fa->fa_type)); |
2388 | if (fa->fa_tos) | 2383 | if (fa->fa_tos) |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a91dc1611081..e5f8a71d3a2a 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -704,7 +704,7 @@ static void icmp_unreach(struct sk_buff *skb) | |||
704 | */ | 704 | */ |
705 | 705 | ||
706 | /* | 706 | /* |
707 | * Check the other end isnt violating RFC 1122. Some routers send | 707 | * Check the other end isn't violating RFC 1122. Some routers send |
708 | * bogus responses to broadcast frames. If you see this message | 708 | * bogus responses to broadcast frames. If you see this message |
709 | * first check your netmask matches at both ends, if it does then | 709 | * first check your netmask matches at both ends, if it does then |
710 | * get the other vendor to fix their kit. | 710 | * get the other vendor to fix their kit. |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 6c0b7f4a3d7d..38f23e721b80 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -73,7 +73,7 @@ int inet_csk_bind_conflict(const struct sock *sk, | |||
73 | !sk2->sk_bound_dev_if || | 73 | !sk2->sk_bound_dev_if || |
74 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { | 74 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { |
75 | if (!reuse || !sk2->sk_reuse || | 75 | if (!reuse || !sk2->sk_reuse || |
76 | ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) { | 76 | sk2->sk_state == TCP_LISTEN) { |
77 | const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); | 77 | const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); |
78 | if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || | 78 | if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || |
79 | sk2_rcv_saddr == sk_rcv_saddr(sk)) | 79 | sk2_rcv_saddr == sk_rcv_saddr(sk)) |
@@ -122,8 +122,7 @@ again: | |||
122 | (tb->num_owners < smallest_size || smallest_size == -1)) { | 122 | (tb->num_owners < smallest_size || smallest_size == -1)) { |
123 | smallest_size = tb->num_owners; | 123 | smallest_size = tb->num_owners; |
124 | smallest_rover = rover; | 124 | smallest_rover = rover; |
125 | if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 && | 125 | if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { |
126 | !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { | ||
127 | spin_unlock(&head->lock); | 126 | spin_unlock(&head->lock); |
128 | snum = smallest_rover; | 127 | snum = smallest_rover; |
129 | goto have_snum; | 128 | goto have_snum; |
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index dd1b20eca1a2..9df4e635fb5f 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c | |||
@@ -354,7 +354,8 @@ static void inetpeer_free_rcu(struct rcu_head *head) | |||
354 | } | 354 | } |
355 | 355 | ||
356 | /* May be called with local BH enabled. */ | 356 | /* May be called with local BH enabled. */ |
357 | static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base) | 357 | static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base, |
358 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]) | ||
358 | { | 359 | { |
359 | int do_free; | 360 | int do_free; |
360 | 361 | ||
@@ -368,7 +369,6 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base) | |||
368 | * We use refcnt=-1 to alert lockless readers this entry is deleted. | 369 | * We use refcnt=-1 to alert lockless readers this entry is deleted. |
369 | */ | 370 | */ |
370 | if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) { | 371 | if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) { |
371 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]; | ||
372 | struct inet_peer __rcu ***stackptr, ***delp; | 372 | struct inet_peer __rcu ***stackptr, ***delp; |
373 | if (lookup(&p->daddr, stack, base) != p) | 373 | if (lookup(&p->daddr, stack, base) != p) |
374 | BUG(); | 374 | BUG(); |
@@ -422,7 +422,7 @@ static struct inet_peer_base *peer_to_base(struct inet_peer *p) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /* May be called with local BH enabled. */ | 424 | /* May be called with local BH enabled. */ |
425 | static int cleanup_once(unsigned long ttl) | 425 | static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH]) |
426 | { | 426 | { |
427 | struct inet_peer *p = NULL; | 427 | struct inet_peer *p = NULL; |
428 | 428 | ||
@@ -454,7 +454,7 @@ static int cleanup_once(unsigned long ttl) | |||
454 | * happen because of entry limits in route cache. */ | 454 | * happen because of entry limits in route cache. */ |
455 | return -1; | 455 | return -1; |
456 | 456 | ||
457 | unlink_from_pool(p, peer_to_base(p)); | 457 | unlink_from_pool(p, peer_to_base(p), stack); |
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
@@ -524,7 +524,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create) | |||
524 | 524 | ||
525 | if (base->total >= inet_peer_threshold) | 525 | if (base->total >= inet_peer_threshold) |
526 | /* Remove one less-recently-used entry. */ | 526 | /* Remove one less-recently-used entry. */ |
527 | cleanup_once(0); | 527 | cleanup_once(0, stack); |
528 | 528 | ||
529 | return p; | 529 | return p; |
530 | } | 530 | } |
@@ -540,6 +540,7 @@ static void peer_check_expire(unsigned long dummy) | |||
540 | { | 540 | { |
541 | unsigned long now = jiffies; | 541 | unsigned long now = jiffies; |
542 | int ttl, total; | 542 | int ttl, total; |
543 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]; | ||
543 | 544 | ||
544 | total = compute_total(); | 545 | total = compute_total(); |
545 | if (total >= inet_peer_threshold) | 546 | if (total >= inet_peer_threshold) |
@@ -548,7 +549,7 @@ static void peer_check_expire(unsigned long dummy) | |||
548 | ttl = inet_peer_maxttl | 549 | ttl = inet_peer_maxttl |
549 | - (inet_peer_maxttl - inet_peer_minttl) / HZ * | 550 | - (inet_peer_maxttl - inet_peer_minttl) / HZ * |
550 | total / inet_peer_threshold * HZ; | 551 | total / inet_peer_threshold * HZ; |
551 | while (!cleanup_once(ttl)) { | 552 | while (!cleanup_once(ttl, stack)) { |
552 | if (jiffies != now) | 553 | if (jiffies != now) |
553 | break; | 554 | break; |
554 | } | 555 | } |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index a1151b8adf3c..b1d282f11be7 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -223,31 +223,30 @@ static void ip_expire(unsigned long arg) | |||
223 | 223 | ||
224 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { | 224 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { |
225 | struct sk_buff *head = qp->q.fragments; | 225 | struct sk_buff *head = qp->q.fragments; |
226 | const struct iphdr *iph; | ||
227 | int err; | ||
226 | 228 | ||
227 | rcu_read_lock(); | 229 | rcu_read_lock(); |
228 | head->dev = dev_get_by_index_rcu(net, qp->iif); | 230 | head->dev = dev_get_by_index_rcu(net, qp->iif); |
229 | if (!head->dev) | 231 | if (!head->dev) |
230 | goto out_rcu_unlock; | 232 | goto out_rcu_unlock; |
231 | 233 | ||
234 | /* skb dst is stale, drop it, and perform route lookup again */ | ||
235 | skb_dst_drop(head); | ||
236 | iph = ip_hdr(head); | ||
237 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, | ||
238 | iph->tos, head->dev); | ||
239 | if (err) | ||
240 | goto out_rcu_unlock; | ||
241 | |||
232 | /* | 242 | /* |
233 | * Only search router table for the head fragment, | 243 | * Only an end host needs to send an ICMP |
234 | * when defraging timeout at PRE_ROUTING HOOK. | 244 | * "Fragment Reassembly Timeout" message, per RFC792. |
235 | */ | 245 | */ |
236 | if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) { | 246 | if (qp->user == IP_DEFRAG_CONNTRACK_IN && |
237 | const struct iphdr *iph = ip_hdr(head); | 247 | skb_rtable(head)->rt_type != RTN_LOCAL) |
238 | int err = ip_route_input(head, iph->daddr, iph->saddr, | 248 | goto out_rcu_unlock; |
239 | iph->tos, head->dev); | ||
240 | if (unlikely(err)) | ||
241 | goto out_rcu_unlock; | ||
242 | |||
243 | /* | ||
244 | * Only an end host needs to send an ICMP | ||
245 | * "Fragment Reassembly Timeout" message, per RFC792. | ||
246 | */ | ||
247 | if (skb_rtable(head)->rt_type != RTN_LOCAL) | ||
248 | goto out_rcu_unlock; | ||
249 | 249 | ||
250 | } | ||
251 | 250 | ||
252 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 251 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
253 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 252 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1906fa35860c..2391b24e8251 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
140 | } else { | 140 | } else { |
141 | dopt->ts_needtime = 0; | 141 | dopt->ts_needtime = 0; |
142 | 142 | ||
143 | if (soffset + 8 <= optlen) { | 143 | if (soffset + 7 <= optlen) { |
144 | __be32 addr; | 144 | __be32 addr; |
145 | 145 | ||
146 | memcpy(&addr, sptr+soffset-1, 4); | 146 | memcpy(&addr, dptr+soffset-1, 4); |
147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { | 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) { |
148 | dopt->ts_needtime = 1; | 148 | dopt->ts_needtime = 1; |
149 | soffset += 8; | 149 | soffset += 8; |
150 | } | 150 | } |
@@ -329,7 +329,7 @@ int ip_options_compile(struct net *net, | |||
329 | pp_ptr = optptr + 2; | 329 | pp_ptr = optptr + 2; |
330 | goto error; | 330 | goto error; |
331 | } | 331 | } |
332 | if (skb) { | 332 | if (rt) { |
333 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); | 333 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); |
334 | opt->is_changed = 1; | 334 | opt->is_changed = 1; |
335 | } | 335 | } |
@@ -371,7 +371,7 @@ int ip_options_compile(struct net *net, | |||
371 | goto error; | 371 | goto error; |
372 | } | 372 | } |
373 | opt->ts = optptr - iph; | 373 | opt->ts = optptr - iph; |
374 | if (skb) { | 374 | if (rt) { |
375 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); | 375 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); |
376 | timeptr = (__be32*)&optptr[optptr[2]+3]; | 376 | timeptr = (__be32*)&optptr[optptr[2]+3]; |
377 | } | 377 | } |
@@ -603,7 +603,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
603 | unsigned long orefdst; | 603 | unsigned long orefdst; |
604 | int err; | 604 | int err; |
605 | 605 | ||
606 | if (!opt->srr) | 606 | if (!opt->srr || !rt) |
607 | return 0; | 607 | return 0; |
608 | 608 | ||
609 | if (skb->pkt_type != PACKET_HOST) | 609 | if (skb->pkt_type != PACKET_HOST) |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 67f241b97649..459c011b1d4a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -603,7 +603,7 @@ slow_path: | |||
603 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 603 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
604 | if (len > mtu) | 604 | if (len > mtu) |
605 | len = mtu; | 605 | len = mtu; |
606 | /* IF: we are not sending upto and including the packet end | 606 | /* IF: we are not sending up to and including the packet end |
607 | then align the next start on an eight byte boundary */ | 607 | then align the next start on an eight byte boundary */ |
608 | if (len < left) { | 608 | if (len < left) { |
609 | len &= ~7; | 609 | len &= ~7; |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 2b097752426b..cbff2ecccf3d 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -1444,7 +1444,7 @@ static int __init ip_auto_config(void) | |||
1444 | root_server_addr = addr; | 1444 | root_server_addr = addr; |
1445 | 1445 | ||
1446 | /* | 1446 | /* |
1447 | * Use defaults whereever applicable. | 1447 | * Use defaults wherever applicable. |
1448 | */ | 1448 | */ |
1449 | if (ic_defaults() < 0) | 1449 | if (ic_defaults() < 0) |
1450 | return -1; | 1450 | return -1; |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index f3c0b549b8e1..4614babdc45f 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -221,9 +221,10 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
221 | return csum; | 221 | return csum; |
222 | } | 222 | } |
223 | 223 | ||
224 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) | 224 | static int nf_ip_route(struct net *net, struct dst_entry **dst, |
225 | struct flowi *fl, bool strict __always_unused) | ||
225 | { | 226 | { |
226 | struct rtable *rt = ip_route_output_key(&init_net, &fl->u.ip4); | 227 | struct rtable *rt = ip_route_output_key(net, &fl->u.ip4); |
227 | if (IS_ERR(rt)) | 228 | if (IS_ERR(rt)) |
228 | return PTR_ERR(rt); | 229 | return PTR_ERR(rt); |
229 | *dst = &rt->dst; | 230 | *dst = &rt->dst; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b5d457c2d76..89bc7e66d598 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -76,7 +76,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Unfortunatly, _b and _mask are not aligned to an int (or long int) | 79 | * Unfortunately, _b and _mask are not aligned to an int (or long int) |
80 | * Some arches dont care, unrolling the loop is a win on them. | 80 | * Some arches dont care, unrolling the loop is a win on them. |
81 | * For other arches, we only have a 16bit alignement. | 81 | * For other arches, we only have a 16bit alignement. |
82 | */ | 82 | */ |
@@ -1874,7 +1874,7 @@ static int __init arp_tables_init(void) | |||
1874 | if (ret < 0) | 1874 | if (ret < 0) |
1875 | goto err1; | 1875 | goto err1; |
1876 | 1876 | ||
1877 | /* Noone else will be downing sem now, so we won't sleep */ | 1877 | /* No one else will be downing sem now, so we won't sleep */ |
1878 | ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); | 1878 | ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); |
1879 | if (ret < 0) | 1879 | if (ret < 0) |
1880 | goto err2; | 1880 | goto err2; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index b09ed0d080f9..704915028009 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -387,7 +387,7 @@ ipt_do_table(struct sk_buff *skb, | |||
387 | verdict = (unsigned)(-v) - 1; | 387 | verdict = (unsigned)(-v) - 1; |
388 | break; | 388 | break; |
389 | } | 389 | } |
390 | if (*stackptr == 0) { | 390 | if (*stackptr <= origptr) { |
391 | e = get_entry(table_base, | 391 | e = get_entry(table_base, |
392 | private->underflow[hook]); | 392 | private->underflow[hook]); |
393 | pr_debug("Underflow (this is normal) " | 393 | pr_debug("Underflow (this is normal) " |
@@ -427,10 +427,10 @@ ipt_do_table(struct sk_buff *skb, | |||
427 | /* Verdict */ | 427 | /* Verdict */ |
428 | break; | 428 | break; |
429 | } while (!acpar.hotdrop); | 429 | } while (!acpar.hotdrop); |
430 | xt_info_rdunlock_bh(); | ||
431 | pr_debug("Exiting %s; resetting sp from %u to %u\n", | 430 | pr_debug("Exiting %s; resetting sp from %u to %u\n", |
432 | __func__, *stackptr, origptr); | 431 | __func__, *stackptr, origptr); |
433 | *stackptr = origptr; | 432 | *stackptr = origptr; |
433 | xt_info_rdunlock_bh(); | ||
434 | #ifdef DEBUG_ALLOW_ALL | 434 | #ifdef DEBUG_ALLOW_ALL |
435 | return NF_ACCEPT; | 435 | return NF_ACCEPT; |
436 | #else | 436 | #else |
@@ -2233,7 +2233,7 @@ static int __init ip_tables_init(void) | |||
2233 | if (ret < 0) | 2233 | if (ret < 0) |
2234 | goto err1; | 2234 | goto err1; |
2235 | 2235 | ||
2236 | /* Noone else will be downing sem now, so we won't sleep */ | 2236 | /* No one else will be downing sem now, so we won't sleep */ |
2237 | ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); | 2237 | ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); |
2238 | if (ret < 0) | 2238 | if (ret < 0) |
2239 | goto err2; | 2239 | goto err2; |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 403ca57f6011..d609ac3cb9a4 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -664,8 +664,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input, | |||
664 | char buffer[PROC_WRITELEN+1]; | 664 | char buffer[PROC_WRITELEN+1]; |
665 | unsigned long nodenum; | 665 | unsigned long nodenum; |
666 | 666 | ||
667 | if (copy_from_user(buffer, input, PROC_WRITELEN)) | 667 | if (size > PROC_WRITELEN) |
668 | return -EIO; | ||
669 | if (copy_from_user(buffer, input, size)) | ||
668 | return -EFAULT; | 670 | return -EFAULT; |
671 | buffer[size] = 0; | ||
669 | 672 | ||
670 | if (*buffer == '+') { | 673 | if (*buffer == '+') { |
671 | nodenum = simple_strtoul(buffer+1, NULL, 10); | 674 | nodenum = simple_strtoul(buffer+1, NULL, 10); |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 21bcf471b25a..9c71b2755ce3 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -521,7 +521,7 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto) | |||
521 | } | 521 | } |
522 | EXPORT_SYMBOL(nf_nat_protocol_register); | 522 | EXPORT_SYMBOL(nf_nat_protocol_register); |
523 | 523 | ||
524 | /* Noone stores the protocol anywhere; simply delete it. */ | 524 | /* No one stores the protocol anywhere; simply delete it. */ |
525 | void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) | 525 | void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) |
526 | { | 526 | { |
527 | spin_lock_bh(&nf_nat_lock); | 527 | spin_lock_bh(&nf_nat_lock); |
@@ -532,7 +532,7 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) | |||
532 | } | 532 | } |
533 | EXPORT_SYMBOL(nf_nat_protocol_unregister); | 533 | EXPORT_SYMBOL(nf_nat_protocol_unregister); |
534 | 534 | ||
535 | /* Noone using conntrack by the time this called. */ | 535 | /* No one using conntrack by the time this called. */ |
536 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | 536 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) |
537 | { | 537 | { |
538 | struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); | 538 | struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e837ffd3edc3..bceaec42c37d 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); |
570 | if (IS_ERR(rt)) { | 570 | if (IS_ERR(rt)) { |
571 | err = PTR_ERR(rt); | 571 | err = PTR_ERR(rt); |
572 | rt = NULL; | ||
572 | goto done; | 573 | goto done; |
573 | } | 574 | } |
574 | } | 575 | } |
@@ -621,7 +622,7 @@ do_confirm: | |||
621 | static void raw_close(struct sock *sk, long timeout) | 622 | static void raw_close(struct sock *sk, long timeout) |
622 | { | 623 | { |
623 | /* | 624 | /* |
624 | * Raw sockets may have direct kernel refereneces. Kill them. | 625 | * Raw sockets may have direct kernel references. Kill them. |
625 | */ | 626 | */ |
626 | ip_ra_control(sk, 0, NULL); | 627 | ip_ra_control(sk, 0, NULL); |
627 | 628 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 870b5182ddd8..99e6e4bb1c72 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -821,7 +821,7 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) | |||
821 | } | 821 | } |
822 | 822 | ||
823 | /* | 823 | /* |
824 | * Pertubation of rt_genid by a small quantity [1..256] | 824 | * Perturbation of rt_genid by a small quantity [1..256] |
825 | * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() | 825 | * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() |
826 | * many times (2^24) without giving recent rt_genid. | 826 | * many times (2^24) without giving recent rt_genid. |
827 | * Jenkins hash is strong enough that litle changes of rt_genid are OK. | 827 | * Jenkins hash is strong enough that litle changes of rt_genid are OK. |
@@ -1191,7 +1191,7 @@ restart: | |||
1191 | #endif | 1191 | #endif |
1192 | /* | 1192 | /* |
1193 | * Since lookup is lockfree, we must make sure | 1193 | * Since lookup is lockfree, we must make sure |
1194 | * previous writes to rt are comitted to memory | 1194 | * previous writes to rt are committed to memory |
1195 | * before making rt visible to other CPUS. | 1195 | * before making rt visible to other CPUS. |
1196 | */ | 1196 | */ |
1197 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); | 1197 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); |
@@ -1593,8 +1593,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1593 | rt->rt_peer_genid = rt_peer_genid(); | 1593 | rt->rt_peer_genid = rt_peer_genid(); |
1594 | } | 1594 | } |
1595 | check_peer_pmtu(dst, peer); | 1595 | check_peer_pmtu(dst, peer); |
1596 | |||
1597 | inet_putpeer(peer); | ||
1598 | } | 1596 | } |
1599 | } | 1597 | } |
1600 | 1598 | ||
@@ -1720,7 +1718,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt) | |||
1720 | 1718 | ||
1721 | rcu_read_lock(); | 1719 | rcu_read_lock(); |
1722 | if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) | 1720 | if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) |
1723 | src = FIB_RES_PREFSRC(res); | 1721 | src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res); |
1724 | else | 1722 | else |
1725 | src = inet_select_addr(rt->dst.dev, rt->rt_gateway, | 1723 | src = inet_select_addr(rt->dst.dev, rt->rt_gateway, |
1726 | RT_SCOPE_UNIVERSE); | 1724 | RT_SCOPE_UNIVERSE); |
@@ -1893,6 +1891,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1893 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1891 | #ifdef CONFIG_IP_ROUTE_CLASSID |
1894 | rth->dst.tclassid = itag; | 1892 | rth->dst.tclassid = itag; |
1895 | #endif | 1893 | #endif |
1894 | rth->rt_route_iif = dev->ifindex; | ||
1896 | rth->rt_iif = dev->ifindex; | 1895 | rth->rt_iif = dev->ifindex; |
1897 | rth->dst.dev = init_net.loopback_dev; | 1896 | rth->dst.dev = init_net.loopback_dev; |
1898 | dev_hold(rth->dst.dev); | 1897 | dev_hold(rth->dst.dev); |
@@ -2028,6 +2027,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
2028 | rth->rt_key_src = saddr; | 2027 | rth->rt_key_src = saddr; |
2029 | rth->rt_src = saddr; | 2028 | rth->rt_src = saddr; |
2030 | rth->rt_gateway = daddr; | 2029 | rth->rt_gateway = daddr; |
2030 | rth->rt_route_iif = in_dev->dev->ifindex; | ||
2031 | rth->rt_iif = in_dev->dev->ifindex; | 2031 | rth->rt_iif = in_dev->dev->ifindex; |
2032 | rth->dst.dev = (out_dev)->dev; | 2032 | rth->dst.dev = (out_dev)->dev; |
2033 | dev_hold(rth->dst.dev); | 2033 | dev_hold(rth->dst.dev); |
@@ -2204,6 +2204,7 @@ local_input: | |||
2204 | #ifdef CONFIG_IP_ROUTE_CLASSID | 2204 | #ifdef CONFIG_IP_ROUTE_CLASSID |
2205 | rth->dst.tclassid = itag; | 2205 | rth->dst.tclassid = itag; |
2206 | #endif | 2206 | #endif |
2207 | rth->rt_route_iif = dev->ifindex; | ||
2207 | rth->rt_iif = dev->ifindex; | 2208 | rth->rt_iif = dev->ifindex; |
2208 | rth->dst.dev = net->loopback_dev; | 2209 | rth->dst.dev = net->loopback_dev; |
2209 | dev_hold(rth->dst.dev); | 2210 | dev_hold(rth->dst.dev); |
@@ -2403,7 +2404,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2403 | rth->rt_mark = oldflp4->flowi4_mark; | 2404 | rth->rt_mark = oldflp4->flowi4_mark; |
2404 | rth->rt_dst = fl4->daddr; | 2405 | rth->rt_dst = fl4->daddr; |
2405 | rth->rt_src = fl4->saddr; | 2406 | rth->rt_src = fl4->saddr; |
2406 | rth->rt_iif = 0; | 2407 | rth->rt_route_iif = 0; |
2408 | rth->rt_iif = oldflp4->flowi4_oif ? : dev_out->ifindex; | ||
2407 | /* get references to the devices that are to be hold by the routing | 2409 | /* get references to the devices that are to be hold by the routing |
2408 | cache entry */ | 2410 | cache entry */ |
2409 | rth->dst.dev = dev_out; | 2411 | rth->dst.dev = dev_out; |
@@ -2617,7 +2619,7 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2617 | fib_select_default(&res); | 2619 | fib_select_default(&res); |
2618 | 2620 | ||
2619 | if (!fl4.saddr) | 2621 | if (!fl4.saddr) |
2620 | fl4.saddr = FIB_RES_PREFSRC(res); | 2622 | fl4.saddr = FIB_RES_PREFSRC(net, res); |
2621 | 2623 | ||
2622 | dev_out = FIB_RES_DEV(res); | 2624 | dev_out = FIB_RES_DEV(res); |
2623 | fl4.flowi4_oif = dev_out->ifindex; | 2625 | fl4.flowi4_oif = dev_out->ifindex; |
@@ -2688,6 +2690,12 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
2688 | { | 2690 | { |
2689 | } | 2691 | } |
2690 | 2692 | ||
2693 | static u32 *ipv4_rt_blackhole_cow_metrics(struct dst_entry *dst, | ||
2694 | unsigned long old) | ||
2695 | { | ||
2696 | return NULL; | ||
2697 | } | ||
2698 | |||
2691 | static struct dst_ops ipv4_dst_blackhole_ops = { | 2699 | static struct dst_ops ipv4_dst_blackhole_ops = { |
2692 | .family = AF_INET, | 2700 | .family = AF_INET, |
2693 | .protocol = cpu_to_be16(ETH_P_IP), | 2701 | .protocol = cpu_to_be16(ETH_P_IP), |
@@ -2696,6 +2704,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = { | |||
2696 | .default_mtu = ipv4_blackhole_default_mtu, | 2704 | .default_mtu = ipv4_blackhole_default_mtu, |
2697 | .default_advmss = ipv4_default_advmss, | 2705 | .default_advmss = ipv4_default_advmss, |
2698 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2706 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
2707 | .cow_metrics = ipv4_rt_blackhole_cow_metrics, | ||
2699 | }; | 2708 | }; |
2700 | 2709 | ||
2701 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) | 2710 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
@@ -2718,6 +2727,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2718 | rt->rt_key_dst = ort->rt_key_dst; | 2727 | rt->rt_key_dst = ort->rt_key_dst; |
2719 | rt->rt_key_src = ort->rt_key_src; | 2728 | rt->rt_key_src = ort->rt_key_src; |
2720 | rt->rt_tos = ort->rt_tos; | 2729 | rt->rt_tos = ort->rt_tos; |
2730 | rt->rt_route_iif = ort->rt_route_iif; | ||
2721 | rt->rt_iif = ort->rt_iif; | 2731 | rt->rt_iif = ort->rt_iif; |
2722 | rt->rt_oif = ort->rt_oif; | 2732 | rt->rt_oif = ort->rt_oif; |
2723 | rt->rt_mark = ort->rt_mark; | 2733 | rt->rt_mark = ort->rt_mark; |
@@ -2727,7 +2737,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2727 | rt->rt_type = ort->rt_type; | 2737 | rt->rt_type = ort->rt_type; |
2728 | rt->rt_dst = ort->rt_dst; | 2738 | rt->rt_dst = ort->rt_dst; |
2729 | rt->rt_src = ort->rt_src; | 2739 | rt->rt_src = ort->rt_src; |
2730 | rt->rt_iif = ort->rt_iif; | ||
2731 | rt->rt_gateway = ort->rt_gateway; | 2740 | rt->rt_gateway = ort->rt_gateway; |
2732 | rt->rt_spec_dst = ort->rt_spec_dst; | 2741 | rt->rt_spec_dst = ort->rt_spec_dst; |
2733 | rt->peer = ort->peer; | 2742 | rt->peer = ort->peer; |
@@ -3221,6 +3230,8 @@ static __net_init int rt_genid_init(struct net *net) | |||
3221 | { | 3230 | { |
3222 | get_random_bytes(&net->ipv4.rt_genid, | 3231 | get_random_bytes(&net->ipv4.rt_genid, |
3223 | sizeof(net->ipv4.rt_genid)); | 3232 | sizeof(net->ipv4.rt_genid)); |
3233 | get_random_bytes(&net->ipv4.dev_addr_genid, | ||
3234 | sizeof(net->ipv4.dev_addr_genid)); | ||
3224 | return 0; | 3235 | return 0; |
3225 | } | 3236 | } |
3226 | 3237 | ||
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1a456652086b..321e6e84dbcc 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -311,7 +311,6 @@ static struct ctl_table ipv4_table[] = { | |||
311 | .mode = 0644, | 311 | .mode = 0644, |
312 | .proc_handler = proc_do_large_bitmap, | 312 | .proc_handler = proc_do_large_bitmap, |
313 | }, | 313 | }, |
314 | #ifdef CONFIG_IP_MULTICAST | ||
315 | { | 314 | { |
316 | .procname = "igmp_max_memberships", | 315 | .procname = "igmp_max_memberships", |
317 | .data = &sysctl_igmp_max_memberships, | 316 | .data = &sysctl_igmp_max_memberships, |
@@ -319,8 +318,6 @@ static struct ctl_table ipv4_table[] = { | |||
319 | .mode = 0644, | 318 | .mode = 0644, |
320 | .proc_handler = proc_dointvec | 319 | .proc_handler = proc_dointvec |
321 | }, | 320 | }, |
322 | |||
323 | #endif | ||
324 | { | 321 | { |
325 | .procname = "igmp_max_msf", | 322 | .procname = "igmp_max_msf", |
326 | .data = &sysctl_igmp_max_msf, | 323 | .data = &sysctl_igmp_max_msf, |
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 34340c9c95fa..f376b05cca81 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
@@ -93,6 +93,7 @@ struct bictcp { | |||
93 | u32 ack_cnt; /* number of acks */ | 93 | u32 ack_cnt; /* number of acks */ |
94 | u32 tcp_cwnd; /* estimated tcp cwnd */ | 94 | u32 tcp_cwnd; /* estimated tcp cwnd */ |
95 | #define ACK_RATIO_SHIFT 4 | 95 | #define ACK_RATIO_SHIFT 4 |
96 | #define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT) | ||
96 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ | 97 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ |
97 | u8 sample_cnt; /* number of samples to decide curr_rtt */ | 98 | u8 sample_cnt; /* number of samples to decide curr_rtt */ |
98 | u8 found; /* the exit point is found? */ | 99 | u8 found; /* the exit point is found? */ |
@@ -398,8 +399,12 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | |||
398 | u32 delay; | 399 | u32 delay; |
399 | 400 | ||
400 | if (icsk->icsk_ca_state == TCP_CA_Open) { | 401 | if (icsk->icsk_ca_state == TCP_CA_Open) { |
401 | cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT; | 402 | u32 ratio = ca->delayed_ack; |
402 | ca->delayed_ack += cnt; | 403 | |
404 | ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; | ||
405 | ratio += cnt; | ||
406 | |||
407 | ca->delayed_ack = min(ratio, ACK_RATIO_LIMIT); | ||
403 | } | 408 | } |
404 | 409 | ||
405 | /* Some calls are for duplicates without timetamps */ | 410 | /* Some calls are for duplicates without timetamps */ |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index da782e7ab16d..bef9f04c22ba 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2659,7 +2659,7 @@ static void DBGUNDO(struct sock *sk, const char *msg) | |||
2659 | #define DBGUNDO(x...) do { } while (0) | 2659 | #define DBGUNDO(x...) do { } while (0) |
2660 | #endif | 2660 | #endif |
2661 | 2661 | ||
2662 | static void tcp_undo_cwr(struct sock *sk, const int undo) | 2662 | static void tcp_undo_cwr(struct sock *sk, const bool undo_ssthresh) |
2663 | { | 2663 | { |
2664 | struct tcp_sock *tp = tcp_sk(sk); | 2664 | struct tcp_sock *tp = tcp_sk(sk); |
2665 | 2665 | ||
@@ -2671,14 +2671,13 @@ static void tcp_undo_cwr(struct sock *sk, const int undo) | |||
2671 | else | 2671 | else |
2672 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1); | 2672 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh << 1); |
2673 | 2673 | ||
2674 | if (undo && tp->prior_ssthresh > tp->snd_ssthresh) { | 2674 | if (undo_ssthresh && tp->prior_ssthresh > tp->snd_ssthresh) { |
2675 | tp->snd_ssthresh = tp->prior_ssthresh; | 2675 | tp->snd_ssthresh = tp->prior_ssthresh; |
2676 | TCP_ECN_withdraw_cwr(tp); | 2676 | TCP_ECN_withdraw_cwr(tp); |
2677 | } | 2677 | } |
2678 | } else { | 2678 | } else { |
2679 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); | 2679 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); |
2680 | } | 2680 | } |
2681 | tcp_moderate_cwnd(tp); | ||
2682 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2681 | tp->snd_cwnd_stamp = tcp_time_stamp; |
2683 | } | 2682 | } |
2684 | 2683 | ||
@@ -2699,7 +2698,7 @@ static int tcp_try_undo_recovery(struct sock *sk) | |||
2699 | * or our original transmission succeeded. | 2698 | * or our original transmission succeeded. |
2700 | */ | 2699 | */ |
2701 | DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans"); | 2700 | DBGUNDO(sk, inet_csk(sk)->icsk_ca_state == TCP_CA_Loss ? "loss" : "retrans"); |
2702 | tcp_undo_cwr(sk, 1); | 2701 | tcp_undo_cwr(sk, true); |
2703 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) | 2702 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Loss) |
2704 | mib_idx = LINUX_MIB_TCPLOSSUNDO; | 2703 | mib_idx = LINUX_MIB_TCPLOSSUNDO; |
2705 | else | 2704 | else |
@@ -2726,7 +2725,7 @@ static void tcp_try_undo_dsack(struct sock *sk) | |||
2726 | 2725 | ||
2727 | if (tp->undo_marker && !tp->undo_retrans) { | 2726 | if (tp->undo_marker && !tp->undo_retrans) { |
2728 | DBGUNDO(sk, "D-SACK"); | 2727 | DBGUNDO(sk, "D-SACK"); |
2729 | tcp_undo_cwr(sk, 1); | 2728 | tcp_undo_cwr(sk, true); |
2730 | tp->undo_marker = 0; | 2729 | tp->undo_marker = 0; |
2731 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); | 2730 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDSACKUNDO); |
2732 | } | 2731 | } |
@@ -2779,7 +2778,7 @@ static int tcp_try_undo_partial(struct sock *sk, int acked) | |||
2779 | tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); | 2778 | tcp_update_reordering(sk, tcp_fackets_out(tp) + acked, 1); |
2780 | 2779 | ||
2781 | DBGUNDO(sk, "Hoe"); | 2780 | DBGUNDO(sk, "Hoe"); |
2782 | tcp_undo_cwr(sk, 0); | 2781 | tcp_undo_cwr(sk, false); |
2783 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); | 2782 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); |
2784 | 2783 | ||
2785 | /* So... Do not make Hoe's retransmit yet. | 2784 | /* So... Do not make Hoe's retransmit yet. |
@@ -2808,7 +2807,7 @@ static int tcp_try_undo_loss(struct sock *sk) | |||
2808 | 2807 | ||
2809 | DBGUNDO(sk, "partial loss"); | 2808 | DBGUNDO(sk, "partial loss"); |
2810 | tp->lost_out = 0; | 2809 | tp->lost_out = 0; |
2811 | tcp_undo_cwr(sk, 1); | 2810 | tcp_undo_cwr(sk, true); |
2812 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); | 2811 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPLOSSUNDO); |
2813 | inet_csk(sk)->icsk_retransmits = 0; | 2812 | inet_csk(sk)->icsk_retransmits = 0; |
2814 | tp->undo_marker = 0; | 2813 | tp->undo_marker = 0; |
@@ -2822,8 +2821,11 @@ static int tcp_try_undo_loss(struct sock *sk) | |||
2822 | static inline void tcp_complete_cwr(struct sock *sk) | 2821 | static inline void tcp_complete_cwr(struct sock *sk) |
2823 | { | 2822 | { |
2824 | struct tcp_sock *tp = tcp_sk(sk); | 2823 | struct tcp_sock *tp = tcp_sk(sk); |
2825 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); | 2824 | /* Do not moderate cwnd if it's already undone in cwr or recovery */ |
2826 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2825 | if (tp->undo_marker && tp->snd_cwnd > tp->snd_ssthresh) { |
2826 | tp->snd_cwnd = tp->snd_ssthresh; | ||
2827 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
2828 | } | ||
2827 | tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR); | 2829 | tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR); |
2828 | } | 2830 | } |
2829 | 2831 | ||
@@ -3494,7 +3496,7 @@ static void tcp_undo_spur_to_response(struct sock *sk, int flag) | |||
3494 | if (flag & FLAG_ECE) | 3496 | if (flag & FLAG_ECE) |
3495 | tcp_ratehalving_spur_to_response(sk); | 3497 | tcp_ratehalving_spur_to_response(sk); |
3496 | else | 3498 | else |
3497 | tcp_undo_cwr(sk, 1); | 3499 | tcp_undo_cwr(sk, true); |
3498 | } | 3500 | } |
3499 | 3501 | ||
3500 | /* F-RTO spurious RTO detection algorithm (RFC4138) | 3502 | /* F-RTO spurious RTO detection algorithm (RFC4138) |
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 656d431c99ad..72f7218b03f5 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * within cong_avoid. | 12 | * within cong_avoid. |
13 | * o Error correcting in remote HZ, therefore remote HZ will be keeped | 13 | * o Error correcting in remote HZ, therefore remote HZ will be keeped |
14 | * on checking and updating. | 14 | * on checking and updating. |
15 | * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne | 15 | * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, since |
16 | * OWD have a similar meaning as RTT. Also correct the buggy formular. | 16 | * OWD have a similar meaning as RTT. Also correct the buggy formular. |
17 | * o Handle reaction for Early Congestion Indication (ECI) within | 17 | * o Handle reaction for Early Congestion Indication (ECI) within |
18 | * pkts_acked, as mentioned within pseudo code. | 18 | * pkts_acked, as mentioned within pseudo code. |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index dfa5beb0c1c8..17388c7f49c4 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -73,7 +73,7 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) | |||
73 | tcp_advance_send_head(sk, skb); | 73 | tcp_advance_send_head(sk, skb); |
74 | tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; | 74 | tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; |
75 | 75 | ||
76 | /* Don't override Nagle indefinately with F-RTO */ | 76 | /* Don't override Nagle indefinitely with F-RTO */ |
77 | if (tp->frto_counter == 2) | 77 | if (tp->frto_counter == 2) |
78 | tp->frto_counter = 3; | 78 | tp->frto_counter = 3; |
79 | 79 | ||
@@ -1003,7 +1003,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, | |||
1003 | int nlen; | 1003 | int nlen; |
1004 | u8 flags; | 1004 | u8 flags; |
1005 | 1005 | ||
1006 | BUG_ON(len > skb->len); | 1006 | if (WARN_ON(len > skb->len)) |
1007 | return -EINVAL; | ||
1007 | 1008 | ||
1008 | nsize = skb_headlen(skb) - len; | 1009 | nsize = skb_headlen(skb) - len; |
1009 | if (nsize < 0) | 1010 | if (nsize < 0) |
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index dc7f43179c9a..05c3b6f0e8e1 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #define TCP_YEAH_DELTA 3 //log minimum fraction of cwnd to be removed on loss | 20 | #define TCP_YEAH_DELTA 3 //log minimum fraction of cwnd to be removed on loss |
21 | #define TCP_YEAH_EPSILON 1 //log maximum fraction to be removed on early decongestion | 21 | #define TCP_YEAH_EPSILON 1 //log maximum fraction to be removed on early decongestion |
22 | #define TCP_YEAH_PHY 8 //lin maximum delta from base | 22 | #define TCP_YEAH_PHY 8 //lin maximum delta from base |
23 | #define TCP_YEAH_RHO 16 //lin minumum number of consecutive rtt to consider competition on loss | 23 | #define TCP_YEAH_RHO 16 //lin minimum number of consecutive rtt to consider competition on loss |
24 | #define TCP_YEAH_ZETA 50 //lin minimum number of state switchs to reset reno_count | 24 | #define TCP_YEAH_ZETA 50 //lin minimum number of state switchs to reset reno_count |
25 | 25 | ||
26 | #define TCP_SCALABLE_AI_CNT 100U | 26 | #define TCP_SCALABLE_AI_CNT 100U |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 588f47af5faf..f87a8eb76f3b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -189,7 +189,7 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
189 | * @sk: socket struct in question | 189 | * @sk: socket struct in question |
190 | * @snum: port number to look up | 190 | * @snum: port number to look up |
191 | * @saddr_comp: AF-dependent comparison of bound local IP addresses | 191 | * @saddr_comp: AF-dependent comparison of bound local IP addresses |
192 | * @hash2_nulladdr: AF-dependant hash value in secondary hash chains, | 192 | * @hash2_nulladdr: AF-dependent hash value in secondary hash chains, |
193 | * with NULL address | 193 | * with NULL address |
194 | */ | 194 | */ |
195 | int udp_lib_get_port(struct sock *sk, unsigned short snum, | 195 | int udp_lib_get_port(struct sock *sk, unsigned short snum, |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 571aa96a175c..2d51840e53a1 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -69,7 +69,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
69 | } | 69 | } |
70 | EXPORT_SYMBOL(xfrm4_prepare_output); | 70 | EXPORT_SYMBOL(xfrm4_prepare_output); |
71 | 71 | ||
72 | static int xfrm4_output_finish(struct sk_buff *skb) | 72 | int xfrm4_output_finish(struct sk_buff *skb) |
73 | { | 73 | { |
74 | #ifdef CONFIG_NETFILTER | 74 | #ifdef CONFIG_NETFILTER |
75 | if (!skb_dst(skb)->xfrm) { | 75 | if (!skb_dst(skb)->xfrm) { |
@@ -86,7 +86,11 @@ static int xfrm4_output_finish(struct sk_buff *skb) | |||
86 | 86 | ||
87 | int xfrm4_output(struct sk_buff *skb) | 87 | int xfrm4_output(struct sk_buff *skb) |
88 | { | 88 | { |
89 | struct dst_entry *dst = skb_dst(skb); | ||
90 | struct xfrm_state *x = dst->xfrm; | ||
91 | |||
89 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, | 92 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, |
90 | NULL, skb_dst(skb)->dev, xfrm4_output_finish, | 93 | NULL, dst->dev, |
94 | x->outer_mode->afinfo->output_finish, | ||
91 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 95 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
92 | } | 96 | } |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 13e0e7f659ff..d20a05e970d8 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -74,6 +74,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
74 | rt->rt_key_dst = fl4->daddr; | 74 | rt->rt_key_dst = fl4->daddr; |
75 | rt->rt_key_src = fl4->saddr; | 75 | rt->rt_key_src = fl4->saddr; |
76 | rt->rt_tos = fl4->flowi4_tos; | 76 | rt->rt_tos = fl4->flowi4_tos; |
77 | rt->rt_route_iif = fl4->flowi4_iif; | ||
77 | rt->rt_iif = fl4->flowi4_iif; | 78 | rt->rt_iif = fl4->flowi4_iif; |
78 | rt->rt_oif = fl4->flowi4_oif; | 79 | rt->rt_oif = fl4->flowi4_oif; |
79 | rt->rt_mark = fl4->flowi4_mark; | 80 | rt->rt_mark = fl4->flowi4_mark; |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 1717c64628d1..805d63ef4340 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -78,6 +78,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { | |||
78 | .init_tempsel = __xfrm4_init_tempsel, | 78 | .init_tempsel = __xfrm4_init_tempsel, |
79 | .init_temprop = xfrm4_init_temprop, | 79 | .init_temprop = xfrm4_init_temprop, |
80 | .output = xfrm4_output, | 80 | .output = xfrm4_output, |
81 | .output_finish = xfrm4_output_finish, | ||
81 | .extract_input = xfrm4_extract_input, | 82 | .extract_input = xfrm4_extract_input, |
82 | .extract_output = xfrm4_extract_output, | 83 | .extract_output = xfrm4_extract_output, |
83 | .transport_finish = xfrm4_transport_finish, | 84 | .transport_finish = xfrm4_transport_finish, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3daaf3c7703c..a7bda0757053 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1084,7 +1084,7 @@ static int ipv6_get_saddr_eval(struct net *net, | |||
1084 | case IPV6_SADDR_RULE_PRIVACY: | 1084 | case IPV6_SADDR_RULE_PRIVACY: |
1085 | { | 1085 | { |
1086 | /* Rule 7: Prefer public address | 1086 | /* Rule 7: Prefer public address |
1087 | * Note: prefer temprary address if use_tempaddr >= 2 | 1087 | * Note: prefer temporary address if use_tempaddr >= 2 |
1088 | */ | 1088 | */ |
1089 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? | 1089 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? |
1090 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : | 1090 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : |
@@ -1968,7 +1968,7 @@ ok: | |||
1968 | * to the stored lifetime since we'll | 1968 | * to the stored lifetime since we'll |
1969 | * be updating the timestamp below, | 1969 | * be updating the timestamp below, |
1970 | * else we'll set it back to the | 1970 | * else we'll set it back to the |
1971 | * minumum. | 1971 | * minimum. |
1972 | */ | 1972 | */ |
1973 | if (prefered_lft != ifp->prefered_lft) { | 1973 | if (prefered_lft != ifp->prefered_lft) { |
1974 | valid_lft = stored_lft; | 1974 | valid_lft = stored_lft; |
@@ -4537,7 +4537,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
4537 | 4537 | ||
4538 | t = p->sysctl; | 4538 | t = p->sysctl; |
4539 | p->sysctl = NULL; | 4539 | p->sysctl = NULL; |
4540 | unregister_sysctl_table(t->sysctl_header); | 4540 | unregister_net_sysctl_table(t->sysctl_header); |
4541 | kfree(t->dev_name); | 4541 | kfree(t->dev_name); |
4542 | kfree(t); | 4542 | kfree(t); |
4543 | } | 4543 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 4b13d5d8890e..afcc7099f96d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -1113,7 +1113,7 @@ static int __init inet6_init(void) | |||
1113 | /* | 1113 | /* |
1114 | * ipngwg API draft makes clear that the correct semantics | 1114 | * ipngwg API draft makes clear that the correct semantics |
1115 | * for TCP and UDP is to consider one TCP and UDP instance | 1115 | * for TCP and UDP is to consider one TCP and UDP instance |
1116 | * in a host availiable by both INET and INET6 APIs and | 1116 | * in a host available by both INET and INET6 APIs and |
1117 | * able to communicate via both network protocols. | 1117 | * able to communicate via both network protocols. |
1118 | */ | 1118 | */ |
1119 | 1119 | ||
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 5aa8ec88f194..59dccfbb5b11 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -371,7 +371,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
371 | iv = esp_tmp_iv(aead, tmp, seqhilen); | 371 | iv = esp_tmp_iv(aead, tmp, seqhilen); |
372 | req = esp_tmp_req(aead, iv); | 372 | req = esp_tmp_req(aead, iv); |
373 | asg = esp_req_sg(aead, req); | 373 | asg = esp_req_sg(aead, req); |
374 | sg = asg + 1; | 374 | sg = asg + sglists; |
375 | 375 | ||
376 | skb->ip_summed = CHECKSUM_NONE; | 376 | skb->ip_summed = CHECKSUM_NONE; |
377 | 377 | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 166054650466..f2c5b0fc0f21 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -44,7 +44,7 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
44 | !sk2->sk_bound_dev_if || | 44 | !sk2->sk_bound_dev_if || |
45 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && | 45 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && |
46 | (!sk->sk_reuse || !sk2->sk_reuse || | 46 | (!sk->sk_reuse || !sk2->sk_reuse || |
47 | ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) && | 47 | sk2->sk_state == TCP_LISTEN) && |
48 | ipv6_rcv_saddr_equal(sk, sk2)) | 48 | ipv6_rcv_saddr_equal(sk, sk2)) |
49 | break; | 49 | break; |
50 | } | 50 | } |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 18208876aa8a..46cf7bea6769 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -779,7 +779,7 @@ slow_path: | |||
779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
780 | if (len > mtu) | 780 | if (len > mtu) |
781 | len = mtu; | 781 | len = mtu; |
782 | /* IF: we are not sending upto and including the packet end | 782 | /* IF: we are not sending up to and including the packet end |
783 | then align the next start on an eight byte boundary */ | 783 | then align the next start on an eight byte boundary */ |
784 | if (len < left) { | 784 | if (len < left) { |
785 | len &= ~7; | 785 | len &= ~7; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 7ff0343e05c7..29e48593bf22 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
663 | skb_pull(skb, (u8 *)encap - skb->data); | 663 | skb_pull(skb, (u8 *)encap - skb->data); |
664 | skb_reset_network_header(skb); | 664 | skb_reset_network_header(skb); |
665 | skb->protocol = htons(ETH_P_IPV6); | 665 | skb->protocol = htons(ETH_P_IPV6); |
666 | skb->ip_summed = 0; | 666 | skb->ip_summed = CHECKSUM_NONE; |
667 | skb->pkt_type = PACKET_HOST; | 667 | skb->pkt_type = PACKET_HOST; |
668 | 668 | ||
669 | skb_tunnel_rx(skb, reg_dev); | 669 | skb_tunnel_rx(skb, reg_dev); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0e49c9db3c98..92f952d093db 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d | |||
341 | case ARPHRD_INFINIBAND: | 341 | case ARPHRD_INFINIBAND: |
342 | ipv6_ib_mc_map(addr, dev->broadcast, buf); | 342 | ipv6_ib_mc_map(addr, dev->broadcast, buf); |
343 | return 0; | 343 | return 0; |
344 | case ARPHRD_IPGRE: | ||
345 | return ipv6_ipgre_mc_map(addr, dev->broadcast, buf); | ||
344 | default: | 346 | default: |
345 | if (dir) { | 347 | if (dir) { |
346 | memcpy(buf, dev->broadcast, dev->addr_len); | 348 | memcpy(buf, dev->broadcast, dev->addr_len); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 39aaca2b4fd2..28bc1f644b7b 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -90,9 +90,18 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | 93 | static int nf_ip6_route(struct net *net, struct dst_entry **dst, |
94 | struct flowi *fl, bool strict) | ||
94 | { | 95 | { |
95 | *dst = ip6_route_output(&init_net, NULL, &fl->u.ip6); | 96 | static const struct ipv6_pinfo fake_pinfo; |
97 | static const struct inet_sock fake_sk = { | ||
98 | /* makes ip6_route_output set RT6_LOOKUP_F_IFACE: */ | ||
99 | .sk.sk_bound_dev_if = 1, | ||
100 | .pinet6 = (struct ipv6_pinfo *) &fake_pinfo, | ||
101 | }; | ||
102 | const void *sk = strict ? &fake_sk : NULL; | ||
103 | |||
104 | *dst = ip6_route_output(net, sk, &fl->u.ip6); | ||
96 | return (*dst)->error; | 105 | return (*dst)->error; |
97 | } | 106 | } |
98 | 107 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index c9598a9067d7..5a1c6f27ffaf 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
410 | verdict = (unsigned)(-v) - 1; | 410 | verdict = (unsigned)(-v) - 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
413 | if (*stackptr == 0) | 413 | if (*stackptr <= origptr) |
414 | e = get_entry(table_base, | 414 | e = get_entry(table_base, |
415 | private->underflow[hook]); | 415 | private->underflow[hook]); |
416 | else | 416 | else |
@@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
441 | break; | 441 | break; |
442 | } while (!acpar.hotdrop); | 442 | } while (!acpar.hotdrop); |
443 | 443 | ||
444 | xt_info_rdunlock_bh(); | ||
445 | *stackptr = origptr; | 444 | *stackptr = origptr; |
445 | xt_info_rdunlock_bh(); | ||
446 | 446 | ||
447 | #ifdef DEBUG_ALLOW_ALL | 447 | #ifdef DEBUG_ALLOW_ALL |
448 | return NF_ACCEPT; | 448 | return NF_ACCEPT; |
@@ -2248,7 +2248,7 @@ static int __init ip6_tables_init(void) | |||
2248 | if (ret < 0) | 2248 | if (ret < 0) |
2249 | goto err1; | 2249 | goto err1; |
2250 | 2250 | ||
2251 | /* Noone else will be downing sem now, so we won't sleep */ | 2251 | /* No one else will be downing sem now, so we won't sleep */ |
2252 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); | 2252 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2253 | if (ret < 0) | 2253 | if (ret < 0) |
2254 | goto err2; | 2254 | goto err2; |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 28e74488a329..a5a4c5dd5396 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
45 | int tcphoff, needs_ack; | 45 | int tcphoff, needs_ack; |
46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
47 | struct ipv6hdr *ip6h; | 47 | struct ipv6hdr *ip6h; |
48 | #define DEFAULT_TOS_VALUE 0x0U | ||
49 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
48 | struct dst_entry *dst = NULL; | 50 | struct dst_entry *dst = NULL; |
49 | u8 proto; | 51 | u8 proto; |
50 | struct flowi6 fl6; | 52 | struct flowi6 fl6; |
@@ -124,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
124 | skb_put(nskb, sizeof(struct ipv6hdr)); | 126 | skb_put(nskb, sizeof(struct ipv6hdr)); |
125 | skb_reset_network_header(nskb); | 127 | skb_reset_network_header(nskb); |
126 | ip6h = ipv6_hdr(nskb); | 128 | ip6h = ipv6_hdr(nskb); |
127 | ip6h->version = 6; | 129 | *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); |
128 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 130 | ip6h->hop_limit = ip6_dst_hoplimit(dst); |
129 | ip6h->nexthdr = IPPROTO_TCP; | 131 | ip6h->nexthdr = IPPROTO_TCP; |
130 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); | 132 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 97c5b21b9674..cdd6d045e42e 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -71,7 +71,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
71 | if (reasm == NULL) | 71 | if (reasm == NULL) |
72 | return NF_STOLEN; | 72 | return NF_STOLEN; |
73 | 73 | ||
74 | /* error occured or not fragmented */ | 74 | /* error occurred or not fragmented */ |
75 | if (reasm == skb) | 75 | if (reasm == skb) |
76 | return NF_ACCEPT; | 76 | return NF_ACCEPT; |
77 | 77 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6814c8722fa7..fd0eec6f88c6 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -153,6 +153,12 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
153 | { | 153 | { |
154 | } | 154 | } |
155 | 155 | ||
156 | static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst, | ||
157 | unsigned long old) | ||
158 | { | ||
159 | return NULL; | ||
160 | } | ||
161 | |||
156 | static struct dst_ops ip6_dst_blackhole_ops = { | 162 | static struct dst_ops ip6_dst_blackhole_ops = { |
157 | .family = AF_INET6, | 163 | .family = AF_INET6, |
158 | .protocol = cpu_to_be16(ETH_P_IPV6), | 164 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -161,6 +167,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
161 | .default_mtu = ip6_blackhole_default_mtu, | 167 | .default_mtu = ip6_blackhole_default_mtu, |
162 | .default_advmss = ip6_default_advmss, | 168 | .default_advmss = ip6_default_advmss, |
163 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 169 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
170 | .cow_metrics = ip6_rt_blackhole_cow_metrics, | ||
164 | }; | 171 | }; |
165 | 172 | ||
166 | static const u32 ip6_template_metrics[RTAX_MAX] = { | 173 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
@@ -854,7 +861,7 @@ static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table | |||
854 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); | 861 | return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); |
855 | } | 862 | } |
856 | 863 | ||
857 | struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | 864 | struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk, |
858 | struct flowi6 *fl6) | 865 | struct flowi6 *fl6) |
859 | { | 866 | { |
860 | int flags = 0; | 867 | int flags = 0; |
@@ -2012,7 +2019,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2012 | rt->dst.output = ip6_output; | 2019 | rt->dst.output = ip6_output; |
2013 | rt->rt6i_dev = net->loopback_dev; | 2020 | rt->rt6i_dev = net->loopback_dev; |
2014 | rt->rt6i_idev = idev; | 2021 | rt->rt6i_idev = idev; |
2015 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); | ||
2016 | rt->dst.obsolete = -1; | 2022 | rt->dst.obsolete = -1; |
2017 | 2023 | ||
2018 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 2024 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 7cb65ef79f9c..6dcf5e7d661b 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -17,6 +17,16 @@ | |||
17 | 17 | ||
18 | static struct ctl_table empty[1]; | 18 | static struct ctl_table empty[1]; |
19 | 19 | ||
20 | static ctl_table ipv6_static_skeleton[] = { | ||
21 | { | ||
22 | .procname = "neigh", | ||
23 | .maxlen = 0, | ||
24 | .mode = 0555, | ||
25 | .child = empty, | ||
26 | }, | ||
27 | { } | ||
28 | }; | ||
29 | |||
20 | static ctl_table ipv6_table_template[] = { | 30 | static ctl_table ipv6_table_template[] = { |
21 | { | 31 | { |
22 | .procname = "route", | 32 | .procname = "route", |
@@ -37,12 +47,6 @@ static ctl_table ipv6_table_template[] = { | |||
37 | .mode = 0644, | 47 | .mode = 0644, |
38 | .proc_handler = proc_dointvec | 48 | .proc_handler = proc_dointvec |
39 | }, | 49 | }, |
40 | { | ||
41 | .procname = "neigh", | ||
42 | .maxlen = 0, | ||
43 | .mode = 0555, | ||
44 | .child = empty, | ||
45 | }, | ||
46 | { } | 50 | { } |
47 | }; | 51 | }; |
48 | 52 | ||
@@ -160,7 +164,7 @@ static struct ctl_table_header *ip6_base; | |||
160 | 164 | ||
161 | int ipv6_static_sysctl_register(void) | 165 | int ipv6_static_sysctl_register(void) |
162 | { | 166 | { |
163 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); | 167 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton); |
164 | if (ip6_base == NULL) | 168 | if (ip6_base == NULL) |
165 | return -ENOMEM; | 169 | return -ENOMEM; |
166 | return 0; | 170 | return 0; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2b0c186862c8..4f49e5dd41bb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -503,6 +503,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
504 | if (IS_ERR(dst)) { | 504 | if (IS_ERR(dst)) { |
505 | err = PTR_ERR(dst); | 505 | err = PTR_ERR(dst); |
506 | dst = NULL; | ||
506 | goto done; | 507 | goto done; |
507 | } | 508 | } |
508 | skb = tcp_make_synack(sk, dst, req, rvp); | 509 | skb = tcp_make_synack(sk, dst, req, rvp); |
@@ -1621,6 +1622,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1621 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1622 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1622 | 1623 | ||
1623 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1624 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1625 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1624 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1626 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1625 | goto reset; | 1627 | goto reset; |
1626 | if (opt_skb) | 1628 | if (opt_skb) |
@@ -1648,7 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1648 | __kfree_skb(opt_skb); | 1650 | __kfree_skb(opt_skb); |
1649 | return 0; | 1651 | return 0; |
1650 | } | 1652 | } |
1651 | } | 1653 | } else |
1654 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1652 | 1655 | ||
1653 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1656 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1654 | goto reset; | 1657 | goto reset; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d7037c006e13..9e305d74b3d4 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -505,6 +505,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
505 | int rc; | 505 | int rc; |
506 | int is_udplite = IS_UDPLITE(sk); | 506 | int is_udplite = IS_UDPLITE(sk); |
507 | 507 | ||
508 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | ||
509 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
510 | |||
508 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 511 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
509 | goto drop; | 512 | goto drop; |
510 | 513 | ||
@@ -1332,7 +1335,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) | |||
1332 | skb->ip_summed = CHECKSUM_NONE; | 1335 | skb->ip_summed = CHECKSUM_NONE; |
1333 | 1336 | ||
1334 | /* Check if there is enough headroom to insert fragment header. */ | 1337 | /* Check if there is enough headroom to insert fragment header. */ |
1335 | if ((skb_headroom(skb) < frag_hdr_sz) && | 1338 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && |
1336 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 1339 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) |
1337 | goto out; | 1340 | goto out; |
1338 | 1341 | ||
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 8e688b3de9ab..49a91c5f5623 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -79,7 +79,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
79 | } | 79 | } |
80 | EXPORT_SYMBOL(xfrm6_prepare_output); | 80 | EXPORT_SYMBOL(xfrm6_prepare_output); |
81 | 81 | ||
82 | static int xfrm6_output_finish(struct sk_buff *skb) | 82 | int xfrm6_output_finish(struct sk_buff *skb) |
83 | { | 83 | { |
84 | #ifdef CONFIG_NETFILTER | 84 | #ifdef CONFIG_NETFILTER |
85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | 85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; |
@@ -97,9 +97,9 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && | 97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && |
98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
99 | dst_allfrag(skb_dst(skb)))) { | 99 | dst_allfrag(skb_dst(skb)))) { |
100 | return ip6_fragment(skb, xfrm6_output_finish); | 100 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |
101 | } | 101 | } |
102 | return xfrm6_output_finish(skb); | 102 | return x->outer_mode->afinfo->output_finish(skb); |
103 | } | 103 | } |
104 | 104 | ||
105 | int xfrm6_output(struct sk_buff *skb) | 105 | int xfrm6_output(struct sk_buff *skb) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index afe941e9415c..248f0b2a7ee9 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -178,6 +178,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | |||
178 | .tmpl_sort = __xfrm6_tmpl_sort, | 178 | .tmpl_sort = __xfrm6_tmpl_sort, |
179 | .state_sort = __xfrm6_state_sort, | 179 | .state_sort = __xfrm6_state_sort, |
180 | .output = xfrm6_output, | 180 | .output = xfrm6_output, |
181 | .output_finish = xfrm6_output_finish, | ||
181 | .extract_input = xfrm6_extract_input, | 182 | .extract_input = xfrm6_extract_input, |
182 | .extract_output = xfrm6_extract_output, | 183 | .extract_output = xfrm6_extract_output, |
183 | .transport_finish = xfrm6_transport_finish, | 184 | .transport_finish = xfrm6_transport_finish, |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 2731b51923d1..9680226640ef 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -148,7 +148,6 @@ static void ipx_destroy_socket(struct sock *sk) | |||
148 | ipx_remove_socket(sk); | 148 | ipx_remove_socket(sk); |
149 | skb_queue_purge(&sk->sk_receive_queue); | 149 | skb_queue_purge(&sk->sk_receive_queue); |
150 | sk_refcnt_debug_dec(sk); | 150 | sk_refcnt_debug_dec(sk); |
151 | sock_put(sk); | ||
152 | } | 151 | } |
153 | 152 | ||
154 | /* | 153 | /* |
@@ -1404,6 +1403,7 @@ static int ipx_release(struct socket *sock) | |||
1404 | sk_refcnt_debug_release(sk); | 1403 | sk_refcnt_debug_release(sk); |
1405 | ipx_destroy_socket(sk); | 1404 | ipx_destroy_socket(sk); |
1406 | release_sock(sk); | 1405 | release_sock(sk); |
1406 | sock_put(sk); | ||
1407 | out: | 1407 | out: |
1408 | return 0; | 1408 | return 0; |
1409 | } | 1409 | } |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index c9890e25cd4c..cc616974a447 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -1297,8 +1297,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1297 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ | 1297 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ |
1298 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | | 1298 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | |
1299 | MSG_NOSIGNAL)) { | 1299 | MSG_NOSIGNAL)) { |
1300 | err = -EINVAL; | 1300 | return -EINVAL; |
1301 | goto out; | ||
1302 | } | 1301 | } |
1303 | 1302 | ||
1304 | lock_sock(sk); | 1303 | lock_sock(sk); |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 5b743bdd89ba..36477538cea8 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, | |||
656 | n = 1; | 656 | n = 1; |
657 | 657 | ||
658 | name_len = fp[n++]; | 658 | name_len = fp[n++]; |
659 | |||
660 | IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); | ||
661 | |||
659 | memcpy(name, fp+n, name_len); n+=name_len; | 662 | memcpy(name, fp+n, name_len); n+=name_len; |
660 | name[name_len] = '\0'; | 663 | name[name_len] = '\0'; |
661 | 664 | ||
662 | attr_len = fp[n++]; | 665 | attr_len = fp[n++]; |
666 | |||
667 | IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); | ||
668 | |||
663 | memcpy(attr, fp+n, attr_len); n+=attr_len; | 669 | memcpy(attr, fp+n, attr_len); n+=attr_len; |
664 | attr[attr_len] = '\0'; | 670 | attr[attr_len] = '\0'; |
665 | 671 | ||
diff --git a/net/irda/irlap.c b/net/irda/irlap.c index 783c5f367d29..005b424494a0 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c | |||
@@ -165,7 +165,7 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos, | |||
165 | 165 | ||
166 | irlap_apply_default_connection_parameters(self); | 166 | irlap_apply_default_connection_parameters(self); |
167 | 167 | ||
168 | self->N3 = 3; /* # connections attemts to try before giving up */ | 168 | self->N3 = 3; /* # connections attempts to try before giving up */ |
169 | 169 | ||
170 | self->state = LAP_NDM; | 170 | self->state = LAP_NDM; |
171 | 171 | ||
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index d434c8880745..bb47021c9a55 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c | |||
@@ -708,7 +708,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, | |||
708 | 708 | ||
709 | self->frame_sent = TRUE; | 709 | self->frame_sent = TRUE; |
710 | } | 710 | } |
711 | /* Readjust our timer to accomodate devices | 711 | /* Readjust our timer to accommodate devices |
712 | * doing faster or slower discovery than us... | 712 | * doing faster or slower discovery than us... |
713 | * Jean II */ | 713 | * Jean II */ |
714 | irlap_start_query_timer(self, info->S, info->s); | 714 | irlap_start_query_timer(self, info->S, info->s); |
@@ -931,7 +931,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, | |||
931 | irlap_send_rr_frame(self, CMD_FRAME); | 931 | irlap_send_rr_frame(self, CMD_FRAME); |
932 | 932 | ||
933 | /* The timer is set to half the normal timer to quickly | 933 | /* The timer is set to half the normal timer to quickly |
934 | * detect a failure to negociate the new connection | 934 | * detect a failure to negotiate the new connection |
935 | * parameters. IrLAP 6.11.3.2, note 3. | 935 | * parameters. IrLAP 6.11.3.2, note 3. |
936 | * Note that currently we don't process this failure | 936 | * Note that currently we don't process this failure |
937 | * properly, as we should do a quick disconnect. | 937 | * properly, as we should do a quick disconnect. |
@@ -1052,7 +1052,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, | |||
1052 | return -EPROTO; | 1052 | return -EPROTO; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | /* Substract space used by this skb */ | 1055 | /* Subtract space used by this skb */ |
1056 | self->bytes_left -= skb->len; | 1056 | self->bytes_left -= skb->len; |
1057 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ | 1057 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ |
1058 | /* Window has been adjusted for the max packet | 1058 | /* Window has been adjusted for the max packet |
@@ -1808,7 +1808,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, | |||
1808 | 1808 | ||
1809 | return -EPROTO; /* Try again later */ | 1809 | return -EPROTO; /* Try again later */ |
1810 | } | 1810 | } |
1811 | /* Substract space used by this skb */ | 1811 | /* Subtract space used by this skb */ |
1812 | self->bytes_left -= skb->len; | 1812 | self->bytes_left -= skb->len; |
1813 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ | 1813 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ |
1814 | /* Window has been adjusted for the max packet | 1814 | /* Window has been adjusted for the max packet |
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 688222cbf55b..8c004161a843 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -848,7 +848,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) | |||
848 | * though IrLAP is currently sending the *last* frame of the | 848 | * though IrLAP is currently sending the *last* frame of the |
849 | * tx-window, the driver most likely has only just started | 849 | * tx-window, the driver most likely has only just started |
850 | * sending the *first* frame of the same tx-window. | 850 | * sending the *first* frame of the same tx-window. |
851 | * I.e. we are always at the very begining of or Tx window. | 851 | * I.e. we are always at the very beginning of or Tx window. |
852 | * Now, we are supposed to set the final timer from the end | 852 | * Now, we are supposed to set the final timer from the end |
853 | * of our tx-window to let the other peer reply. So, we need | 853 | * of our tx-window to let the other peer reply. So, we need |
854 | * to add extra time to compensate for the fact that we | 854 | * to add extra time to compensate for the fact that we |
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index c1fb5db81042..9505a7d06f1a 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c | |||
@@ -498,7 +498,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event, | |||
498 | switch (event) { | 498 | switch (event) { |
499 | #ifdef CONFIG_IRDA_ULTRA | 499 | #ifdef CONFIG_IRDA_ULTRA |
500 | case LM_UDATA_INDICATION: | 500 | case LM_UDATA_INDICATION: |
501 | /* This is most bizzare. Those packets are aka unreliable | 501 | /* This is most bizarre. Those packets are aka unreliable |
502 | * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. | 502 | * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. |
503 | * Why do we pass them as Ultra ??? Jean II */ | 503 | * Why do we pass them as Ultra ??? Jean II */ |
504 | irlmp_connless_data_indication(self, skb); | 504 | irlmp_connless_data_indication(self, skb); |
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index 0d82ff5aeff1..979ecb2435a7 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -73,7 +73,7 @@ | |||
73 | * Infinite thanks to those brave souls for providing the infrastructure | 73 | * Infinite thanks to those brave souls for providing the infrastructure |
74 | * upon which IrNET is built. | 74 | * upon which IrNET is built. |
75 | * | 75 | * |
76 | * Thanks to all my collegues in HP for helping me. In particular, | 76 | * Thanks to all my colleagues in HP for helping me. In particular, |
77 | * thanks to Salil Pradhan and Bill Serra for W2k testing... | 77 | * thanks to Salil Pradhan and Bill Serra for W2k testing... |
78 | * Thanks to Luiz Magalhaes for irnetd and much testing... | 78 | * Thanks to Luiz Magalhaes for irnetd and much testing... |
79 | * | 79 | * |
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 7c567b8aa89a..2bb2beb6a373 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap, | |||
105 | while(isspace(start[length - 1])) | 105 | while(isspace(start[length - 1])) |
106 | length--; | 106 | length--; |
107 | 107 | ||
108 | DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, | ||
109 | -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); | ||
110 | |||
108 | /* Copy the name for later reuse */ | 111 | /* Copy the name for later reuse */ |
109 | memcpy(ap->rname, start + 5, length - 5); | 112 | memcpy(ap->rname, start + 5, length - 5); |
110 | ap->rname[length - 5] = '\0'; | 113 | ap->rname[length - 5] = '\0'; |
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 849aaf0dabb5..9715e6e5900b 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c | |||
@@ -40,7 +40,7 @@ | |||
40 | * o the hash function for ints is pathetic (but could be changed) | 40 | * o the hash function for ints is pathetic (but could be changed) |
41 | * o locking is sometime suspicious (especially during enumeration) | 41 | * o locking is sometime suspicious (especially during enumeration) |
42 | * o most users have only a few elements (== overhead) | 42 | * o most users have only a few elements (== overhead) |
43 | * o most users never use seach, so don't benefit from hashing | 43 | * o most users never use search, so don't benefit from hashing |
44 | * Problem already fixed : | 44 | * Problem already fixed : |
45 | * o not 64 bit compliant (most users do hashv = (int) self) | 45 | * o not 64 bit compliant (most users do hashv = (int) self) |
46 | * o hashbin_remove() is broken => use hashbin_remove_this() | 46 | * o hashbin_remove() is broken => use hashbin_remove_this() |
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index f6054f9ccbe3..9d9af4606970 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -1193,7 +1193,7 @@ EXPORT_SYMBOL(irttp_connect_request); | |||
1193 | /* | 1193 | /* |
1194 | * Function irttp_connect_confirm (handle, qos, skb) | 1194 | * Function irttp_connect_confirm (handle, qos, skb) |
1195 | * | 1195 | * |
1196 | * Sevice user confirms TSAP connection with peer. | 1196 | * Service user confirms TSAP connection with peer. |
1197 | * | 1197 | * |
1198 | */ | 1198 | */ |
1199 | static void irttp_connect_confirm(void *instance, void *sap, | 1199 | static void irttp_connect_confirm(void *instance, void *sap, |
diff --git a/net/irda/qos.c b/net/irda/qos.c index 2b00974e5bae..1b51bcf42394 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c | |||
@@ -39,16 +39,16 @@ | |||
39 | #include <net/irda/irlap_frame.h> | 39 | #include <net/irda/irlap_frame.h> |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Maximum values of the baud rate we negociate with the other end. | 42 | * Maximum values of the baud rate we negotiate with the other end. |
43 | * Most often, you don't have to change that, because Linux-IrDA will | 43 | * Most often, you don't have to change that, because Linux-IrDA will |
44 | * use the maximum offered by the link layer, which usually works fine. | 44 | * use the maximum offered by the link layer, which usually works fine. |
45 | * In some very rare cases, you may want to limit it to lower speeds... | 45 | * In some very rare cases, you may want to limit it to lower speeds... |
46 | */ | 46 | */ |
47 | int sysctl_max_baud_rate = 16000000; | 47 | int sysctl_max_baud_rate = 16000000; |
48 | /* | 48 | /* |
49 | * Maximum value of the lap disconnect timer we negociate with the other end. | 49 | * Maximum value of the lap disconnect timer we negotiate with the other end. |
50 | * Most often, the value below represent the best compromise, but some user | 50 | * Most often, the value below represent the best compromise, but some user |
51 | * may want to keep the LAP alive longuer or shorter in case of link failure. | 51 | * may want to keep the LAP alive longer or shorter in case of link failure. |
52 | * Remember that the threshold time (early warning) is fixed to 3s... | 52 | * Remember that the threshold time (early warning) is fixed to 3s... |
53 | */ | 53 | */ |
54 | int sysctl_max_noreply_time = 12; | 54 | int sysctl_max_noreply_time = 12; |
@@ -411,7 +411,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos) | |||
411 | * Fix tx data size according to user limits - Jean II | 411 | * Fix tx data size according to user limits - Jean II |
412 | */ | 412 | */ |
413 | if (qos->data_size.value > sysctl_max_tx_data_size) | 413 | if (qos->data_size.value > sysctl_max_tx_data_size) |
414 | /* Allow non discrete adjustement to avoid loosing capacity */ | 414 | /* Allow non discrete adjustement to avoid losing capacity */ |
415 | qos->data_size.value = sysctl_max_tx_data_size; | 415 | qos->data_size.value = sysctl_max_tx_data_size; |
416 | /* | 416 | /* |
417 | * Override Tx window if user request it. - Jean II | 417 | * Override Tx window if user request it. - Jean II |
diff --git a/net/irda/timer.c b/net/irda/timer.c index 0335ba0cc593..f418cb2ad49c 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c | |||
@@ -59,7 +59,7 @@ void irlap_start_query_timer(struct irlap_cb *self, int S, int s) | |||
59 | * slot time, plus add some extra time to properly receive the last | 59 | * slot time, plus add some extra time to properly receive the last |
60 | * discovery packet (which is longer due to extra discovery info), | 60 | * discovery packet (which is longer due to extra discovery info), |
61 | * to avoid messing with for incomming connections requests and | 61 | * to avoid messing with for incomming connections requests and |
62 | * to accomodate devices that perform discovery slower than us. | 62 | * to accommodate devices that perform discovery slower than us. |
63 | * Jean II */ | 63 | * Jean II */ |
64 | timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s) | 64 | timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s) |
65 | + XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT); | 65 | + XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 9637e45744fa..986b2a5e8769 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -250,7 +250,7 @@ static struct device *af_iucv_dev; | |||
250 | * PRMDATA[0..6] socket data (max 7 bytes); | 250 | * PRMDATA[0..6] socket data (max 7 bytes); |
251 | * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) | 251 | * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) |
252 | * | 252 | * |
253 | * The socket data length is computed by substracting the socket data length | 253 | * The socket data length is computed by subtracting the socket data length |
254 | * value from 0xFF. | 254 | * value from 0xFF. |
255 | * If the socket data len is greater 7, then PRMDATA can be used for special | 255 | * If the socket data len is greater 7, then PRMDATA can be used for special |
256 | * notifications (see iucv_sock_shutdown); and further, | 256 | * notifications (see iucv_sock_shutdown); and further, |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 1ee5dab3cfae..8f156bd86be7 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -735,7 +735,7 @@ static void iucv_cleanup_queue(void) | |||
735 | struct iucv_irq_list *p, *n; | 735 | struct iucv_irq_list *p, *n; |
736 | 736 | ||
737 | /* | 737 | /* |
738 | * When a path is severed, the pathid can be reused immediatly | 738 | * When a path is severed, the pathid can be reused immediately |
739 | * on a iucv connect or a connection pending interrupt. Remove | 739 | * on a iucv connect or a connection pending interrupt. Remove |
740 | * all entries from the task queue that refer to a stale pathid | 740 | * all entries from the task queue that refer to a stale pathid |
741 | * (iucv_path_table[ix] == NULL). Only then do the iucv connect | 741 | * (iucv_path_table[ix] == NULL). Only then do the iucv connect |
@@ -807,7 +807,7 @@ void iucv_unregister(struct iucv_handler *handler, int smp) | |||
807 | spin_lock_bh(&iucv_table_lock); | 807 | spin_lock_bh(&iucv_table_lock); |
808 | /* Remove handler from the iucv_handler_list. */ | 808 | /* Remove handler from the iucv_handler_list. */ |
809 | list_del_init(&handler->list); | 809 | list_del_init(&handler->list); |
810 | /* Sever all pathids still refering to the handler. */ | 810 | /* Sever all pathids still referring to the handler. */ |
811 | list_for_each_entry_safe(p, n, &handler->paths, list) { | 811 | list_for_each_entry_safe(p, n, &handler->paths, list) { |
812 | iucv_sever_pathid(p->pathid, NULL); | 812 | iucv_sever_pathid(p->pathid, NULL); |
813 | iucv_path_table[p->pathid] = NULL; | 813 | iucv_path_table[p->pathid] = NULL; |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 8d9ce0accc98..a8193f52c13c 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
@@ -283,7 +283,7 @@ static __net_init int l2tp_eth_init_net(struct net *net) | |||
283 | return 0; | 283 | return 0; |
284 | } | 284 | } |
285 | 285 | ||
286 | static __net_initdata struct pernet_operations l2tp_eth_net_ops = { | 286 | static struct pernet_operations l2tp_eth_net_ops = { |
287 | .init = l2tp_eth_init_net, | 287 | .init = l2tp_eth_init_net, |
288 | .id = &l2tp_eth_net_id, | 288 | .id = &l2tp_eth_net_id, |
289 | .size = sizeof(struct l2tp_eth_net), | 289 | .size = sizeof(struct l2tp_eth_net), |
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index fce9bd3bd3fe..5c04f3e42704 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
@@ -667,7 +667,7 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | |||
667 | MODULE_DESCRIPTION("L2TP over IP"); | 667 | MODULE_DESCRIPTION("L2TP over IP"); |
668 | MODULE_VERSION("1.0"); | 668 | MODULE_VERSION("1.0"); |
669 | 669 | ||
670 | /* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like | 670 | /* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like |
671 | * enums | 671 | * enums |
672 | */ | 672 | */ |
673 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP); | 673 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP); |
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 058f1e9a9128..903242111317 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c | |||
@@ -121,8 +121,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb) | |||
121 | s32 data_size = ntohs(pdulen) - llc_len; | 121 | s32 data_size = ntohs(pdulen) - llc_len; |
122 | 122 | ||
123 | if (data_size < 0 || | 123 | if (data_size < 0 || |
124 | ((skb_tail_pointer(skb) - | 124 | !pskb_may_pull(skb, data_size)) |
125 | (u8 *)pdu) - llc_len) < data_size) | ||
126 | return 0; | 125 | return 0; |
127 | if (unlikely(pskb_trim_rcsum(skb, data_size))) | 126 | if (unlikely(pskb_trim_rcsum(skb, data_size))) |
128 | return 0; | 127 | return 0; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 334213571ad0..44049733c4ea 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1504,6 +1504,8 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1504 | enum ieee80211_smps_mode old_req; | 1504 | enum ieee80211_smps_mode old_req; |
1505 | int err; | 1505 | int err; |
1506 | 1506 | ||
1507 | lockdep_assert_held(&sdata->u.mgd.mtx); | ||
1508 | |||
1507 | old_req = sdata->u.mgd.req_smps; | 1509 | old_req = sdata->u.mgd.req_smps; |
1508 | sdata->u.mgd.req_smps = smps_mode; | 1510 | sdata->u.mgd.req_smps = smps_mode; |
1509 | 1511 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index dacace6b1393..9ea7c0d0103f 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -177,9 +177,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | |||
177 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 177 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
178 | return -EOPNOTSUPP; | 178 | return -EOPNOTSUPP; |
179 | 179 | ||
180 | mutex_lock(&local->iflist_mtx); | 180 | mutex_lock(&sdata->u.mgd.mtx); |
181 | err = __ieee80211_request_smps(sdata, smps_mode); | 181 | err = __ieee80211_request_smps(sdata, smps_mode); |
182 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&sdata->u.mgd.mtx); |
183 | 183 | ||
184 | return err; | 184 | return err; |
185 | } | 185 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a40401701424..c18396c248d7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -97,7 +97,7 @@ struct ieee80211_bss { | |||
97 | size_t supp_rates_len; | 97 | size_t supp_rates_len; |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * During assocation, we save an ERP value from a probe response so | 100 | * During association, we save an ERP value from a probe response so |
101 | * that we can feed ERP info to the driver when handling the | 101 | * that we can feed ERP info to the driver when handling the |
102 | * association completes. these fields probably won't be up-to-date | 102 | * association completes. these fields probably won't be up-to-date |
103 | * otherwise, you probably don't want to use them. | 103 | * otherwise, you probably don't want to use them. |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 8c02469b7176..af3c56482c80 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -342,7 +342,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
342 | if (IS_ERR(key->u.ccmp.tfm)) { | 342 | if (IS_ERR(key->u.ccmp.tfm)) { |
343 | err = PTR_ERR(key->u.ccmp.tfm); | 343 | err = PTR_ERR(key->u.ccmp.tfm); |
344 | kfree(key); | 344 | kfree(key); |
345 | key = ERR_PTR(err); | 345 | return ERR_PTR(err); |
346 | } | 346 | } |
347 | break; | 347 | break; |
348 | case WLAN_CIPHER_SUITE_AES_CMAC: | 348 | case WLAN_CIPHER_SUITE_AES_CMAC: |
@@ -360,7 +360,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
360 | if (IS_ERR(key->u.aes_cmac.tfm)) { | 360 | if (IS_ERR(key->u.aes_cmac.tfm)) { |
361 | err = PTR_ERR(key->u.aes_cmac.tfm); | 361 | err = PTR_ERR(key->u.aes_cmac.tfm); |
362 | kfree(key); | 362 | kfree(key); |
363 | key = ERR_PTR(err); | 363 | return ERR_PTR(err); |
364 | } | 364 | } |
365 | break; | 365 | break; |
366 | } | 366 | } |
@@ -400,11 +400,12 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
400 | { | 400 | { |
401 | struct ieee80211_key *old_key; | 401 | struct ieee80211_key *old_key; |
402 | int idx, ret; | 402 | int idx, ret; |
403 | bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | 403 | bool pairwise; |
404 | 404 | ||
405 | BUG_ON(!sdata); | 405 | BUG_ON(!sdata); |
406 | BUG_ON(!key); | 406 | BUG_ON(!key); |
407 | 407 | ||
408 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | ||
408 | idx = key->conf.keyidx; | 409 | idx = key->conf.keyidx; |
409 | key->local = sdata->local; | 410 | key->local = sdata->local; |
410 | key->sdata = sdata; | 411 | key->sdata = sdata; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 8d65b47d9837..336ca9d0c5c4 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -628,7 +628,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
628 | * | 628 | * |
629 | * @mpath: mesh path whose queue has to be freed | 629 | * @mpath: mesh path whose queue has to be freed |
630 | * | 630 | * |
631 | * Locking: the function must me called withing a rcu_read_lock region | 631 | * Locking: the function must me called within a rcu_read_lock region |
632 | */ | 632 | */ |
633 | void mesh_path_flush_pending(struct mesh_path *mpath) | 633 | void mesh_path_flush_pending(struct mesh_path *mpath) |
634 | { | 634 | { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 8212a8bebf06..c06aa3ac6b9d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -259,7 +259,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
259 | } | 259 | } |
260 | } | 260 | } |
261 | 261 | ||
262 | /* try to sample up to half of the availble rates during each interval */ | 262 | /* try to sample up to half of the available rates during each interval */ |
263 | mi->sample_count *= 4; | 263 | mi->sample_count *= 4; |
264 | 264 | ||
265 | cur_prob = 0; | 265 | cur_prob = 0; |
@@ -659,18 +659,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
659 | struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; | 659 | struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; |
660 | struct ieee80211_local *local = hw_to_local(mp->hw); | 660 | struct ieee80211_local *local = hw_to_local(mp->hw); |
661 | u16 sta_cap = sta->ht_cap.cap; | 661 | u16 sta_cap = sta->ht_cap.cap; |
662 | int n_supported = 0; | ||
662 | int ack_dur; | 663 | int ack_dur; |
663 | int stbc; | 664 | int stbc; |
664 | int i; | 665 | int i; |
665 | 666 | ||
666 | /* fall back to the old minstrel for legacy stations */ | 667 | /* fall back to the old minstrel for legacy stations */ |
667 | if (!sta->ht_cap.ht_supported) { | 668 | if (!sta->ht_cap.ht_supported) |
668 | msp->is_ht = false; | 669 | goto use_legacy; |
669 | memset(&msp->legacy, 0, sizeof(msp->legacy)); | ||
670 | msp->legacy.r = msp->ratelist; | ||
671 | msp->legacy.sample_table = msp->sample_table; | ||
672 | return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); | ||
673 | } | ||
674 | 670 | ||
675 | BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != | 671 | BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != |
676 | MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); | 672 | MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS); |
@@ -725,7 +721,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
725 | 721 | ||
726 | mi->groups[i].supported = | 722 | mi->groups[i].supported = |
727 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; | 723 | mcs->rx_mask[minstrel_mcs_groups[i].streams - 1]; |
724 | |||
725 | if (mi->groups[i].supported) | ||
726 | n_supported++; | ||
728 | } | 727 | } |
728 | |||
729 | if (!n_supported) | ||
730 | goto use_legacy; | ||
731 | |||
732 | return; | ||
733 | |||
734 | use_legacy: | ||
735 | msp->is_ht = false; | ||
736 | memset(&msp->legacy, 0, sizeof(msp->legacy)); | ||
737 | msp->legacy.r = msp->ratelist; | ||
738 | msp->legacy.sample_table = msp->sample_table; | ||
739 | return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); | ||
729 | } | 740 | } |
730 | 741 | ||
731 | static void | 742 | static void |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 6510f8ee738e..19111c7bf454 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -77,7 +77,7 @@ union rc_pid_event_data { | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | struct rc_pid_event { | 79 | struct rc_pid_event { |
80 | /* The time when the event occured */ | 80 | /* The time when the event occurred */ |
81 | unsigned long timestamp; | 81 | unsigned long timestamp; |
82 | 82 | ||
83 | /* Event ID number */ | 83 | /* Event ID number */ |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5c1930ba8ebe..c5d4530d8284 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -381,7 +381,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
381 | * specs were sane enough this time around to require padding each A-MSDU | 381 | * specs were sane enough this time around to require padding each A-MSDU |
382 | * subframe to a length that is a multiple of four. | 382 | * subframe to a length that is a multiple of four. |
383 | * | 383 | * |
384 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and | 384 | * Padding like Atheros hardware adds which is between the 802.11 header and |
385 | * the payload is not supported, the driver is required to move the 802.11 | 385 | * the payload is not supported, the driver is required to move the 802.11 |
386 | * header to be directly in front of the payload in that case. | 386 | * header to be directly in front of the payload in that case. |
387 | */ | 387 | */ |
@@ -612,7 +612,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
612 | skipped++; | 612 | skipped++; |
613 | continue; | 613 | continue; |
614 | } | 614 | } |
615 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | 615 | if (skipped && |
616 | !time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
616 | HT_RX_REORDER_BUF_TIMEOUT)) | 617 | HT_RX_REORDER_BUF_TIMEOUT)) |
617 | goto set_release_timer; | 618 | goto set_release_timer; |
618 | 619 | ||
@@ -2540,7 +2541,6 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2540 | * same TID from the same station | 2541 | * same TID from the same station |
2541 | */ | 2542 | */ |
2542 | rx->skb = skb; | 2543 | rx->skb = skb; |
2543 | rx->flags = 0; | ||
2544 | 2544 | ||
2545 | CALL_RXH(ieee80211_rx_h_decrypt) | 2545 | CALL_RXH(ieee80211_rx_h_decrypt) |
2546 | CALL_RXH(ieee80211_rx_h_check_more_data) | 2546 | CALL_RXH(ieee80211_rx_h_check_more_data) |
@@ -2611,6 +2611,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2611 | .sdata = sta->sdata, | 2611 | .sdata = sta->sdata, |
2612 | .local = sta->local, | 2612 | .local = sta->local, |
2613 | .queue = tid, | 2613 | .queue = tid, |
2614 | .flags = 0, | ||
2614 | }; | 2615 | }; |
2615 | struct tid_ampdu_rx *tid_agg_rx; | 2616 | struct tid_ampdu_rx *tid_agg_rx; |
2616 | 2617 | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 5a11078827ab..13e8c30adf01 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -47,9 +47,9 @@ | |||
47 | * Station entries are added by mac80211 when you establish a link with a | 47 | * Station entries are added by mac80211 when you establish a link with a |
48 | * peer. This means different things for the different type of interfaces | 48 | * peer. This means different things for the different type of interfaces |
49 | * we support. For a regular station this mean we add the AP sta when we | 49 | * we support. For a regular station this mean we add the AP sta when we |
50 | * receive an assocation response from the AP. For IBSS this occurs when | 50 | * receive an association response from the AP. For IBSS this occurs when |
51 | * get to know about a peer on the same IBSS. For WDS we add the sta for | 51 | * get to know about a peer on the same IBSS. For WDS we add the sta for |
52 | * the peer imediately upon device open. When using AP mode we add stations | 52 | * the peer immediately upon device open. When using AP mode we add stations |
53 | * for each respective station upon request from userspace through nl80211. | 53 | * for each respective station upon request from userspace through nl80211. |
54 | * | 54 | * |
55 | * In order to remove a STA info structure, various sta_info_destroy_*() | 55 | * In order to remove a STA info structure, various sta_info_destroy_*() |
@@ -243,6 +243,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
243 | memcpy(sta->sta.addr, addr, ETH_ALEN); | 243 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
244 | sta->local = local; | 244 | sta->local = local; |
245 | sta->sdata = sdata; | 245 | sta->sdata = sdata; |
246 | sta->last_rx = jiffies; | ||
246 | 247 | ||
247 | ewma_init(&sta->avg_signal, 1024, 8); | 248 | ewma_init(&sta->avg_signal, 1024, 8); |
248 | 249 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 57681149e37f..b2f95966c7f4 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -173,7 +173,7 @@ struct sta_ampdu_mlme { | |||
173 | /** | 173 | /** |
174 | * enum plink_state - state of a mesh peer link finite state machine | 174 | * enum plink_state - state of a mesh peer link finite state machine |
175 | * | 175 | * |
176 | * @PLINK_LISTEN: initial state, considered the implicit state of non existant | 176 | * @PLINK_LISTEN: initial state, considered the implicit state of non existent |
177 | * mesh peer links | 177 | * mesh peer links |
178 | * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer | 178 | * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer |
179 | * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer | 179 | * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce4596ed1268..bd1224fd216a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -237,6 +237,10 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
237 | &local->dynamic_ps_disable_work); | 237 | &local->dynamic_ps_disable_work); |
238 | } | 238 | } |
239 | 239 | ||
240 | /* Don't restart the timer if we're not disassociated */ | ||
241 | if (!ifmgd->associated) | ||
242 | return TX_CONTINUE; | ||
243 | |||
240 | mod_timer(&local->dynamic_ps_timer, jiffies + | 244 | mod_timer(&local->dynamic_ps_timer, jiffies + |
241 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 245 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
242 | 246 | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c3f988aa1152..32bff6d86cb2 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -652,7 +652,6 @@ comment "Xtables matches" | |||
652 | config NETFILTER_XT_MATCH_ADDRTYPE | 652 | config NETFILTER_XT_MATCH_ADDRTYPE |
653 | tristate '"addrtype" address type match support' | 653 | tristate '"addrtype" address type match support' |
654 | depends on NETFILTER_ADVANCED | 654 | depends on NETFILTER_ADVANCED |
655 | depends on (IPV6 || IPV6=n) | ||
656 | ---help--- | 655 | ---help--- |
657 | This option allows you to match what routing thinks of an address, | 656 | This option allows you to match what routing thinks of an address, |
658 | eg. UNICAST, LOCAL, BROADCAST, ... | 657 | eg. UNICAST, LOCAL, BROADCAST, ... |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index bca96990218d..a113ff066928 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c | |||
@@ -338,8 +338,7 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) | |||
338 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); | 338 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); |
339 | if (map->netmask != 32) | 339 | if (map->netmask != 32) |
340 | NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); | 340 | NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); |
341 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 341 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
342 | htonl(atomic_read(&set->ref) - 1)); | ||
343 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 342 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
344 | htonl(sizeof(*map) + map->memsize)); | 343 | htonl(sizeof(*map) + map->memsize)); |
345 | if (with_timeout(map->timeout)) | 344 | if (with_timeout(map->timeout)) |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index 5e790172deff..a274300b6a56 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c | |||
@@ -343,6 +343,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
343 | ipset_adtfn adtfn = set->variant->adt[adt]; | 343 | ipset_adtfn adtfn = set->variant->adt[adt]; |
344 | struct ipmac data; | 344 | struct ipmac data; |
345 | 345 | ||
346 | /* MAC can be src only */ | ||
347 | if (!(flags & IPSET_DIM_TWO_SRC)) | ||
348 | return 0; | ||
349 | |||
346 | data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); | 350 | data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); |
347 | if (data.id < map->first_ip || data.id > map->last_ip) | 351 | if (data.id < map->first_ip || data.id > map->last_ip) |
348 | return -IPSET_ERR_BITMAP_RANGE; | 352 | return -IPSET_ERR_BITMAP_RANGE; |
@@ -434,8 +438,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) | |||
434 | goto nla_put_failure; | 438 | goto nla_put_failure; |
435 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); | 439 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); |
436 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); | 440 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); |
437 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 441 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
438 | htonl(atomic_read(&set->ref) - 1)); | ||
439 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 442 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
440 | htonl(sizeof(*map) | 443 | htonl(sizeof(*map) |
441 | + (map->last_ip - map->first_ip + 1) * map->dsize)); | 444 | + (map->last_ip - map->first_ip + 1) * map->dsize)); |
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index 165f09b1a9cb..6b38eb8f6ed8 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c | |||
@@ -320,8 +320,7 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb) | |||
320 | goto nla_put_failure; | 320 | goto nla_put_failure; |
321 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); | 321 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); |
322 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); | 322 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); |
323 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 323 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
324 | htonl(atomic_read(&set->ref) - 1)); | ||
325 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 324 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
326 | htonl(sizeof(*map) + map->memsize)); | 325 | htonl(sizeof(*map) + map->memsize)); |
327 | if (with_timeout(map->timeout)) | 326 | if (with_timeout(map->timeout)) |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 618a615acc9d..72d1ac611fdc 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | static LIST_HEAD(ip_set_type_list); /* all registered set types */ | 27 | static LIST_HEAD(ip_set_type_list); /* all registered set types */ |
28 | static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ | 28 | static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ |
29 | static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ | ||
29 | 30 | ||
30 | static struct ip_set **ip_set_list; /* all individual sets */ | 31 | static struct ip_set **ip_set_list; /* all individual sets */ |
31 | static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ | 32 | static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ |
@@ -94,16 +95,28 @@ static int | |||
94 | find_set_type_get(const char *name, u8 family, u8 revision, | 95 | find_set_type_get(const char *name, u8 family, u8 revision, |
95 | struct ip_set_type **found) | 96 | struct ip_set_type **found) |
96 | { | 97 | { |
98 | struct ip_set_type *type; | ||
99 | int err; | ||
100 | |||
97 | rcu_read_lock(); | 101 | rcu_read_lock(); |
98 | *found = find_set_type(name, family, revision); | 102 | *found = find_set_type(name, family, revision); |
99 | if (*found) { | 103 | if (*found) { |
100 | int err = !try_module_get((*found)->me); | 104 | err = !try_module_get((*found)->me) ? -EFAULT : 0; |
101 | rcu_read_unlock(); | 105 | goto unlock; |
102 | return err ? -EFAULT : 0; | ||
103 | } | 106 | } |
107 | /* Make sure the type is loaded but we don't support the revision */ | ||
108 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | ||
109 | if (STREQ(type->name, name)) { | ||
110 | err = -IPSET_ERR_FIND_TYPE; | ||
111 | goto unlock; | ||
112 | } | ||
104 | rcu_read_unlock(); | 113 | rcu_read_unlock(); |
105 | 114 | ||
106 | return try_to_load_type(name); | 115 | return try_to_load_type(name); |
116 | |||
117 | unlock: | ||
118 | rcu_read_unlock(); | ||
119 | return err; | ||
107 | } | 120 | } |
108 | 121 | ||
109 | /* Find a given set type by name and family. | 122 | /* Find a given set type by name and family. |
@@ -116,7 +129,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) | |||
116 | struct ip_set_type *type; | 129 | struct ip_set_type *type; |
117 | bool found = false; | 130 | bool found = false; |
118 | 131 | ||
119 | *min = *max = 0; | 132 | *min = 255; *max = 0; |
120 | rcu_read_lock(); | 133 | rcu_read_lock(); |
121 | list_for_each_entry_rcu(type, &ip_set_type_list, list) | 134 | list_for_each_entry_rcu(type, &ip_set_type_list, list) |
122 | if (STREQ(type->name, name) && | 135 | if (STREQ(type->name, name) && |
@@ -124,7 +137,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) | |||
124 | found = true; | 137 | found = true; |
125 | if (type->revision < *min) | 138 | if (type->revision < *min) |
126 | *min = type->revision; | 139 | *min = type->revision; |
127 | else if (type->revision > *max) | 140 | if (type->revision > *max) |
128 | *max = type->revision; | 141 | *max = type->revision; |
129 | } | 142 | } |
130 | rcu_read_unlock(); | 143 | rcu_read_unlock(); |
@@ -289,13 +302,18 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); | |||
289 | static inline void | 302 | static inline void |
290 | __ip_set_get(ip_set_id_t index) | 303 | __ip_set_get(ip_set_id_t index) |
291 | { | 304 | { |
292 | atomic_inc(&ip_set_list[index]->ref); | 305 | write_lock_bh(&ip_set_ref_lock); |
306 | ip_set_list[index]->ref++; | ||
307 | write_unlock_bh(&ip_set_ref_lock); | ||
293 | } | 308 | } |
294 | 309 | ||
295 | static inline void | 310 | static inline void |
296 | __ip_set_put(ip_set_id_t index) | 311 | __ip_set_put(ip_set_id_t index) |
297 | { | 312 | { |
298 | atomic_dec(&ip_set_list[index]->ref); | 313 | write_lock_bh(&ip_set_ref_lock); |
314 | BUG_ON(ip_set_list[index]->ref == 0); | ||
315 | ip_set_list[index]->ref--; | ||
316 | write_unlock_bh(&ip_set_ref_lock); | ||
299 | } | 317 | } |
300 | 318 | ||
301 | /* | 319 | /* |
@@ -312,7 +330,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, | |||
312 | struct ip_set *set = ip_set_list[index]; | 330 | struct ip_set *set = ip_set_list[index]; |
313 | int ret = 0; | 331 | int ret = 0; |
314 | 332 | ||
315 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 333 | BUG_ON(set == NULL); |
316 | pr_debug("set %s, index %u\n", set->name, index); | 334 | pr_debug("set %s, index %u\n", set->name, index); |
317 | 335 | ||
318 | if (dim < set->type->dimension || | 336 | if (dim < set->type->dimension || |
@@ -344,7 +362,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, | |||
344 | struct ip_set *set = ip_set_list[index]; | 362 | struct ip_set *set = ip_set_list[index]; |
345 | int ret; | 363 | int ret; |
346 | 364 | ||
347 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 365 | BUG_ON(set == NULL); |
348 | pr_debug("set %s, index %u\n", set->name, index); | 366 | pr_debug("set %s, index %u\n", set->name, index); |
349 | 367 | ||
350 | if (dim < set->type->dimension || | 368 | if (dim < set->type->dimension || |
@@ -366,7 +384,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, | |||
366 | struct ip_set *set = ip_set_list[index]; | 384 | struct ip_set *set = ip_set_list[index]; |
367 | int ret = 0; | 385 | int ret = 0; |
368 | 386 | ||
369 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 387 | BUG_ON(set == NULL); |
370 | pr_debug("set %s, index %u\n", set->name, index); | 388 | pr_debug("set %s, index %u\n", set->name, index); |
371 | 389 | ||
372 | if (dim < set->type->dimension || | 390 | if (dim < set->type->dimension || |
@@ -385,7 +403,6 @@ EXPORT_SYMBOL_GPL(ip_set_del); | |||
385 | * Find set by name, reference it once. The reference makes sure the | 403 | * Find set by name, reference it once. The reference makes sure the |
386 | * thing pointed to, does not go away under our feet. | 404 | * thing pointed to, does not go away under our feet. |
387 | * | 405 | * |
388 | * The nfnl mutex must already be activated. | ||
389 | */ | 406 | */ |
390 | ip_set_id_t | 407 | ip_set_id_t |
391 | ip_set_get_byname(const char *name, struct ip_set **set) | 408 | ip_set_get_byname(const char *name, struct ip_set **set) |
@@ -411,15 +428,12 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname); | |||
411 | * reference count by 1. The caller shall not assume the index | 428 | * reference count by 1. The caller shall not assume the index |
412 | * to be valid, after calling this function. | 429 | * to be valid, after calling this function. |
413 | * | 430 | * |
414 | * The nfnl mutex must already be activated. | ||
415 | */ | 431 | */ |
416 | void | 432 | void |
417 | ip_set_put_byindex(ip_set_id_t index) | 433 | ip_set_put_byindex(ip_set_id_t index) |
418 | { | 434 | { |
419 | if (ip_set_list[index] != NULL) { | 435 | if (ip_set_list[index] != NULL) |
420 | BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); | ||
421 | __ip_set_put(index); | 436 | __ip_set_put(index); |
422 | } | ||
423 | } | 437 | } |
424 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); | 438 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); |
425 | 439 | ||
@@ -429,7 +443,6 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex); | |||
429 | * can't be destroyed. The set cannot be renamed due to | 443 | * can't be destroyed. The set cannot be renamed due to |
430 | * the referencing either. | 444 | * the referencing either. |
431 | * | 445 | * |
432 | * The nfnl mutex must already be activated. | ||
433 | */ | 446 | */ |
434 | const char * | 447 | const char * |
435 | ip_set_name_byindex(ip_set_id_t index) | 448 | ip_set_name_byindex(ip_set_id_t index) |
@@ -437,7 +450,7 @@ ip_set_name_byindex(ip_set_id_t index) | |||
437 | const struct ip_set *set = ip_set_list[index]; | 450 | const struct ip_set *set = ip_set_list[index]; |
438 | 451 | ||
439 | BUG_ON(set == NULL); | 452 | BUG_ON(set == NULL); |
440 | BUG_ON(atomic_read(&set->ref) == 0); | 453 | BUG_ON(set->ref == 0); |
441 | 454 | ||
442 | /* Referenced, so it's safe */ | 455 | /* Referenced, so it's safe */ |
443 | return set->name; | 456 | return set->name; |
@@ -503,10 +516,7 @@ void | |||
503 | ip_set_nfnl_put(ip_set_id_t index) | 516 | ip_set_nfnl_put(ip_set_id_t index) |
504 | { | 517 | { |
505 | nfnl_lock(); | 518 | nfnl_lock(); |
506 | if (ip_set_list[index] != NULL) { | 519 | ip_set_put_byindex(index); |
507 | BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); | ||
508 | __ip_set_put(index); | ||
509 | } | ||
510 | nfnl_unlock(); | 520 | nfnl_unlock(); |
511 | } | 521 | } |
512 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); | 522 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); |
@@ -514,7 +524,7 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put); | |||
514 | /* | 524 | /* |
515 | * Communication protocol with userspace over netlink. | 525 | * Communication protocol with userspace over netlink. |
516 | * | 526 | * |
517 | * We already locked by nfnl_lock. | 527 | * The commands are serialized by the nfnl mutex. |
518 | */ | 528 | */ |
519 | 529 | ||
520 | static inline bool | 530 | static inline bool |
@@ -645,7 +655,6 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
645 | return -ENOMEM; | 655 | return -ENOMEM; |
646 | rwlock_init(&set->lock); | 656 | rwlock_init(&set->lock); |
647 | strlcpy(set->name, name, IPSET_MAXNAMELEN); | 657 | strlcpy(set->name, name, IPSET_MAXNAMELEN); |
648 | atomic_set(&set->ref, 0); | ||
649 | set->family = family; | 658 | set->family = family; |
650 | 659 | ||
651 | /* | 660 | /* |
@@ -678,8 +687,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
678 | 687 | ||
679 | /* | 688 | /* |
680 | * Here, we have a valid, constructed set and we are protected | 689 | * Here, we have a valid, constructed set and we are protected |
681 | * by nfnl_lock. Find the first free index in ip_set_list and | 690 | * by the nfnl mutex. Find the first free index in ip_set_list |
682 | * check clashing. | 691 | * and check clashing. |
683 | */ | 692 | */ |
684 | if ((ret = find_free_id(set->name, &index, &clash)) != 0) { | 693 | if ((ret = find_free_id(set->name, &index, &clash)) != 0) { |
685 | /* If this is the same set and requested, ignore error */ | 694 | /* If this is the same set and requested, ignore error */ |
@@ -739,31 +748,51 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, | |||
739 | const struct nlattr * const attr[]) | 748 | const struct nlattr * const attr[]) |
740 | { | 749 | { |
741 | ip_set_id_t i; | 750 | ip_set_id_t i; |
751 | int ret = 0; | ||
742 | 752 | ||
743 | if (unlikely(protocol_failed(attr))) | 753 | if (unlikely(protocol_failed(attr))) |
744 | return -IPSET_ERR_PROTOCOL; | 754 | return -IPSET_ERR_PROTOCOL; |
745 | 755 | ||
746 | /* References are protected by the nfnl mutex */ | 756 | /* Commands are serialized and references are |
757 | * protected by the ip_set_ref_lock. | ||
758 | * External systems (i.e. xt_set) must call | ||
759 | * ip_set_put|get_nfnl_* functions, that way we | ||
760 | * can safely check references here. | ||
761 | * | ||
762 | * list:set timer can only decrement the reference | ||
763 | * counter, so if it's already zero, we can proceed | ||
764 | * without holding the lock. | ||
765 | */ | ||
766 | read_lock_bh(&ip_set_ref_lock); | ||
747 | if (!attr[IPSET_ATTR_SETNAME]) { | 767 | if (!attr[IPSET_ATTR_SETNAME]) { |
748 | for (i = 0; i < ip_set_max; i++) { | 768 | for (i = 0; i < ip_set_max; i++) { |
749 | if (ip_set_list[i] != NULL && | 769 | if (ip_set_list[i] != NULL && ip_set_list[i]->ref) { |
750 | (atomic_read(&ip_set_list[i]->ref))) | 770 | ret = IPSET_ERR_BUSY; |
751 | return -IPSET_ERR_BUSY; | 771 | goto out; |
772 | } | ||
752 | } | 773 | } |
774 | read_unlock_bh(&ip_set_ref_lock); | ||
753 | for (i = 0; i < ip_set_max; i++) { | 775 | for (i = 0; i < ip_set_max; i++) { |
754 | if (ip_set_list[i] != NULL) | 776 | if (ip_set_list[i] != NULL) |
755 | ip_set_destroy_set(i); | 777 | ip_set_destroy_set(i); |
756 | } | 778 | } |
757 | } else { | 779 | } else { |
758 | i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); | 780 | i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); |
759 | if (i == IPSET_INVALID_ID) | 781 | if (i == IPSET_INVALID_ID) { |
760 | return -ENOENT; | 782 | ret = -ENOENT; |
761 | else if (atomic_read(&ip_set_list[i]->ref)) | 783 | goto out; |
762 | return -IPSET_ERR_BUSY; | 784 | } else if (ip_set_list[i]->ref) { |
785 | ret = -IPSET_ERR_BUSY; | ||
786 | goto out; | ||
787 | } | ||
788 | read_unlock_bh(&ip_set_ref_lock); | ||
763 | 789 | ||
764 | ip_set_destroy_set(i); | 790 | ip_set_destroy_set(i); |
765 | } | 791 | } |
766 | return 0; | 792 | return 0; |
793 | out: | ||
794 | read_unlock_bh(&ip_set_ref_lock); | ||
795 | return ret; | ||
767 | } | 796 | } |
768 | 797 | ||
769 | /* Flush sets */ | 798 | /* Flush sets */ |
@@ -822,6 +851,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | |||
822 | struct ip_set *set; | 851 | struct ip_set *set; |
823 | const char *name2; | 852 | const char *name2; |
824 | ip_set_id_t i; | 853 | ip_set_id_t i; |
854 | int ret = 0; | ||
825 | 855 | ||
826 | if (unlikely(protocol_failed(attr) || | 856 | if (unlikely(protocol_failed(attr) || |
827 | attr[IPSET_ATTR_SETNAME] == NULL || | 857 | attr[IPSET_ATTR_SETNAME] == NULL || |
@@ -831,25 +861,33 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | |||
831 | set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | 861 | set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); |
832 | if (set == NULL) | 862 | if (set == NULL) |
833 | return -ENOENT; | 863 | return -ENOENT; |
834 | if (atomic_read(&set->ref) != 0) | 864 | |
835 | return -IPSET_ERR_REFERENCED; | 865 | read_lock_bh(&ip_set_ref_lock); |
866 | if (set->ref != 0) { | ||
867 | ret = -IPSET_ERR_REFERENCED; | ||
868 | goto out; | ||
869 | } | ||
836 | 870 | ||
837 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); | 871 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); |
838 | for (i = 0; i < ip_set_max; i++) { | 872 | for (i = 0; i < ip_set_max; i++) { |
839 | if (ip_set_list[i] != NULL && | 873 | if (ip_set_list[i] != NULL && |
840 | STREQ(ip_set_list[i]->name, name2)) | 874 | STREQ(ip_set_list[i]->name, name2)) { |
841 | return -IPSET_ERR_EXIST_SETNAME2; | 875 | ret = -IPSET_ERR_EXIST_SETNAME2; |
876 | goto out; | ||
877 | } | ||
842 | } | 878 | } |
843 | strncpy(set->name, name2, IPSET_MAXNAMELEN); | 879 | strncpy(set->name, name2, IPSET_MAXNAMELEN); |
844 | 880 | ||
845 | return 0; | 881 | out: |
882 | read_unlock_bh(&ip_set_ref_lock); | ||
883 | return ret; | ||
846 | } | 884 | } |
847 | 885 | ||
848 | /* Swap two sets so that name/index points to the other. | 886 | /* Swap two sets so that name/index points to the other. |
849 | * References and set names are also swapped. | 887 | * References and set names are also swapped. |
850 | * | 888 | * |
851 | * We are protected by the nfnl mutex and references are | 889 | * The commands are serialized by the nfnl mutex and references are |
852 | * manipulated only by holding the mutex. The kernel interfaces | 890 | * protected by the ip_set_ref_lock. The kernel interfaces |
853 | * do not hold the mutex but the pointer settings are atomic | 891 | * do not hold the mutex but the pointer settings are atomic |
854 | * so the ip_set_list always contains valid pointers to the sets. | 892 | * so the ip_set_list always contains valid pointers to the sets. |
855 | */ | 893 | */ |
@@ -862,7 +900,6 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
862 | struct ip_set *from, *to; | 900 | struct ip_set *from, *to; |
863 | ip_set_id_t from_id, to_id; | 901 | ip_set_id_t from_id, to_id; |
864 | char from_name[IPSET_MAXNAMELEN]; | 902 | char from_name[IPSET_MAXNAMELEN]; |
865 | u32 from_ref; | ||
866 | 903 | ||
867 | if (unlikely(protocol_failed(attr) || | 904 | if (unlikely(protocol_failed(attr) || |
868 | attr[IPSET_ATTR_SETNAME] == NULL || | 905 | attr[IPSET_ATTR_SETNAME] == NULL || |
@@ -881,23 +918,21 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
881 | to = ip_set_list[to_id]; | 918 | to = ip_set_list[to_id]; |
882 | 919 | ||
883 | /* Features must not change. | 920 | /* Features must not change. |
884 | * Not an artifical restriction anymore, as we must prevent | 921 | * Not an artificial restriction anymore, as we must prevent |
885 | * possible loops created by swapping in setlist type of sets. */ | 922 | * possible loops created by swapping in setlist type of sets. */ |
886 | if (!(from->type->features == to->type->features && | 923 | if (!(from->type->features == to->type->features && |
887 | from->type->family == to->type->family)) | 924 | from->type->family == to->type->family)) |
888 | return -IPSET_ERR_TYPE_MISMATCH; | 925 | return -IPSET_ERR_TYPE_MISMATCH; |
889 | 926 | ||
890 | /* No magic here: ref munging protected by the nfnl_lock */ | ||
891 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); | 927 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); |
892 | from_ref = atomic_read(&from->ref); | ||
893 | |||
894 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); | 928 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); |
895 | atomic_set(&from->ref, atomic_read(&to->ref)); | ||
896 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); | 929 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); |
897 | atomic_set(&to->ref, from_ref); | ||
898 | 930 | ||
931 | write_lock_bh(&ip_set_ref_lock); | ||
932 | swap(from->ref, to->ref); | ||
899 | ip_set_list[from_id] = to; | 933 | ip_set_list[from_id] = to; |
900 | ip_set_list[to_id] = from; | 934 | ip_set_list[to_id] = from; |
935 | write_unlock_bh(&ip_set_ref_lock); | ||
901 | 936 | ||
902 | return 0; | 937 | return 0; |
903 | } | 938 | } |
@@ -914,7 +949,7 @@ ip_set_dump_done(struct netlink_callback *cb) | |||
914 | { | 949 | { |
915 | if (cb->args[2]) { | 950 | if (cb->args[2]) { |
916 | pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); | 951 | pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); |
917 | __ip_set_put((ip_set_id_t) cb->args[1]); | 952 | ip_set_put_byindex((ip_set_id_t) cb->args[1]); |
918 | } | 953 | } |
919 | return 0; | 954 | return 0; |
920 | } | 955 | } |
@@ -987,8 +1022,9 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
987 | if (cb->args[1] >= ip_set_max) | 1022 | if (cb->args[1] >= ip_set_max) |
988 | goto out; | 1023 | goto out; |
989 | 1024 | ||
990 | pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]); | ||
991 | max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; | 1025 | max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; |
1026 | dump_last: | ||
1027 | pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]); | ||
992 | for (; cb->args[1] < max; cb->args[1]++) { | 1028 | for (; cb->args[1] < max; cb->args[1]++) { |
993 | index = (ip_set_id_t) cb->args[1]; | 1029 | index = (ip_set_id_t) cb->args[1]; |
994 | set = ip_set_list[index]; | 1030 | set = ip_set_list[index]; |
@@ -1003,8 +1039,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
1003 | * so that lists (unions of sets) are dumped last. | 1039 | * so that lists (unions of sets) are dumped last. |
1004 | */ | 1040 | */ |
1005 | if (cb->args[0] != DUMP_ONE && | 1041 | if (cb->args[0] != DUMP_ONE && |
1006 | !((cb->args[0] == DUMP_ALL) ^ | 1042 | ((cb->args[0] == DUMP_ALL) == |
1007 | (set->type->features & IPSET_DUMP_LAST))) | 1043 | !!(set->type->features & IPSET_DUMP_LAST))) |
1008 | continue; | 1044 | continue; |
1009 | pr_debug("List set: %s\n", set->name); | 1045 | pr_debug("List set: %s\n", set->name); |
1010 | if (!cb->args[2]) { | 1046 | if (!cb->args[2]) { |
@@ -1048,6 +1084,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
1048 | goto release_refcount; | 1084 | goto release_refcount; |
1049 | } | 1085 | } |
1050 | } | 1086 | } |
1087 | /* If we dump all sets, continue with dumping last ones */ | ||
1088 | if (cb->args[0] == DUMP_ALL) { | ||
1089 | cb->args[0] = DUMP_LAST; | ||
1090 | cb->args[1] = 0; | ||
1091 | goto dump_last; | ||
1092 | } | ||
1051 | goto out; | 1093 | goto out; |
1052 | 1094 | ||
1053 | nla_put_failure: | 1095 | nla_put_failure: |
@@ -1056,13 +1098,8 @@ release_refcount: | |||
1056 | /* If there was an error or set is done, release set */ | 1098 | /* If there was an error or set is done, release set */ |
1057 | if (ret || !cb->args[2]) { | 1099 | if (ret || !cb->args[2]) { |
1058 | pr_debug("release set %s\n", ip_set_list[index]->name); | 1100 | pr_debug("release set %s\n", ip_set_list[index]->name); |
1059 | __ip_set_put(index); | 1101 | ip_set_put_byindex(index); |
1060 | } | 1102 | } |
1061 | |||
1062 | /* If we dump all sets, continue with dumping last ones */ | ||
1063 | if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2]) | ||
1064 | cb->args[0] = DUMP_LAST; | ||
1065 | |||
1066 | out: | 1103 | out: |
1067 | if (nlh) { | 1104 | if (nlh) { |
1068 | nlmsg_end(skb, nlh); | 1105 | nlmsg_end(skb, nlh); |
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index adbe787ea5dc..b9214145d357 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
150 | struct hash_ipport4_elem data = { }; | 150 | struct hash_ipport4_elem data = { }; |
151 | u32 ip, ip_to, p, port, port_to; | 151 | u32 ip, ip_to, p, port, port_to; |
152 | u32 timeout = h->timeout; | 152 | u32 timeout = h->timeout; |
153 | bool with_ports = false; | ||
153 | int ret; | 154 | int ret; |
154 | 155 | ||
155 | if (unlikely(!tb[IPSET_ATTR_IP] || | 156 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
172 | 173 | ||
173 | if (tb[IPSET_ATTR_PROTO]) { | 174 | if (tb[IPSET_ATTR_PROTO]) { |
174 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 175 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
176 | with_ports = ip_set_proto_with_ports(data.proto); | ||
175 | 177 | ||
176 | if (data.proto == 0) | 178 | if (data.proto == 0) |
177 | return -IPSET_ERR_INVALID_PROTO; | 179 | return -IPSET_ERR_INVALID_PROTO; |
178 | } else | 180 | } else |
179 | return -IPSET_ERR_MISSING_PROTO; | 181 | return -IPSET_ERR_MISSING_PROTO; |
180 | 182 | ||
181 | switch (data.proto) { | 183 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
182 | case IPPROTO_UDP: | ||
183 | case IPPROTO_TCP: | ||
184 | case IPPROTO_ICMP: | ||
185 | break; | ||
186 | default: | ||
187 | data.port = 0; | 184 | data.port = 0; |
188 | break; | ||
189 | } | ||
190 | 185 | ||
191 | if (tb[IPSET_ATTR_TIMEOUT]) { | 186 | if (tb[IPSET_ATTR_TIMEOUT]) { |
192 | if (!with_timeout(h->timeout)) | 187 | if (!with_timeout(h->timeout)) |
@@ -195,7 +190,6 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
195 | } | 190 | } |
196 | 191 | ||
197 | if (adt == IPSET_TEST || | 192 | if (adt == IPSET_TEST || |
198 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
199 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 193 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
200 | tb[IPSET_ATTR_PORT_TO])) { | 194 | tb[IPSET_ATTR_PORT_TO])) { |
201 | ret = adtfn(set, &data, timeout); | 195 | ret = adtfn(set, &data, timeout); |
@@ -219,13 +213,12 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
219 | } else | 213 | } else |
220 | ip_to = ip; | 214 | ip_to = ip; |
221 | 215 | ||
222 | port = ntohs(data.port); | 216 | port_to = port = ntohs(data.port); |
223 | if (tb[IPSET_ATTR_PORT_TO]) { | 217 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
224 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 218 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
225 | if (port > port_to) | 219 | if (port > port_to) |
226 | swap(port, port_to); | 220 | swap(port, port_to); |
227 | } else | 221 | } |
228 | port_to = port; | ||
229 | 222 | ||
230 | for (; !before(ip_to, ip); ip++) | 223 | for (; !before(ip_to, ip); ip++) |
231 | for (p = port; p <= port_to; p++) { | 224 | for (p = port; p <= port_to; p++) { |
@@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
361 | struct hash_ipport6_elem data = { }; | 354 | struct hash_ipport6_elem data = { }; |
362 | u32 port, port_to; | 355 | u32 port, port_to; |
363 | u32 timeout = h->timeout; | 356 | u32 timeout = h->timeout; |
357 | bool with_ports = false; | ||
364 | int ret; | 358 | int ret; |
365 | 359 | ||
366 | if (unlikely(!tb[IPSET_ATTR_IP] || | 360 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
385 | 379 | ||
386 | if (tb[IPSET_ATTR_PROTO]) { | 380 | if (tb[IPSET_ATTR_PROTO]) { |
387 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 381 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
382 | with_ports = ip_set_proto_with_ports(data.proto); | ||
388 | 383 | ||
389 | if (data.proto == 0) | 384 | if (data.proto == 0) |
390 | return -IPSET_ERR_INVALID_PROTO; | 385 | return -IPSET_ERR_INVALID_PROTO; |
391 | } else | 386 | } else |
392 | return -IPSET_ERR_MISSING_PROTO; | 387 | return -IPSET_ERR_MISSING_PROTO; |
393 | 388 | ||
394 | switch (data.proto) { | 389 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
395 | case IPPROTO_UDP: | ||
396 | case IPPROTO_TCP: | ||
397 | case IPPROTO_ICMPV6: | ||
398 | break; | ||
399 | default: | ||
400 | data.port = 0; | 390 | data.port = 0; |
401 | break; | ||
402 | } | ||
403 | 391 | ||
404 | if (tb[IPSET_ATTR_TIMEOUT]) { | 392 | if (tb[IPSET_ATTR_TIMEOUT]) { |
405 | if (!with_timeout(h->timeout)) | 393 | if (!with_timeout(h->timeout)) |
@@ -407,9 +395,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
407 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 395 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
408 | } | 396 | } |
409 | 397 | ||
410 | if (adt == IPSET_TEST || | 398 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
411 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
412 | !tb[IPSET_ATTR_PORT_TO]) { | ||
413 | ret = adtfn(set, &data, timeout); | 399 | ret = adtfn(set, &data, timeout); |
414 | return ip_set_eexist(ret, flags) ? 0 : ret; | 400 | return ip_set_eexist(ret, flags) ? 0 : ret; |
415 | } | 401 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 22e23abb86c6..4642872df6e1 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
154 | struct hash_ipportip4_elem data = { }; | 154 | struct hash_ipportip4_elem data = { }; |
155 | u32 ip, ip_to, p, port, port_to; | 155 | u32 ip, ip_to, p, port, port_to; |
156 | u32 timeout = h->timeout; | 156 | u32 timeout = h->timeout; |
157 | bool with_ports = false; | ||
157 | int ret; | 158 | int ret; |
158 | 159 | ||
159 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 160 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
180 | 181 | ||
181 | if (tb[IPSET_ATTR_PROTO]) { | 182 | if (tb[IPSET_ATTR_PROTO]) { |
182 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 183 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
184 | with_ports = ip_set_proto_with_ports(data.proto); | ||
183 | 185 | ||
184 | if (data.proto == 0) | 186 | if (data.proto == 0) |
185 | return -IPSET_ERR_INVALID_PROTO; | 187 | return -IPSET_ERR_INVALID_PROTO; |
186 | } else | 188 | } else |
187 | return -IPSET_ERR_MISSING_PROTO; | 189 | return -IPSET_ERR_MISSING_PROTO; |
188 | 190 | ||
189 | switch (data.proto) { | 191 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
190 | case IPPROTO_UDP: | ||
191 | case IPPROTO_TCP: | ||
192 | case IPPROTO_ICMP: | ||
193 | break; | ||
194 | default: | ||
195 | data.port = 0; | 192 | data.port = 0; |
196 | break; | ||
197 | } | ||
198 | 193 | ||
199 | if (tb[IPSET_ATTR_TIMEOUT]) { | 194 | if (tb[IPSET_ATTR_TIMEOUT]) { |
200 | if (!with_timeout(h->timeout)) | 195 | if (!with_timeout(h->timeout)) |
@@ -203,7 +198,6 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
203 | } | 198 | } |
204 | 199 | ||
205 | if (adt == IPSET_TEST || | 200 | if (adt == IPSET_TEST || |
206 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
207 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 201 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
208 | tb[IPSET_ATTR_PORT_TO])) { | 202 | tb[IPSET_ATTR_PORT_TO])) { |
209 | ret = adtfn(set, &data, timeout); | 203 | ret = adtfn(set, &data, timeout); |
@@ -227,13 +221,12 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
227 | } else | 221 | } else |
228 | ip_to = ip; | 222 | ip_to = ip; |
229 | 223 | ||
230 | port = ntohs(data.port); | 224 | port_to = port = ntohs(data.port); |
231 | if (tb[IPSET_ATTR_PORT_TO]) { | 225 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
232 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 226 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
233 | if (port > port_to) | 227 | if (port > port_to) |
234 | swap(port, port_to); | 228 | swap(port, port_to); |
235 | } else | 229 | } |
236 | port_to = port; | ||
237 | 230 | ||
238 | for (; !before(ip_to, ip); ip++) | 231 | for (; !before(ip_to, ip); ip++) |
239 | for (p = port; p <= port_to; p++) { | 232 | for (p = port; p <= port_to; p++) { |
@@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
375 | struct hash_ipportip6_elem data = { }; | 368 | struct hash_ipportip6_elem data = { }; |
376 | u32 port, port_to; | 369 | u32 port, port_to; |
377 | u32 timeout = h->timeout; | 370 | u32 timeout = h->timeout; |
371 | bool with_ports = false; | ||
378 | int ret; | 372 | int ret; |
379 | 373 | ||
380 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 374 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
403 | 397 | ||
404 | if (tb[IPSET_ATTR_PROTO]) { | 398 | if (tb[IPSET_ATTR_PROTO]) { |
405 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 399 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
400 | with_ports = ip_set_proto_with_ports(data.proto); | ||
406 | 401 | ||
407 | if (data.proto == 0) | 402 | if (data.proto == 0) |
408 | return -IPSET_ERR_INVALID_PROTO; | 403 | return -IPSET_ERR_INVALID_PROTO; |
409 | } else | 404 | } else |
410 | return -IPSET_ERR_MISSING_PROTO; | 405 | return -IPSET_ERR_MISSING_PROTO; |
411 | 406 | ||
412 | switch (data.proto) { | 407 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
413 | case IPPROTO_UDP: | ||
414 | case IPPROTO_TCP: | ||
415 | case IPPROTO_ICMPV6: | ||
416 | break; | ||
417 | default: | ||
418 | data.port = 0; | 408 | data.port = 0; |
419 | break; | ||
420 | } | ||
421 | 409 | ||
422 | if (tb[IPSET_ATTR_TIMEOUT]) { | 410 | if (tb[IPSET_ATTR_TIMEOUT]) { |
423 | if (!with_timeout(h->timeout)) | 411 | if (!with_timeout(h->timeout)) |
@@ -425,9 +413,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
425 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 413 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
426 | } | 414 | } |
427 | 415 | ||
428 | if (adt == IPSET_TEST || | 416 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
429 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
430 | !tb[IPSET_ATTR_PORT_TO]) { | ||
431 | ret = adtfn(set, &data, timeout); | 417 | ret = adtfn(set, &data, timeout); |
432 | return ip_set_eexist(ret, flags) ? 0 : ret; | 418 | return ip_set_eexist(ret, flags) ? 0 : ret; |
433 | } | 419 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 6033e8b54bbd..2cb84a54b7ad 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
174 | struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; | 174 | struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; |
175 | u32 ip, ip_to, p, port, port_to; | 175 | u32 ip, ip_to, p, port, port_to; |
176 | u32 timeout = h->timeout; | 176 | u32 timeout = h->timeout; |
177 | bool with_ports = false; | ||
177 | int ret; | 178 | int ret; |
178 | 179 | ||
179 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 180 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
208 | 209 | ||
209 | if (tb[IPSET_ATTR_PROTO]) { | 210 | if (tb[IPSET_ATTR_PROTO]) { |
210 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 211 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
212 | with_ports = ip_set_proto_with_ports(data.proto); | ||
211 | 213 | ||
212 | if (data.proto == 0) | 214 | if (data.proto == 0) |
213 | return -IPSET_ERR_INVALID_PROTO; | 215 | return -IPSET_ERR_INVALID_PROTO; |
214 | } else | 216 | } else |
215 | return -IPSET_ERR_MISSING_PROTO; | 217 | return -IPSET_ERR_MISSING_PROTO; |
216 | 218 | ||
217 | switch (data.proto) { | 219 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
218 | case IPPROTO_UDP: | ||
219 | case IPPROTO_TCP: | ||
220 | case IPPROTO_ICMP: | ||
221 | break; | ||
222 | default: | ||
223 | data.port = 0; | 220 | data.port = 0; |
224 | break; | ||
225 | } | ||
226 | 221 | ||
227 | if (tb[IPSET_ATTR_TIMEOUT]) { | 222 | if (tb[IPSET_ATTR_TIMEOUT]) { |
228 | if (!with_timeout(h->timeout)) | 223 | if (!with_timeout(h->timeout)) |
@@ -231,7 +226,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
231 | } | 226 | } |
232 | 227 | ||
233 | if (adt == IPSET_TEST || | 228 | if (adt == IPSET_TEST || |
234 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
235 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || | 229 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || |
236 | tb[IPSET_ATTR_PORT_TO])) { | 230 | tb[IPSET_ATTR_PORT_TO])) { |
237 | ret = adtfn(set, &data, timeout); | 231 | ret = adtfn(set, &data, timeout); |
@@ -255,13 +249,12 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
255 | } else | 249 | } else |
256 | ip_to = ip; | 250 | ip_to = ip; |
257 | 251 | ||
258 | port = ntohs(data.port); | 252 | port_to = port = ntohs(data.port); |
259 | if (tb[IPSET_ATTR_PORT_TO]) { | 253 | if (with_ports && tb[IPSET_ATTR_PORT_TO]) { |
260 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); | 254 | port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); |
261 | if (port > port_to) | 255 | if (port > port_to) |
262 | swap(port, port_to); | 256 | swap(port, port_to); |
263 | } else | 257 | } |
264 | port_to = port; | ||
265 | 258 | ||
266 | for (; !before(ip_to, ip); ip++) | 259 | for (; !before(ip_to, ip); ip++) |
267 | for (p = port; p <= port_to; p++) { | 260 | for (p = port; p <= port_to; p++) { |
@@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
429 | struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; | 422 | struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; |
430 | u32 port, port_to; | 423 | u32 port, port_to; |
431 | u32 timeout = h->timeout; | 424 | u32 timeout = h->timeout; |
425 | bool with_ports = false; | ||
432 | int ret; | 426 | int ret; |
433 | 427 | ||
434 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || | 428 | if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || |
@@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
465 | 459 | ||
466 | if (tb[IPSET_ATTR_PROTO]) { | 460 | if (tb[IPSET_ATTR_PROTO]) { |
467 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 461 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
462 | with_ports = ip_set_proto_with_ports(data.proto); | ||
468 | 463 | ||
469 | if (data.proto == 0) | 464 | if (data.proto == 0) |
470 | return -IPSET_ERR_INVALID_PROTO; | 465 | return -IPSET_ERR_INVALID_PROTO; |
471 | } else | 466 | } else |
472 | return -IPSET_ERR_MISSING_PROTO; | 467 | return -IPSET_ERR_MISSING_PROTO; |
473 | 468 | ||
474 | switch (data.proto) { | 469 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
475 | case IPPROTO_UDP: | ||
476 | case IPPROTO_TCP: | ||
477 | case IPPROTO_ICMPV6: | ||
478 | break; | ||
479 | default: | ||
480 | data.port = 0; | 470 | data.port = 0; |
481 | break; | ||
482 | } | ||
483 | 471 | ||
484 | if (tb[IPSET_ATTR_TIMEOUT]) { | 472 | if (tb[IPSET_ATTR_TIMEOUT]) { |
485 | if (!with_timeout(h->timeout)) | 473 | if (!with_timeout(h->timeout)) |
@@ -487,9 +475,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
487 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 475 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
488 | } | 476 | } |
489 | 477 | ||
490 | if (adt == IPSET_TEST || | 478 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
491 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
492 | !tb[IPSET_ATTR_PORT_TO]) { | ||
493 | ret = adtfn(set, &data, timeout); | 479 | ret = adtfn(set, &data, timeout); |
494 | return ip_set_eexist(ret, flags) ? 0 : ret; | 480 | return ip_set_eexist(ret, flags) ? 0 : ret; |
495 | } | 481 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 34a165626ee9..8598676f2a05 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
170 | struct hash_netport4_elem data = { .cidr = HOST_MASK }; | 170 | struct hash_netport4_elem data = { .cidr = HOST_MASK }; |
171 | u32 port, port_to; | 171 | u32 port, port_to; |
172 | u32 timeout = h->timeout; | 172 | u32 timeout = h->timeout; |
173 | bool with_ports = false; | ||
173 | int ret; | 174 | int ret; |
174 | 175 | ||
175 | if (unlikely(!tb[IPSET_ATTR_IP] || | 176 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
198 | 199 | ||
199 | if (tb[IPSET_ATTR_PROTO]) { | 200 | if (tb[IPSET_ATTR_PROTO]) { |
200 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 201 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
202 | with_ports = ip_set_proto_with_ports(data.proto); | ||
201 | 203 | ||
202 | if (data.proto == 0) | 204 | if (data.proto == 0) |
203 | return -IPSET_ERR_INVALID_PROTO; | 205 | return -IPSET_ERR_INVALID_PROTO; |
204 | } else | 206 | } else |
205 | return -IPSET_ERR_MISSING_PROTO; | 207 | return -IPSET_ERR_MISSING_PROTO; |
206 | 208 | ||
207 | switch (data.proto) { | 209 | if (!(with_ports || data.proto == IPPROTO_ICMP)) |
208 | case IPPROTO_UDP: | ||
209 | case IPPROTO_TCP: | ||
210 | case IPPROTO_ICMP: | ||
211 | break; | ||
212 | default: | ||
213 | data.port = 0; | 210 | data.port = 0; |
214 | break; | ||
215 | } | ||
216 | 211 | ||
217 | if (tb[IPSET_ATTR_TIMEOUT]) { | 212 | if (tb[IPSET_ATTR_TIMEOUT]) { |
218 | if (!with_timeout(h->timeout)) | 213 | if (!with_timeout(h->timeout)) |
@@ -220,9 +215,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |||
220 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 215 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
221 | } | 216 | } |
222 | 217 | ||
223 | if (adt == IPSET_TEST || | 218 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
224 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
225 | !tb[IPSET_ATTR_PORT_TO]) { | ||
226 | ret = adtfn(set, &data, timeout); | 219 | ret = adtfn(set, &data, timeout); |
227 | return ip_set_eexist(ret, flags) ? 0 : ret; | 220 | return ip_set_eexist(ret, flags) ? 0 : ret; |
228 | } | 221 | } |
@@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
390 | struct hash_netport6_elem data = { .cidr = HOST_MASK }; | 383 | struct hash_netport6_elem data = { .cidr = HOST_MASK }; |
391 | u32 port, port_to; | 384 | u32 port, port_to; |
392 | u32 timeout = h->timeout; | 385 | u32 timeout = h->timeout; |
386 | bool with_ports = false; | ||
393 | int ret; | 387 | int ret; |
394 | 388 | ||
395 | if (unlikely(!tb[IPSET_ATTR_IP] || | 389 | if (unlikely(!tb[IPSET_ATTR_IP] || |
@@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
418 | 412 | ||
419 | if (tb[IPSET_ATTR_PROTO]) { | 413 | if (tb[IPSET_ATTR_PROTO]) { |
420 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); | 414 | data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); |
415 | with_ports = ip_set_proto_with_ports(data.proto); | ||
421 | 416 | ||
422 | if (data.proto == 0) | 417 | if (data.proto == 0) |
423 | return -IPSET_ERR_INVALID_PROTO; | 418 | return -IPSET_ERR_INVALID_PROTO; |
424 | } else | 419 | } else |
425 | return -IPSET_ERR_MISSING_PROTO; | 420 | return -IPSET_ERR_MISSING_PROTO; |
426 | 421 | ||
427 | switch (data.proto) { | 422 | if (!(with_ports || data.proto == IPPROTO_ICMPV6)) |
428 | case IPPROTO_UDP: | ||
429 | case IPPROTO_TCP: | ||
430 | case IPPROTO_ICMPV6: | ||
431 | break; | ||
432 | default: | ||
433 | data.port = 0; | 423 | data.port = 0; |
434 | break; | ||
435 | } | ||
436 | 424 | ||
437 | if (tb[IPSET_ATTR_TIMEOUT]) { | 425 | if (tb[IPSET_ATTR_TIMEOUT]) { |
438 | if (!with_timeout(h->timeout)) | 426 | if (!with_timeout(h->timeout)) |
@@ -440,9 +428,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], | |||
440 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); | 428 | timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); |
441 | } | 429 | } |
442 | 430 | ||
443 | if (adt == IPSET_TEST || | 431 | if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { |
444 | !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || | ||
445 | !tb[IPSET_ATTR_PORT_TO]) { | ||
446 | ret = adtfn(set, &data, timeout); | 432 | ret = adtfn(set, &data, timeout); |
447 | return ip_set_eexist(ret, flags) ? 0 : ret; | 433 | return ip_set_eexist(ret, flags) ? 0 : ret; |
448 | } | 434 | } |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index a47c32982f06..e9159e99fc4b 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -43,14 +43,19 @@ struct list_set { | |||
43 | static inline struct set_elem * | 43 | static inline struct set_elem * |
44 | list_set_elem(const struct list_set *map, u32 id) | 44 | list_set_elem(const struct list_set *map, u32 id) |
45 | { | 45 | { |
46 | return (struct set_elem *)((char *)map->members + id * map->dsize); | 46 | return (struct set_elem *)((void *)map->members + id * map->dsize); |
47 | } | ||
48 | |||
49 | static inline struct set_telem * | ||
50 | list_set_telem(const struct list_set *map, u32 id) | ||
51 | { | ||
52 | return (struct set_telem *)((void *)map->members + id * map->dsize); | ||
47 | } | 53 | } |
48 | 54 | ||
49 | static inline bool | 55 | static inline bool |
50 | list_set_timeout(const struct list_set *map, u32 id) | 56 | list_set_timeout(const struct list_set *map, u32 id) |
51 | { | 57 | { |
52 | const struct set_telem *elem = | 58 | const struct set_telem *elem = list_set_telem(map, id); |
53 | (const struct set_telem *) list_set_elem(map, id); | ||
54 | 59 | ||
55 | return ip_set_timeout_test(elem->timeout); | 60 | return ip_set_timeout_test(elem->timeout); |
56 | } | 61 | } |
@@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id) | |||
58 | static inline bool | 63 | static inline bool |
59 | list_set_expired(const struct list_set *map, u32 id) | 64 | list_set_expired(const struct list_set *map, u32 id) |
60 | { | 65 | { |
61 | const struct set_telem *elem = | 66 | const struct set_telem *elem = list_set_telem(map, id); |
62 | (const struct set_telem *) list_set_elem(map, id); | ||
63 | 67 | ||
64 | return ip_set_timeout_expired(elem->timeout); | 68 | return ip_set_timeout_expired(elem->timeout); |
65 | } | 69 | } |
66 | 70 | ||
67 | static inline int | ||
68 | list_set_exist(const struct set_telem *elem) | ||
69 | { | ||
70 | return elem->id != IPSET_INVALID_ID && | ||
71 | !ip_set_timeout_expired(elem->timeout); | ||
72 | } | ||
73 | |||
74 | /* Set list without and with timeout */ | 71 | /* Set list without and with timeout */ |
75 | 72 | ||
76 | static int | 73 | static int |
@@ -146,11 +143,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id, | |||
146 | struct set_telem *e; | 143 | struct set_telem *e; |
147 | 144 | ||
148 | for (; i < map->size; i++) { | 145 | for (; i < map->size; i++) { |
149 | e = (struct set_telem *)list_set_elem(map, i); | 146 | e = list_set_telem(map, i); |
150 | swap(e->id, id); | 147 | swap(e->id, id); |
148 | swap(e->timeout, timeout); | ||
151 | if (e->id == IPSET_INVALID_ID) | 149 | if (e->id == IPSET_INVALID_ID) |
152 | break; | 150 | break; |
153 | swap(e->timeout, timeout); | ||
154 | } | 151 | } |
155 | } | 152 | } |
156 | 153 | ||
@@ -164,7 +161,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, | |||
164 | /* Last element replaced: e.g. add new,before,last */ | 161 | /* Last element replaced: e.g. add new,before,last */ |
165 | ip_set_put_byindex(e->id); | 162 | ip_set_put_byindex(e->id); |
166 | if (with_timeout(map->timeout)) | 163 | if (with_timeout(map->timeout)) |
167 | list_elem_tadd(map, i, id, timeout); | 164 | list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); |
168 | else | 165 | else |
169 | list_elem_add(map, i, id); | 166 | list_elem_add(map, i, id); |
170 | 167 | ||
@@ -172,11 +169,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, | |||
172 | } | 169 | } |
173 | 170 | ||
174 | static int | 171 | static int |
175 | list_set_del(struct list_set *map, ip_set_id_t id, u32 i) | 172 | list_set_del(struct list_set *map, u32 i) |
176 | { | 173 | { |
177 | struct set_elem *a = list_set_elem(map, i), *b; | 174 | struct set_elem *a = list_set_elem(map, i), *b; |
178 | 175 | ||
179 | ip_set_put_byindex(id); | 176 | ip_set_put_byindex(a->id); |
180 | 177 | ||
181 | for (; i < map->size - 1; i++) { | 178 | for (; i < map->size - 1; i++) { |
182 | b = list_set_elem(map, i + 1); | 179 | b = list_set_elem(map, i + 1); |
@@ -308,11 +305,11 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
308 | (before == 0 || | 305 | (before == 0 || |
309 | (before > 0 && | 306 | (before > 0 && |
310 | next_id_eq(map, i, refid)))) | 307 | next_id_eq(map, i, refid)))) |
311 | ret = list_set_del(map, id, i); | 308 | ret = list_set_del(map, i); |
312 | else if (before < 0 && | 309 | else if (before < 0 && |
313 | elem->id == refid && | 310 | elem->id == refid && |
314 | next_id_eq(map, i, id)) | 311 | next_id_eq(map, i, id)) |
315 | ret = list_set_del(map, id, i + 1); | 312 | ret = list_set_del(map, i + 1); |
316 | } | 313 | } |
317 | break; | 314 | break; |
318 | default: | 315 | default: |
@@ -369,8 +366,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) | |||
369 | NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); | 366 | NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); |
370 | if (with_timeout(map->timeout)) | 367 | if (with_timeout(map->timeout)) |
371 | NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); | 368 | NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); |
372 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 369 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
373 | htonl(atomic_read(&set->ref) - 1)); | ||
374 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 370 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
375 | htonl(sizeof(*map) + map->size * map->dsize)); | 371 | htonl(sizeof(*map) + map->size * map->dsize)); |
376 | ipset_nest_end(skb, nested); | 372 | ipset_nest_end(skb, nested); |
@@ -461,16 +457,13 @@ list_set_gc(unsigned long ul_set) | |||
461 | struct set_telem *e; | 457 | struct set_telem *e; |
462 | u32 i; | 458 | u32 i; |
463 | 459 | ||
464 | /* We run parallel with other readers (test element) | 460 | write_lock_bh(&set->lock); |
465 | * but adding/deleting new entries is locked out */ | 461 | for (i = 0; i < map->size; i++) { |
466 | read_lock_bh(&set->lock); | 462 | e = list_set_telem(map, i); |
467 | for (i = map->size - 1; i >= 0; i--) { | 463 | if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) |
468 | e = (struct set_telem *) list_set_elem(map, i); | 464 | list_set_del(map, i); |
469 | if (e->id != IPSET_INVALID_ID && | ||
470 | list_set_expired(map, i)) | ||
471 | list_set_del(map, e->id, i); | ||
472 | } | 465 | } |
473 | read_unlock_bh(&set->lock); | 466 | write_unlock_bh(&set->lock); |
474 | 467 | ||
475 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; | 468 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; |
476 | add_timer(&map->gc); | 469 | add_timer(&map->gc); |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 5c48ffb60c28..059af3120be7 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -43,6 +43,8 @@ EXPORT_SYMBOL(register_ip_vs_app); | |||
43 | EXPORT_SYMBOL(unregister_ip_vs_app); | 43 | EXPORT_SYMBOL(unregister_ip_vs_app); |
44 | EXPORT_SYMBOL(register_ip_vs_app_inc); | 44 | EXPORT_SYMBOL(register_ip_vs_app_inc); |
45 | 45 | ||
46 | static DEFINE_MUTEX(__ip_vs_app_mutex); | ||
47 | |||
46 | /* | 48 | /* |
47 | * Get an ip_vs_app object | 49 | * Get an ip_vs_app object |
48 | */ | 50 | */ |
@@ -167,14 +169,13 @@ int | |||
167 | register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, | 169 | register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, |
168 | __u16 port) | 170 | __u16 port) |
169 | { | 171 | { |
170 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
171 | int result; | 172 | int result; |
172 | 173 | ||
173 | mutex_lock(&ipvs->app_mutex); | 174 | mutex_lock(&__ip_vs_app_mutex); |
174 | 175 | ||
175 | result = ip_vs_app_inc_new(net, app, proto, port); | 176 | result = ip_vs_app_inc_new(net, app, proto, port); |
176 | 177 | ||
177 | mutex_unlock(&ipvs->app_mutex); | 178 | mutex_unlock(&__ip_vs_app_mutex); |
178 | 179 | ||
179 | return result; | 180 | return result; |
180 | } | 181 | } |
@@ -189,11 +190,11 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
189 | /* increase the module use count */ | 190 | /* increase the module use count */ |
190 | ip_vs_use_count_inc(); | 191 | ip_vs_use_count_inc(); |
191 | 192 | ||
192 | mutex_lock(&ipvs->app_mutex); | 193 | mutex_lock(&__ip_vs_app_mutex); |
193 | 194 | ||
194 | list_add(&app->a_list, &ipvs->app_list); | 195 | list_add(&app->a_list, &ipvs->app_list); |
195 | 196 | ||
196 | mutex_unlock(&ipvs->app_mutex); | 197 | mutex_unlock(&__ip_vs_app_mutex); |
197 | 198 | ||
198 | return 0; | 199 | return 0; |
199 | } | 200 | } |
@@ -205,10 +206,9 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
205 | */ | 206 | */ |
206 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | 207 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) |
207 | { | 208 | { |
208 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
209 | struct ip_vs_app *inc, *nxt; | 209 | struct ip_vs_app *inc, *nxt; |
210 | 210 | ||
211 | mutex_lock(&ipvs->app_mutex); | 211 | mutex_lock(&__ip_vs_app_mutex); |
212 | 212 | ||
213 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { | 213 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { |
214 | ip_vs_app_inc_release(net, inc); | 214 | ip_vs_app_inc_release(net, inc); |
@@ -216,7 +216,7 @@ void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
216 | 216 | ||
217 | list_del(&app->a_list); | 217 | list_del(&app->a_list); |
218 | 218 | ||
219 | mutex_unlock(&ipvs->app_mutex); | 219 | mutex_unlock(&__ip_vs_app_mutex); |
220 | 220 | ||
221 | /* decrease the module use count */ | 221 | /* decrease the module use count */ |
222 | ip_vs_use_count_dec(); | 222 | ip_vs_use_count_dec(); |
@@ -501,7 +501,7 @@ static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos) | |||
501 | struct net *net = seq_file_net(seq); | 501 | struct net *net = seq_file_net(seq); |
502 | struct netns_ipvs *ipvs = net_ipvs(net); | 502 | struct netns_ipvs *ipvs = net_ipvs(net); |
503 | 503 | ||
504 | mutex_lock(&ipvs->app_mutex); | 504 | mutex_lock(&__ip_vs_app_mutex); |
505 | 505 | ||
506 | return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN; | 506 | return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN; |
507 | } | 507 | } |
@@ -535,9 +535,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
535 | 535 | ||
536 | static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) | 536 | static void ip_vs_app_seq_stop(struct seq_file *seq, void *v) |
537 | { | 537 | { |
538 | struct netns_ipvs *ipvs = net_ipvs(seq_file_net(seq)); | 538 | mutex_unlock(&__ip_vs_app_mutex); |
539 | |||
540 | mutex_unlock(&ipvs->app_mutex); | ||
541 | } | 539 | } |
542 | 540 | ||
543 | static int ip_vs_app_seq_show(struct seq_file *seq, void *v) | 541 | static int ip_vs_app_seq_show(struct seq_file *seq, void *v) |
@@ -574,40 +572,30 @@ static const struct file_operations ip_vs_app_fops = { | |||
574 | .open = ip_vs_app_open, | 572 | .open = ip_vs_app_open, |
575 | .read = seq_read, | 573 | .read = seq_read, |
576 | .llseek = seq_lseek, | 574 | .llseek = seq_lseek, |
577 | .release = seq_release, | 575 | .release = seq_release_net, |
578 | }; | 576 | }; |
579 | #endif | 577 | #endif |
580 | 578 | ||
581 | static int __net_init __ip_vs_app_init(struct net *net) | 579 | int __net_init __ip_vs_app_init(struct net *net) |
582 | { | 580 | { |
583 | struct netns_ipvs *ipvs = net_ipvs(net); | 581 | struct netns_ipvs *ipvs = net_ipvs(net); |
584 | 582 | ||
585 | INIT_LIST_HEAD(&ipvs->app_list); | 583 | INIT_LIST_HEAD(&ipvs->app_list); |
586 | __mutex_init(&ipvs->app_mutex, "ipvs->app_mutex", &ipvs->app_key); | ||
587 | proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops); | 584 | proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops); |
588 | return 0; | 585 | return 0; |
589 | } | 586 | } |
590 | 587 | ||
591 | static void __net_exit __ip_vs_app_cleanup(struct net *net) | 588 | void __net_exit __ip_vs_app_cleanup(struct net *net) |
592 | { | 589 | { |
593 | proc_net_remove(net, "ip_vs_app"); | 590 | proc_net_remove(net, "ip_vs_app"); |
594 | } | 591 | } |
595 | 592 | ||
596 | static struct pernet_operations ip_vs_app_ops = { | ||
597 | .init = __ip_vs_app_init, | ||
598 | .exit = __ip_vs_app_cleanup, | ||
599 | }; | ||
600 | |||
601 | int __init ip_vs_app_init(void) | 593 | int __init ip_vs_app_init(void) |
602 | { | 594 | { |
603 | int rv; | 595 | return 0; |
604 | |||
605 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
606 | return rv; | ||
607 | } | 596 | } |
608 | 597 | ||
609 | 598 | ||
610 | void ip_vs_app_cleanup(void) | 599 | void ip_vs_app_cleanup(void) |
611 | { | 600 | { |
612 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
613 | } | 601 | } |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index f289306cbf12..bf28ac2fc99b 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
@@ -595,7 +595,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) | |||
595 | atomic_inc(&dest->inactconns); | 595 | atomic_inc(&dest->inactconns); |
596 | } else { | 596 | } else { |
597 | /* It is a persistent connection/template, so increase | 597 | /* It is a persistent connection/template, so increase |
598 | the peristent connection counter */ | 598 | the persistent connection counter */ |
599 | atomic_inc(&dest->persistconns); | 599 | atomic_inc(&dest->persistconns); |
600 | } | 600 | } |
601 | 601 | ||
@@ -657,7 +657,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) | |||
657 | } | 657 | } |
658 | } else { | 658 | } else { |
659 | /* It is a persistent connection/template, so decrease | 659 | /* It is a persistent connection/template, so decrease |
660 | the peristent connection counter */ | 660 | the persistent connection counter */ |
661 | atomic_dec(&dest->persistconns); | 661 | atomic_dec(&dest->persistconns); |
662 | } | 662 | } |
663 | 663 | ||
@@ -1046,7 +1046,7 @@ static const struct file_operations ip_vs_conn_fops = { | |||
1046 | .open = ip_vs_conn_open, | 1046 | .open = ip_vs_conn_open, |
1047 | .read = seq_read, | 1047 | .read = seq_read, |
1048 | .llseek = seq_lseek, | 1048 | .llseek = seq_lseek, |
1049 | .release = seq_release, | 1049 | .release = seq_release_net, |
1050 | }; | 1050 | }; |
1051 | 1051 | ||
1052 | static const char *ip_vs_origin_name(unsigned flags) | 1052 | static const char *ip_vs_origin_name(unsigned flags) |
@@ -1114,7 +1114,7 @@ static const struct file_operations ip_vs_conn_sync_fops = { | |||
1114 | .open = ip_vs_conn_sync_open, | 1114 | .open = ip_vs_conn_sync_open, |
1115 | .read = seq_read, | 1115 | .read = seq_read, |
1116 | .llseek = seq_lseek, | 1116 | .llseek = seq_lseek, |
1117 | .release = seq_release, | 1117 | .release = seq_release_net, |
1118 | }; | 1118 | }; |
1119 | 1119 | ||
1120 | #endif | 1120 | #endif |
@@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net) | |||
1258 | return 0; | 1258 | return 0; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | static void __net_exit __ip_vs_conn_cleanup(struct net *net) | 1261 | void __net_exit __ip_vs_conn_cleanup(struct net *net) |
1262 | { | 1262 | { |
1263 | /* flush all the connection entries first */ | 1263 | /* flush all the connection entries first */ |
1264 | ip_vs_conn_flush(net); | 1264 | ip_vs_conn_flush(net); |
1265 | proc_net_remove(net, "ip_vs_conn"); | 1265 | proc_net_remove(net, "ip_vs_conn"); |
1266 | proc_net_remove(net, "ip_vs_conn_sync"); | 1266 | proc_net_remove(net, "ip_vs_conn_sync"); |
1267 | } | 1267 | } |
1268 | static struct pernet_operations ipvs_conn_ops = { | ||
1269 | .init = __ip_vs_conn_init, | ||
1270 | .exit = __ip_vs_conn_cleanup, | ||
1271 | }; | ||
1272 | 1268 | ||
1273 | int __init ip_vs_conn_init(void) | 1269 | int __init ip_vs_conn_init(void) |
1274 | { | 1270 | { |
1275 | int idx; | 1271 | int idx; |
1276 | int retc; | ||
1277 | 1272 | ||
1278 | /* Compute size and mask */ | 1273 | /* Compute size and mask */ |
1279 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; | 1274 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; |
@@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void) | |||
1309 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); | 1304 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); |
1310 | } | 1305 | } |
1311 | 1306 | ||
1312 | retc = register_pernet_subsys(&ipvs_conn_ops); | ||
1313 | |||
1314 | /* calculate the random value for connection hash */ | 1307 | /* calculate the random value for connection hash */ |
1315 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); | 1308 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); |
1316 | 1309 | ||
1317 | return retc; | 1310 | return 0; |
1318 | } | 1311 | } |
1319 | 1312 | ||
1320 | void ip_vs_conn_cleanup(void) | 1313 | void ip_vs_conn_cleanup(void) |
1321 | { | 1314 | { |
1322 | unregister_pernet_subsys(&ipvs_conn_ops); | ||
1323 | /* Release the empty cache */ | 1315 | /* Release the empty cache */ |
1324 | kmem_cache_destroy(ip_vs_conn_cachep); | 1316 | kmem_cache_destroy(ip_vs_conn_cachep); |
1325 | vfree(ip_vs_conn_tab); | 1317 | vfree(ip_vs_conn_tab); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 07accf6b2401..a74dae6c5dbc 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1113 | return NF_ACCEPT; | 1113 | return NF_ACCEPT; |
1114 | 1114 | ||
1115 | net = skb_net(skb); | 1115 | net = skb_net(skb); |
1116 | if (!net_ipvs(net)->enable) | ||
1117 | return NF_ACCEPT; | ||
1118 | |||
1116 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1119 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1117 | #ifdef CONFIG_IP_VS_IPV6 | 1120 | #ifdef CONFIG_IP_VS_IPV6 |
1118 | if (af == AF_INET6) { | 1121 | if (af == AF_INET6) { |
@@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1343 | return NF_ACCEPT; /* The packet looks wrong, ignore */ | 1346 | return NF_ACCEPT; /* The packet looks wrong, ignore */ |
1344 | 1347 | ||
1345 | net = skb_net(skb); | 1348 | net = skb_net(skb); |
1349 | |||
1346 | pd = ip_vs_proto_data_get(net, cih->protocol); | 1350 | pd = ip_vs_proto_data_get(net, cih->protocol); |
1347 | if (!pd) | 1351 | if (!pd) |
1348 | return NF_ACCEPT; | 1352 | return NF_ACCEPT; |
@@ -1529,6 +1533,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1529 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); | 1533 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); |
1530 | return NF_ACCEPT; | 1534 | return NF_ACCEPT; |
1531 | } | 1535 | } |
1536 | /* ipvs enabled in this netns ? */ | ||
1537 | net = skb_net(skb); | ||
1538 | if (!net_ipvs(net)->enable) | ||
1539 | return NF_ACCEPT; | ||
1540 | |||
1532 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1541 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1533 | 1542 | ||
1534 | /* Bad... Do not break raw sockets */ | 1543 | /* Bad... Do not break raw sockets */ |
@@ -1562,7 +1571,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1562 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1571 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1563 | } | 1572 | } |
1564 | 1573 | ||
1565 | net = skb_net(skb); | ||
1566 | /* Protocol supported? */ | 1574 | /* Protocol supported? */ |
1567 | pd = ip_vs_proto_data_get(net, iph.protocol); | 1575 | pd = ip_vs_proto_data_get(net, iph.protocol); |
1568 | if (unlikely(!pd)) | 1576 | if (unlikely(!pd)) |
@@ -1588,7 +1596,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1588 | } | 1596 | } |
1589 | 1597 | ||
1590 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); | 1598 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); |
1591 | net = skb_net(skb); | ||
1592 | ipvs = net_ipvs(net); | 1599 | ipvs = net_ipvs(net); |
1593 | /* Check the server status */ | 1600 | /* Check the server status */ |
1594 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { | 1601 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
@@ -1743,10 +1750,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, | |||
1743 | int (*okfn)(struct sk_buff *)) | 1750 | int (*okfn)(struct sk_buff *)) |
1744 | { | 1751 | { |
1745 | int r; | 1752 | int r; |
1753 | struct net *net; | ||
1746 | 1754 | ||
1747 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) | 1755 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
1748 | return NF_ACCEPT; | 1756 | return NF_ACCEPT; |
1749 | 1757 | ||
1758 | /* ipvs enabled in this netns ? */ | ||
1759 | net = skb_net(skb); | ||
1760 | if (!net_ipvs(net)->enable) | ||
1761 | return NF_ACCEPT; | ||
1762 | |||
1750 | return ip_vs_in_icmp(skb, &r, hooknum); | 1763 | return ip_vs_in_icmp(skb, &r, hooknum); |
1751 | } | 1764 | } |
1752 | 1765 | ||
@@ -1757,10 +1770,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, | |||
1757 | int (*okfn)(struct sk_buff *)) | 1770 | int (*okfn)(struct sk_buff *)) |
1758 | { | 1771 | { |
1759 | int r; | 1772 | int r; |
1773 | struct net *net; | ||
1760 | 1774 | ||
1761 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) | 1775 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) |
1762 | return NF_ACCEPT; | 1776 | return NF_ACCEPT; |
1763 | 1777 | ||
1778 | /* ipvs enabled in this netns ? */ | ||
1779 | net = skb_net(skb); | ||
1780 | if (!net_ipvs(net)->enable) | ||
1781 | return NF_ACCEPT; | ||
1782 | |||
1764 | return ip_vs_in_icmp_v6(skb, &r, hooknum); | 1783 | return ip_vs_in_icmp_v6(skb, &r, hooknum); |
1765 | } | 1784 | } |
1766 | #endif | 1785 | #endif |
@@ -1884,19 +1903,70 @@ static int __net_init __ip_vs_init(struct net *net) | |||
1884 | pr_err("%s(): no memory.\n", __func__); | 1903 | pr_err("%s(): no memory.\n", __func__); |
1885 | return -ENOMEM; | 1904 | return -ENOMEM; |
1886 | } | 1905 | } |
1906 | /* Hold the beast until a service is registerd */ | ||
1907 | ipvs->enable = 0; | ||
1887 | ipvs->net = net; | 1908 | ipvs->net = net; |
1888 | /* Counters used for creating unique names */ | 1909 | /* Counters used for creating unique names */ |
1889 | ipvs->gen = atomic_read(&ipvs_netns_cnt); | 1910 | ipvs->gen = atomic_read(&ipvs_netns_cnt); |
1890 | atomic_inc(&ipvs_netns_cnt); | 1911 | atomic_inc(&ipvs_netns_cnt); |
1891 | net->ipvs = ipvs; | 1912 | net->ipvs = ipvs; |
1913 | |||
1914 | if (__ip_vs_estimator_init(net) < 0) | ||
1915 | goto estimator_fail; | ||
1916 | |||
1917 | if (__ip_vs_control_init(net) < 0) | ||
1918 | goto control_fail; | ||
1919 | |||
1920 | if (__ip_vs_protocol_init(net) < 0) | ||
1921 | goto protocol_fail; | ||
1922 | |||
1923 | if (__ip_vs_app_init(net) < 0) | ||
1924 | goto app_fail; | ||
1925 | |||
1926 | if (__ip_vs_conn_init(net) < 0) | ||
1927 | goto conn_fail; | ||
1928 | |||
1929 | if (__ip_vs_sync_init(net) < 0) | ||
1930 | goto sync_fail; | ||
1931 | |||
1892 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", | 1932 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", |
1893 | sizeof(struct netns_ipvs), ipvs->gen); | 1933 | sizeof(struct netns_ipvs), ipvs->gen); |
1894 | return 0; | 1934 | return 0; |
1935 | /* | ||
1936 | * Error handling | ||
1937 | */ | ||
1938 | |||
1939 | sync_fail: | ||
1940 | __ip_vs_conn_cleanup(net); | ||
1941 | conn_fail: | ||
1942 | __ip_vs_app_cleanup(net); | ||
1943 | app_fail: | ||
1944 | __ip_vs_protocol_cleanup(net); | ||
1945 | protocol_fail: | ||
1946 | __ip_vs_control_cleanup(net); | ||
1947 | control_fail: | ||
1948 | __ip_vs_estimator_cleanup(net); | ||
1949 | estimator_fail: | ||
1950 | return -ENOMEM; | ||
1895 | } | 1951 | } |
1896 | 1952 | ||
1897 | static void __net_exit __ip_vs_cleanup(struct net *net) | 1953 | static void __net_exit __ip_vs_cleanup(struct net *net) |
1898 | { | 1954 | { |
1899 | IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen); | 1955 | __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */ |
1956 | __ip_vs_conn_cleanup(net); | ||
1957 | __ip_vs_app_cleanup(net); | ||
1958 | __ip_vs_protocol_cleanup(net); | ||
1959 | __ip_vs_control_cleanup(net); | ||
1960 | __ip_vs_estimator_cleanup(net); | ||
1961 | IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); | ||
1962 | } | ||
1963 | |||
1964 | static void __net_exit __ip_vs_dev_cleanup(struct net *net) | ||
1965 | { | ||
1966 | EnterFunction(2); | ||
1967 | net_ipvs(net)->enable = 0; /* Disable packet reception */ | ||
1968 | __ip_vs_sync_cleanup(net); | ||
1969 | LeaveFunction(2); | ||
1900 | } | 1970 | } |
1901 | 1971 | ||
1902 | static struct pernet_operations ipvs_core_ops = { | 1972 | static struct pernet_operations ipvs_core_ops = { |
@@ -1906,6 +1976,10 @@ static struct pernet_operations ipvs_core_ops = { | |||
1906 | .size = sizeof(struct netns_ipvs), | 1976 | .size = sizeof(struct netns_ipvs), |
1907 | }; | 1977 | }; |
1908 | 1978 | ||
1979 | static struct pernet_operations ipvs_core_dev_ops = { | ||
1980 | .exit = __ip_vs_dev_cleanup, | ||
1981 | }; | ||
1982 | |||
1909 | /* | 1983 | /* |
1910 | * Initialize IP Virtual Server | 1984 | * Initialize IP Virtual Server |
1911 | */ | 1985 | */ |
@@ -1913,10 +1987,6 @@ static int __init ip_vs_init(void) | |||
1913 | { | 1987 | { |
1914 | int ret; | 1988 | int ret; |
1915 | 1989 | ||
1916 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
1917 | if (ret < 0) | ||
1918 | return ret; | ||
1919 | |||
1920 | ip_vs_estimator_init(); | 1990 | ip_vs_estimator_init(); |
1921 | ret = ip_vs_control_init(); | 1991 | ret = ip_vs_control_init(); |
1922 | if (ret < 0) { | 1992 | if (ret < 0) { |
@@ -1944,15 +2014,28 @@ static int __init ip_vs_init(void) | |||
1944 | goto cleanup_conn; | 2014 | goto cleanup_conn; |
1945 | } | 2015 | } |
1946 | 2016 | ||
2017 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
2018 | if (ret < 0) | ||
2019 | goto cleanup_sync; | ||
2020 | |||
2021 | ret = register_pernet_device(&ipvs_core_dev_ops); | ||
2022 | if (ret < 0) | ||
2023 | goto cleanup_sub; | ||
2024 | |||
1947 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2025 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
1948 | if (ret < 0) { | 2026 | if (ret < 0) { |
1949 | pr_err("can't register hooks.\n"); | 2027 | pr_err("can't register hooks.\n"); |
1950 | goto cleanup_sync; | 2028 | goto cleanup_dev; |
1951 | } | 2029 | } |
1952 | 2030 | ||
1953 | pr_info("ipvs loaded.\n"); | 2031 | pr_info("ipvs loaded.\n"); |
2032 | |||
1954 | return ret; | 2033 | return ret; |
1955 | 2034 | ||
2035 | cleanup_dev: | ||
2036 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
2037 | cleanup_sub: | ||
2038 | unregister_pernet_subsys(&ipvs_core_ops); | ||
1956 | cleanup_sync: | 2039 | cleanup_sync: |
1957 | ip_vs_sync_cleanup(); | 2040 | ip_vs_sync_cleanup(); |
1958 | cleanup_conn: | 2041 | cleanup_conn: |
@@ -1964,20 +2047,20 @@ cleanup_sync: | |||
1964 | ip_vs_control_cleanup(); | 2047 | ip_vs_control_cleanup(); |
1965 | cleanup_estimator: | 2048 | cleanup_estimator: |
1966 | ip_vs_estimator_cleanup(); | 2049 | ip_vs_estimator_cleanup(); |
1967 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1968 | return ret; | 2050 | return ret; |
1969 | } | 2051 | } |
1970 | 2052 | ||
1971 | static void __exit ip_vs_cleanup(void) | 2053 | static void __exit ip_vs_cleanup(void) |
1972 | { | 2054 | { |
1973 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2055 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
2056 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
2057 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1974 | ip_vs_sync_cleanup(); | 2058 | ip_vs_sync_cleanup(); |
1975 | ip_vs_conn_cleanup(); | 2059 | ip_vs_conn_cleanup(); |
1976 | ip_vs_app_cleanup(); | 2060 | ip_vs_app_cleanup(); |
1977 | ip_vs_protocol_cleanup(); | 2061 | ip_vs_protocol_cleanup(); |
1978 | ip_vs_control_cleanup(); | 2062 | ip_vs_control_cleanup(); |
1979 | ip_vs_estimator_cleanup(); | 2063 | ip_vs_estimator_cleanup(); |
1980 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1981 | pr_info("ipvs unloaded.\n"); | 2064 | pr_info("ipvs unloaded.\n"); |
1982 | } | 2065 | } |
1983 | 2066 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index b799cea31f95..37890f228b19 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void) | |||
69 | } | 69 | } |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | |||
73 | /* Protos */ | ||
74 | static void __ip_vs_del_service(struct ip_vs_service *svc); | ||
75 | |||
76 | |||
72 | #ifdef CONFIG_IP_VS_IPV6 | 77 | #ifdef CONFIG_IP_VS_IPV6 |
73 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ | 78 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ |
74 | static int __ip_vs_addr_is_local_v6(struct net *net, | 79 | static int __ip_vs_addr_is_local_v6(struct net *net, |
@@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1214 | write_unlock_bh(&__ip_vs_svc_lock); | 1219 | write_unlock_bh(&__ip_vs_svc_lock); |
1215 | 1220 | ||
1216 | *svc_p = svc; | 1221 | *svc_p = svc; |
1222 | /* Now there is a service - full throttle */ | ||
1223 | ipvs->enable = 1; | ||
1217 | return 0; | 1224 | return 0; |
1218 | 1225 | ||
1219 | 1226 | ||
@@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net) | |||
1472 | return 0; | 1479 | return 0; |
1473 | } | 1480 | } |
1474 | 1481 | ||
1482 | /* | ||
1483 | * Delete service by {netns} in the service table. | ||
1484 | * Called by __ip_vs_cleanup() | ||
1485 | */ | ||
1486 | void __ip_vs_service_cleanup(struct net *net) | ||
1487 | { | ||
1488 | EnterFunction(2); | ||
1489 | /* Check for "full" addressed entries */ | ||
1490 | mutex_lock(&__ip_vs_mutex); | ||
1491 | ip_vs_flush(net); | ||
1492 | mutex_unlock(&__ip_vs_mutex); | ||
1493 | LeaveFunction(2); | ||
1494 | } | ||
1495 | /* | ||
1496 | * Release dst hold by dst_cache | ||
1497 | */ | ||
1498 | static inline void | ||
1499 | __ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev) | ||
1500 | { | ||
1501 | spin_lock_bh(&dest->dst_lock); | ||
1502 | if (dest->dst_cache && dest->dst_cache->dev == dev) { | ||
1503 | IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n", | ||
1504 | dev->name, | ||
1505 | IP_VS_DBG_ADDR(dest->af, &dest->addr), | ||
1506 | ntohs(dest->port), | ||
1507 | atomic_read(&dest->refcnt)); | ||
1508 | ip_vs_dst_reset(dest); | ||
1509 | } | ||
1510 | spin_unlock_bh(&dest->dst_lock); | ||
1511 | |||
1512 | } | ||
1513 | /* | ||
1514 | * Netdev event receiver | ||
1515 | * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to | ||
1516 | * a device that is "unregister" it must be released. | ||
1517 | */ | ||
1518 | static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, | ||
1519 | void *ptr) | ||
1520 | { | ||
1521 | struct net_device *dev = ptr; | ||
1522 | struct net *net = dev_net(dev); | ||
1523 | struct ip_vs_service *svc; | ||
1524 | struct ip_vs_dest *dest; | ||
1525 | unsigned int idx; | ||
1526 | |||
1527 | if (event != NETDEV_UNREGISTER) | ||
1528 | return NOTIFY_DONE; | ||
1529 | IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); | ||
1530 | EnterFunction(2); | ||
1531 | mutex_lock(&__ip_vs_mutex); | ||
1532 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | ||
1533 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | ||
1534 | if (net_eq(svc->net, net)) { | ||
1535 | list_for_each_entry(dest, &svc->destinations, | ||
1536 | n_list) { | ||
1537 | __ip_vs_dev_reset(dest, dev); | ||
1538 | } | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | ||
1543 | if (net_eq(svc->net, net)) { | ||
1544 | list_for_each_entry(dest, &svc->destinations, | ||
1545 | n_list) { | ||
1546 | __ip_vs_dev_reset(dest, dev); | ||
1547 | } | ||
1548 | } | ||
1549 | |||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { | ||
1554 | __ip_vs_dev_reset(dest, dev); | ||
1555 | } | ||
1556 | mutex_unlock(&__ip_vs_mutex); | ||
1557 | LeaveFunction(2); | ||
1558 | return NOTIFY_DONE; | ||
1559 | } | ||
1475 | 1560 | ||
1476 | /* | 1561 | /* |
1477 | * Zero counters in a service or all services | 1562 | * Zero counters in a service or all services |
@@ -1981,7 +2066,7 @@ static const struct file_operations ip_vs_info_fops = { | |||
1981 | .open = ip_vs_info_open, | 2066 | .open = ip_vs_info_open, |
1982 | .read = seq_read, | 2067 | .read = seq_read, |
1983 | .llseek = seq_lseek, | 2068 | .llseek = seq_lseek, |
1984 | .release = seq_release_private, | 2069 | .release = seq_release_net, |
1985 | }; | 2070 | }; |
1986 | 2071 | ||
1987 | #endif | 2072 | #endif |
@@ -2024,7 +2109,7 @@ static const struct file_operations ip_vs_stats_fops = { | |||
2024 | .open = ip_vs_stats_seq_open, | 2109 | .open = ip_vs_stats_seq_open, |
2025 | .read = seq_read, | 2110 | .read = seq_read, |
2026 | .llseek = seq_lseek, | 2111 | .llseek = seq_lseek, |
2027 | .release = single_release, | 2112 | .release = single_release_net, |
2028 | }; | 2113 | }; |
2029 | 2114 | ||
2030 | static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) | 2115 | static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) |
@@ -2093,7 +2178,7 @@ static const struct file_operations ip_vs_stats_percpu_fops = { | |||
2093 | .open = ip_vs_stats_percpu_seq_open, | 2178 | .open = ip_vs_stats_percpu_seq_open, |
2094 | .read = seq_read, | 2179 | .read = seq_read, |
2095 | .llseek = seq_lseek, | 2180 | .llseek = seq_lseek, |
2096 | .release = single_release, | 2181 | .release = single_release_net, |
2097 | }; | 2182 | }; |
2098 | #endif | 2183 | #endif |
2099 | 2184 | ||
@@ -3120,7 +3205,7 @@ nla_put_failure: | |||
3120 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | 3205 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, |
3121 | struct netlink_callback *cb) | 3206 | struct netlink_callback *cb) |
3122 | { | 3207 | { |
3123 | struct net *net = skb_net(skb); | 3208 | struct net *net = skb_sknet(skb); |
3124 | struct netns_ipvs *ipvs = net_ipvs(net); | 3209 | struct netns_ipvs *ipvs = net_ipvs(net); |
3125 | 3210 | ||
3126 | mutex_lock(&__ip_vs_mutex); | 3211 | mutex_lock(&__ip_vs_mutex); |
@@ -3588,6 +3673,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { } | |||
3588 | 3673 | ||
3589 | #endif | 3674 | #endif |
3590 | 3675 | ||
3676 | static struct notifier_block ip_vs_dst_notifier = { | ||
3677 | .notifier_call = ip_vs_dst_event, | ||
3678 | }; | ||
3679 | |||
3591 | int __net_init __ip_vs_control_init(struct net *net) | 3680 | int __net_init __ip_vs_control_init(struct net *net) |
3592 | { | 3681 | { |
3593 | int idx; | 3682 | int idx; |
@@ -3605,7 +3694,7 @@ int __net_init __ip_vs_control_init(struct net *net) | |||
3605 | 3694 | ||
3606 | /* procfs stats */ | 3695 | /* procfs stats */ |
3607 | ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); | 3696 | ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); |
3608 | if (ipvs->tot_stats.cpustats) { | 3697 | if (!ipvs->tot_stats.cpustats) { |
3609 | pr_err("%s(): alloc_percpu.\n", __func__); | 3698 | pr_err("%s(): alloc_percpu.\n", __func__); |
3610 | return -ENOMEM; | 3699 | return -ENOMEM; |
3611 | } | 3700 | } |
@@ -3626,7 +3715,7 @@ err: | |||
3626 | return -ENOMEM; | 3715 | return -ENOMEM; |
3627 | } | 3716 | } |
3628 | 3717 | ||
3629 | static void __net_exit __ip_vs_control_cleanup(struct net *net) | 3718 | void __net_exit __ip_vs_control_cleanup(struct net *net) |
3630 | { | 3719 | { |
3631 | struct netns_ipvs *ipvs = net_ipvs(net); | 3720 | struct netns_ipvs *ipvs = net_ipvs(net); |
3632 | 3721 | ||
@@ -3639,11 +3728,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net) | |||
3639 | free_percpu(ipvs->tot_stats.cpustats); | 3728 | free_percpu(ipvs->tot_stats.cpustats); |
3640 | } | 3729 | } |
3641 | 3730 | ||
3642 | static struct pernet_operations ipvs_control_ops = { | ||
3643 | .init = __ip_vs_control_init, | ||
3644 | .exit = __ip_vs_control_cleanup, | ||
3645 | }; | ||
3646 | |||
3647 | int __init ip_vs_control_init(void) | 3731 | int __init ip_vs_control_init(void) |
3648 | { | 3732 | { |
3649 | int idx; | 3733 | int idx; |
@@ -3657,33 +3741,32 @@ int __init ip_vs_control_init(void) | |||
3657 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | 3741 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); |
3658 | } | 3742 | } |
3659 | 3743 | ||
3660 | ret = register_pernet_subsys(&ipvs_control_ops); | ||
3661 | if (ret) { | ||
3662 | pr_err("cannot register namespace.\n"); | ||
3663 | goto err; | ||
3664 | } | ||
3665 | |||
3666 | smp_wmb(); /* Do we really need it now ? */ | 3744 | smp_wmb(); /* Do we really need it now ? */ |
3667 | 3745 | ||
3668 | ret = nf_register_sockopt(&ip_vs_sockopts); | 3746 | ret = nf_register_sockopt(&ip_vs_sockopts); |
3669 | if (ret) { | 3747 | if (ret) { |
3670 | pr_err("cannot register sockopt.\n"); | 3748 | pr_err("cannot register sockopt.\n"); |
3671 | goto err_net; | 3749 | goto err_sock; |
3672 | } | 3750 | } |
3673 | 3751 | ||
3674 | ret = ip_vs_genl_register(); | 3752 | ret = ip_vs_genl_register(); |
3675 | if (ret) { | 3753 | if (ret) { |
3676 | pr_err("cannot register Generic Netlink interface.\n"); | 3754 | pr_err("cannot register Generic Netlink interface.\n"); |
3677 | nf_unregister_sockopt(&ip_vs_sockopts); | 3755 | goto err_genl; |
3678 | goto err_net; | ||
3679 | } | 3756 | } |
3680 | 3757 | ||
3758 | ret = register_netdevice_notifier(&ip_vs_dst_notifier); | ||
3759 | if (ret < 0) | ||
3760 | goto err_notf; | ||
3761 | |||
3681 | LeaveFunction(2); | 3762 | LeaveFunction(2); |
3682 | return 0; | 3763 | return 0; |
3683 | 3764 | ||
3684 | err_net: | 3765 | err_notf: |
3685 | unregister_pernet_subsys(&ipvs_control_ops); | 3766 | ip_vs_genl_unregister(); |
3686 | err: | 3767 | err_genl: |
3768 | nf_unregister_sockopt(&ip_vs_sockopts); | ||
3769 | err_sock: | ||
3687 | return ret; | 3770 | return ret; |
3688 | } | 3771 | } |
3689 | 3772 | ||
@@ -3691,7 +3774,6 @@ err: | |||
3691 | void ip_vs_control_cleanup(void) | 3774 | void ip_vs_control_cleanup(void) |
3692 | { | 3775 | { |
3693 | EnterFunction(2); | 3776 | EnterFunction(2); |
3694 | unregister_pernet_subsys(&ipvs_control_ops); | ||
3695 | ip_vs_genl_unregister(); | 3777 | ip_vs_genl_unregister(); |
3696 | nf_unregister_sockopt(&ip_vs_sockopts); | 3778 | nf_unregister_sockopt(&ip_vs_sockopts); |
3697 | LeaveFunction(2); | 3779 | LeaveFunction(2); |
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 8c8766ca56ad..508cce98777c 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c | |||
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | |||
192 | dst->outbps = (e->outbps + 0xF) >> 5; | 192 | dst->outbps = (e->outbps + 0xF) >> 5; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int __net_init __ip_vs_estimator_init(struct net *net) | 195 | int __net_init __ip_vs_estimator_init(struct net *net) |
196 | { | 196 | { |
197 | struct netns_ipvs *ipvs = net_ipvs(net); | 197 | struct netns_ipvs *ipvs = net_ipvs(net); |
198 | 198 | ||
@@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net) | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | static void __net_exit __ip_vs_estimator_exit(struct net *net) | 206 | void __net_exit __ip_vs_estimator_cleanup(struct net *net) |
207 | { | 207 | { |
208 | del_timer_sync(&net_ipvs(net)->est_timer); | 208 | del_timer_sync(&net_ipvs(net)->est_timer); |
209 | } | 209 | } |
210 | static struct pernet_operations ip_vs_app_ops = { | ||
211 | .init = __ip_vs_estimator_init, | ||
212 | .exit = __ip_vs_estimator_exit, | ||
213 | }; | ||
214 | 210 | ||
215 | int __init ip_vs_estimator_init(void) | 211 | int __init ip_vs_estimator_init(void) |
216 | { | 212 | { |
217 | int rv; | 213 | return 0; |
218 | |||
219 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
220 | return rv; | ||
221 | } | 214 | } |
222 | 215 | ||
223 | void ip_vs_estimator_cleanup(void) | 216 | void ip_vs_estimator_cleanup(void) |
224 | { | 217 | { |
225 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
226 | } | 218 | } |
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index f276df9896b3..87e40ea77a95 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c | |||
@@ -131,7 +131,7 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) | |||
131 | { | 131 | { |
132 | list_del(&en->list); | 132 | list_del(&en->list); |
133 | /* | 133 | /* |
134 | * We don't kfree dest because it is refered either by its service | 134 | * We don't kfree dest because it is referred either by its service |
135 | * or the trash dest list. | 135 | * or the trash dest list. |
136 | */ | 136 | */ |
137 | atomic_dec(&en->dest->refcnt); | 137 | atomic_dec(&en->dest->refcnt); |
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index cb1c9913d38b..90f618ab6dda 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c | |||
@@ -152,7 +152,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) | |||
152 | write_lock(&set->lock); | 152 | write_lock(&set->lock); |
153 | list_for_each_entry_safe(e, ep, &set->list, list) { | 153 | list_for_each_entry_safe(e, ep, &set->list, list) { |
154 | /* | 154 | /* |
155 | * We don't kfree dest because it is refered either | 155 | * We don't kfree dest because it is referred either |
156 | * by its service or by the trash dest list. | 156 | * by its service or by the trash dest list. |
157 | */ | 157 | */ |
158 | atomic_dec(&e->dest->refcnt); | 158 | atomic_dec(&e->dest->refcnt); |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 17484a4416ef..eb86028536fc 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, | |||
316 | /* | 316 | /* |
317 | * per network name-space init | 317 | * per network name-space init |
318 | */ | 318 | */ |
319 | static int __net_init __ip_vs_protocol_init(struct net *net) | 319 | int __net_init __ip_vs_protocol_init(struct net *net) |
320 | { | 320 | { |
321 | #ifdef CONFIG_IP_VS_PROTO_TCP | 321 | #ifdef CONFIG_IP_VS_PROTO_TCP |
322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); | 322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); |
@@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net) | |||
336 | return 0; | 336 | return 0; |
337 | } | 337 | } |
338 | 338 | ||
339 | static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | 339 | void __net_exit __ip_vs_protocol_cleanup(struct net *net) |
340 | { | 340 | { |
341 | struct netns_ipvs *ipvs = net_ipvs(net); | 341 | struct netns_ipvs *ipvs = net_ipvs(net); |
342 | struct ip_vs_proto_data *pd; | 342 | struct ip_vs_proto_data *pd; |
@@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | |||
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | static struct pernet_operations ipvs_proto_ops = { | ||
353 | .init = __ip_vs_protocol_init, | ||
354 | .exit = __ip_vs_protocol_cleanup, | ||
355 | }; | ||
356 | |||
357 | int __init ip_vs_protocol_init(void) | 352 | int __init ip_vs_protocol_init(void) |
358 | { | 353 | { |
359 | char protocols[64]; | 354 | char protocols[64]; |
@@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void) | |||
382 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); | 377 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); |
383 | #endif | 378 | #endif |
384 | pr_info("Registered protocols (%s)\n", &protocols[2]); | 379 | pr_info("Registered protocols (%s)\n", &protocols[2]); |
385 | return register_pernet_subsys(&ipvs_proto_ops); | ||
386 | 380 | ||
387 | return 0; | 381 | return 0; |
388 | } | 382 | } |
@@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void) | |||
393 | struct ip_vs_protocol *pp; | 387 | struct ip_vs_protocol *pp; |
394 | int i; | 388 | int i; |
395 | 389 | ||
396 | unregister_pernet_subsys(&ipvs_proto_ops); | ||
397 | /* unregister all the ipvs protocols */ | 390 | /* unregister all the ipvs protocols */ |
398 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { | 391 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { |
399 | while ((pp = ip_vs_proto_table[i]) != NULL) | 392 | while ((pp = ip_vs_proto_table[i]) != NULL) |
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index b027ccc49f43..d12ed53ec95f 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -566,7 +566,7 @@ static struct ipvs_sctp_nextstate | |||
566 | * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server | 566 | * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server |
567 | */ | 567 | */ |
568 | /* | 568 | /* |
569 | * We recieved the data chuck, keep the state unchanged. I assume | 569 | * We received the data chuck, keep the state unchanged. I assume |
570 | * that still data chuncks can be received by both the peers in | 570 | * that still data chuncks can be received by both the peers in |
571 | * SHUDOWN state | 571 | * SHUDOWN state |
572 | */ | 572 | */ |
@@ -633,7 +633,7 @@ static struct ipvs_sctp_nextstate | |||
633 | * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client | 633 | * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client |
634 | */ | 634 | */ |
635 | /* | 635 | /* |
636 | * We recieved the data chuck, keep the state unchanged. I assume | 636 | * We received the data chuck, keep the state unchanged. I assume |
637 | * that still data chuncks can be received by both the peers in | 637 | * that still data chuncks can be received by both the peers in |
638 | * SHUDOWN state | 638 | * SHUDOWN state |
639 | */ | 639 | */ |
@@ -701,7 +701,7 @@ static struct ipvs_sctp_nextstate | |||
701 | * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server | 701 | * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server |
702 | */ | 702 | */ |
703 | /* | 703 | /* |
704 | * We recieved the data chuck, keep the state unchanged. I assume | 704 | * We received the data chuck, keep the state unchanged. I assume |
705 | * that still data chuncks can be received by both the peers in | 705 | * that still data chuncks can be received by both the peers in |
706 | * SHUDOWN state | 706 | * SHUDOWN state |
707 | */ | 707 | */ |
@@ -771,7 +771,7 @@ static struct ipvs_sctp_nextstate | |||
771 | * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client | 771 | * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client |
772 | */ | 772 | */ |
773 | /* | 773 | /* |
774 | * We recieved the data chuck, keep the state unchanged. I assume | 774 | * We received the data chuck, keep the state unchanged. I assume |
775 | * that still data chuncks can be received by both the peers in | 775 | * that still data chuncks can be received by both the peers in |
776 | * SHUDOWN state | 776 | * SHUDOWN state |
777 | */ | 777 | */ |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 3e7961e85e9c..e292e5bddc70 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net) | |||
1303 | struct socket *sock; | 1303 | struct socket *sock; |
1304 | int result; | 1304 | int result; |
1305 | 1305 | ||
1306 | /* First create a socket */ | 1306 | /* First create a socket move it to right name space later */ |
1307 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1307 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1308 | if (result < 0) { | 1308 | if (result < 0) { |
1309 | pr_err("Error during creation of socket; terminating\n"); | 1309 | pr_err("Error during creation of socket; terminating\n"); |
1310 | return ERR_PTR(result); | 1310 | return ERR_PTR(result); |
1311 | } | 1311 | } |
1312 | 1312 | /* | |
1313 | * Kernel sockets that are a part of a namespace, should not | ||
1314 | * hold a reference to a namespace in order to allow to stop it. | ||
1315 | * After sk_change_net should be released using sk_release_kernel. | ||
1316 | */ | ||
1317 | sk_change_net(sock->sk, net); | ||
1313 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); | 1318 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); |
1314 | if (result < 0) { | 1319 | if (result < 0) { |
1315 | pr_err("Error setting outbound mcast interface\n"); | 1320 | pr_err("Error setting outbound mcast interface\n"); |
@@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net) | |||
1334 | 1339 | ||
1335 | return sock; | 1340 | return sock; |
1336 | 1341 | ||
1337 | error: | 1342 | error: |
1338 | sock_release(sock); | 1343 | sk_release_kernel(sock->sk); |
1339 | return ERR_PTR(result); | 1344 | return ERR_PTR(result); |
1340 | } | 1345 | } |
1341 | 1346 | ||
@@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net) | |||
1350 | int result; | 1355 | int result; |
1351 | 1356 | ||
1352 | /* First create a socket */ | 1357 | /* First create a socket */ |
1353 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1358 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1354 | if (result < 0) { | 1359 | if (result < 0) { |
1355 | pr_err("Error during creation of socket; terminating\n"); | 1360 | pr_err("Error during creation of socket; terminating\n"); |
1356 | return ERR_PTR(result); | 1361 | return ERR_PTR(result); |
1357 | } | 1362 | } |
1358 | 1363 | /* | |
1364 | * Kernel sockets that are a part of a namespace, should not | ||
1365 | * hold a reference to a namespace in order to allow to stop it. | ||
1366 | * After sk_change_net should be released using sk_release_kernel. | ||
1367 | */ | ||
1368 | sk_change_net(sock->sk, net); | ||
1359 | /* it is equivalent to the REUSEADDR option in user-space */ | 1369 | /* it is equivalent to the REUSEADDR option in user-space */ |
1360 | sock->sk->sk_reuse = 1; | 1370 | sock->sk->sk_reuse = 1; |
1361 | 1371 | ||
@@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net) | |||
1377 | 1387 | ||
1378 | return sock; | 1388 | return sock; |
1379 | 1389 | ||
1380 | error: | 1390 | error: |
1381 | sock_release(sock); | 1391 | sk_release_kernel(sock->sk); |
1382 | return ERR_PTR(result); | 1392 | return ERR_PTR(result); |
1383 | } | 1393 | } |
1384 | 1394 | ||
@@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data) | |||
1473 | ip_vs_sync_buff_release(sb); | 1483 | ip_vs_sync_buff_release(sb); |
1474 | 1484 | ||
1475 | /* release the sending multicast socket */ | 1485 | /* release the sending multicast socket */ |
1476 | sock_release(tinfo->sock); | 1486 | sk_release_kernel(tinfo->sock->sk); |
1477 | kfree(tinfo); | 1487 | kfree(tinfo); |
1478 | 1488 | ||
1479 | return 0; | 1489 | return 0; |
@@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data) | |||
1513 | } | 1523 | } |
1514 | 1524 | ||
1515 | /* release the sending multicast socket */ | 1525 | /* release the sending multicast socket */ |
1516 | sock_release(tinfo->sock); | 1526 | sk_release_kernel(tinfo->sock->sk); |
1517 | kfree(tinfo->buf); | 1527 | kfree(tinfo->buf); |
1518 | kfree(tinfo); | 1528 | kfree(tinfo); |
1519 | 1529 | ||
@@ -1601,7 +1611,7 @@ outtinfo: | |||
1601 | outbuf: | 1611 | outbuf: |
1602 | kfree(buf); | 1612 | kfree(buf); |
1603 | outsocket: | 1613 | outsocket: |
1604 | sock_release(sock); | 1614 | sk_release_kernel(sock->sk); |
1605 | out: | 1615 | out: |
1606 | return result; | 1616 | return result; |
1607 | } | 1617 | } |
@@ -1610,6 +1620,7 @@ out: | |||
1610 | int stop_sync_thread(struct net *net, int state) | 1620 | int stop_sync_thread(struct net *net, int state) |
1611 | { | 1621 | { |
1612 | struct netns_ipvs *ipvs = net_ipvs(net); | 1622 | struct netns_ipvs *ipvs = net_ipvs(net); |
1623 | int retc = -EINVAL; | ||
1613 | 1624 | ||
1614 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); | 1625 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); |
1615 | 1626 | ||
@@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state) | |||
1629 | spin_lock_bh(&ipvs->sync_lock); | 1640 | spin_lock_bh(&ipvs->sync_lock); |
1630 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; | 1641 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; |
1631 | spin_unlock_bh(&ipvs->sync_lock); | 1642 | spin_unlock_bh(&ipvs->sync_lock); |
1632 | kthread_stop(ipvs->master_thread); | 1643 | retc = kthread_stop(ipvs->master_thread); |
1633 | ipvs->master_thread = NULL; | 1644 | ipvs->master_thread = NULL; |
1634 | } else if (state == IP_VS_STATE_BACKUP) { | 1645 | } else if (state == IP_VS_STATE_BACKUP) { |
1635 | if (!ipvs->backup_thread) | 1646 | if (!ipvs->backup_thread) |
@@ -1639,22 +1650,20 @@ int stop_sync_thread(struct net *net, int state) | |||
1639 | task_pid_nr(ipvs->backup_thread)); | 1650 | task_pid_nr(ipvs->backup_thread)); |
1640 | 1651 | ||
1641 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; | 1652 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; |
1642 | kthread_stop(ipvs->backup_thread); | 1653 | retc = kthread_stop(ipvs->backup_thread); |
1643 | ipvs->backup_thread = NULL; | 1654 | ipvs->backup_thread = NULL; |
1644 | } else { | ||
1645 | return -EINVAL; | ||
1646 | } | 1655 | } |
1647 | 1656 | ||
1648 | /* decrease the module use count */ | 1657 | /* decrease the module use count */ |
1649 | ip_vs_use_count_dec(); | 1658 | ip_vs_use_count_dec(); |
1650 | 1659 | ||
1651 | return 0; | 1660 | return retc; |
1652 | } | 1661 | } |
1653 | 1662 | ||
1654 | /* | 1663 | /* |
1655 | * Initialize data struct for each netns | 1664 | * Initialize data struct for each netns |
1656 | */ | 1665 | */ |
1657 | static int __net_init __ip_vs_sync_init(struct net *net) | 1666 | int __net_init __ip_vs_sync_init(struct net *net) |
1658 | { | 1667 | { |
1659 | struct netns_ipvs *ipvs = net_ipvs(net); | 1668 | struct netns_ipvs *ipvs = net_ipvs(net); |
1660 | 1669 | ||
@@ -1668,24 +1677,24 @@ static int __net_init __ip_vs_sync_init(struct net *net) | |||
1668 | return 0; | 1677 | return 0; |
1669 | } | 1678 | } |
1670 | 1679 | ||
1671 | static void __ip_vs_sync_cleanup(struct net *net) | 1680 | void __ip_vs_sync_cleanup(struct net *net) |
1672 | { | 1681 | { |
1673 | stop_sync_thread(net, IP_VS_STATE_MASTER); | 1682 | int retc; |
1674 | stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
1675 | } | ||
1676 | 1683 | ||
1677 | static struct pernet_operations ipvs_sync_ops = { | 1684 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); |
1678 | .init = __ip_vs_sync_init, | 1685 | if (retc && retc != -ESRCH) |
1679 | .exit = __ip_vs_sync_cleanup, | 1686 | pr_err("Failed to stop Master Daemon\n"); |
1680 | }; | ||
1681 | 1687 | ||
1688 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
1689 | if (retc && retc != -ESRCH) | ||
1690 | pr_err("Failed to stop Backup Daemon\n"); | ||
1691 | } | ||
1682 | 1692 | ||
1683 | int __init ip_vs_sync_init(void) | 1693 | int __init ip_vs_sync_init(void) |
1684 | { | 1694 | { |
1685 | return register_pernet_subsys(&ipvs_sync_ops); | 1695 | return 0; |
1686 | } | 1696 | } |
1687 | 1697 | ||
1688 | void ip_vs_sync_cleanup(void) | 1698 | void ip_vs_sync_cleanup(void) |
1689 | { | 1699 | { |
1690 | unregister_pernet_subsys(&ipvs_sync_ops); | ||
1691 | } | 1700 | } |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 941286ca911d..2e1c11f78419 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -453,7 +453,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
453 | REJECT will give spurious warnings here. */ | 453 | REJECT will give spurious warnings here. */ |
454 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ | 454 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ |
455 | 455 | ||
456 | /* No external references means noone else could have | 456 | /* No external references means no one else could have |
457 | confirmed us. */ | 457 | confirmed us. */ |
458 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 458 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
459 | pr_debug("Confirming conntrack %p\n", ct); | 459 | pr_debug("Confirming conntrack %p\n", ct); |
@@ -901,7 +901,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
901 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), | 901 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), |
902 | &dataoff, &protonum); | 902 | &dataoff, &protonum); |
903 | if (ret <= 0) { | 903 | if (ret <= 0) { |
904 | pr_debug("not prepared to track yet or error occured\n"); | 904 | pr_debug("not prepared to track yet or error occurred\n"); |
905 | NF_CT_STAT_INC_ATOMIC(net, error); | 905 | NF_CT_STAT_INC_ATOMIC(net, error); |
906 | NF_CT_STAT_INC_ATOMIC(net, invalid); | 906 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
907 | ret = -ret; | 907 | ret = -ret; |
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c index 867882313e49..bcd5ed6b7130 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c | |||
@@ -631,7 +631,7 @@ static int decode_seqof(bitstr_t *bs, const struct field_t *f, | |||
631 | CHECK_BOUND(bs, 2); | 631 | CHECK_BOUND(bs, 2); |
632 | count = *bs->cur++; | 632 | count = *bs->cur++; |
633 | count <<= 8; | 633 | count <<= 8; |
634 | count = *bs->cur++; | 634 | count += *bs->cur++; |
635 | break; | 635 | break; |
636 | case SEMI: | 636 | case SEMI: |
637 | BYTE_ALIGN(bs); | 637 | BYTE_ALIGN(bs); |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 533a183e6661..18b2ce5c8ced 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -731,10 +731,10 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
731 | 731 | ||
732 | memset(&fl2, 0, sizeof(fl2)); | 732 | memset(&fl2, 0, sizeof(fl2)); |
733 | fl2.daddr = dst->ip; | 733 | fl2.daddr = dst->ip; |
734 | if (!afinfo->route((struct dst_entry **)&rt1, | 734 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, |
735 | flowi4_to_flowi(&fl1))) { | 735 | flowi4_to_flowi(&fl1), false)) { |
736 | if (!afinfo->route((struct dst_entry **)&rt2, | 736 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, |
737 | flowi4_to_flowi(&fl2))) { | 737 | flowi4_to_flowi(&fl2), false)) { |
738 | if (rt1->rt_gateway == rt2->rt_gateway && | 738 | if (rt1->rt_gateway == rt2->rt_gateway && |
739 | rt1->dst.dev == rt2->dst.dev) | 739 | rt1->dst.dev == rt2->dst.dev) |
740 | ret = 1; | 740 | ret = 1; |
@@ -755,10 +755,10 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
755 | 755 | ||
756 | memset(&fl2, 0, sizeof(fl2)); | 756 | memset(&fl2, 0, sizeof(fl2)); |
757 | ipv6_addr_copy(&fl2.daddr, &dst->in6); | 757 | ipv6_addr_copy(&fl2.daddr, &dst->in6); |
758 | if (!afinfo->route((struct dst_entry **)&rt1, | 758 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, |
759 | flowi6_to_flowi(&fl1))) { | 759 | flowi6_to_flowi(&fl1), false)) { |
760 | if (!afinfo->route((struct dst_entry **)&rt2, | 760 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, |
761 | flowi6_to_flowi(&fl2))) { | 761 | flowi6_to_flowi(&fl2), false)) { |
762 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, | 762 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, |
763 | sizeof(rt1->rt6i_gateway)) && | 763 | sizeof(rt1->rt6i_gateway)) && |
764 | rt1->dst.dev == rt2->dst.dev) | 764 | rt1->dst.dev == rt2->dst.dev) |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 30bf8a167fc8..482e90c61850 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
1334 | struct nf_conn *ct; | 1334 | struct nf_conn *ct; |
1335 | int err = -EINVAL; | 1335 | int err = -EINVAL; |
1336 | struct nf_conntrack_helper *helper; | 1336 | struct nf_conntrack_helper *helper; |
1337 | struct nf_conn_tstamp *tstamp; | ||
1337 | 1338 | ||
1338 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); | 1339 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); |
1339 | if (IS_ERR(ct)) | 1340 | if (IS_ERR(ct)) |
@@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
1451 | __set_bit(IPS_EXPECTED_BIT, &ct->status); | 1452 | __set_bit(IPS_EXPECTED_BIT, &ct->status); |
1452 | ct->master = master_ct; | 1453 | ct->master = master_ct; |
1453 | } | 1454 | } |
1455 | tstamp = nf_conn_tstamp_find(ct); | ||
1456 | if (tstamp) | ||
1457 | tstamp->start = ktime_to_ns(ktime_get_real()); | ||
1454 | 1458 | ||
1455 | add_timer(&ct->timeout); | 1459 | add_timer(&ct->timeout); |
1456 | nf_conntrack_hash_insert(ct); | 1460 | nf_conntrack_hash_insert(ct); |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 9ae57c57c50e..2e664a69d7db 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -98,7 +98,7 @@ static const char * const dccp_state_names[] = { | |||
98 | #define sIV CT_DCCP_INVALID | 98 | #define sIV CT_DCCP_INVALID |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * DCCP state transistion table | 101 | * DCCP state transition table |
102 | * | 102 | * |
103 | * The assumption is the same as for TCP tracking: | 103 | * The assumption is the same as for TCP tracking: |
104 | * | 104 | * |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 6f4ee70f460b..6772b1154654 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -107,9 +107,9 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { | |||
107 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, | 107 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
108 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA}, | 108 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA}, |
109 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA}, | 109 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA}, |
110 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/ | 110 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't have Stale cookie*/ |
111 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */ | 111 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */ |
112 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */ | 112 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in orig dir */ |
113 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL} | 113 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL} |
114 | }, | 114 | }, |
115 | { | 115 | { |
@@ -121,7 +121,7 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { | |||
121 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA}, | 121 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA}, |
122 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA}, | 122 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA}, |
123 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA}, | 123 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA}, |
124 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */ | 124 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in reply dir */ |
125 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA}, | 125 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA}, |
126 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL} | 126 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL} |
127 | } | 127 | } |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index bcf47eb518ef..237cc1981b89 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -707,7 +707,7 @@ static const char *ct_sdp_header_search(const char *dptr, const char *limit, | |||
707 | } | 707 | } |
708 | 708 | ||
709 | /* Locate a SDP header (optionally a substring within the header value), | 709 | /* Locate a SDP header (optionally a substring within the header value), |
710 | * optionally stopping at the first occurence of the term header, parse | 710 | * optionally stopping at the first occurrence of the term header, parse |
711 | * it and return the offset and length of the data we're interested in. | 711 | * it and return the offset and length of the data we're interested in. |
712 | */ | 712 | */ |
713 | int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, | 713 | int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5ab22e2bbd7d..5b466cd1272f 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -134,7 +134,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
134 | const struct nf_afinfo *afinfo; | 134 | const struct nf_afinfo *afinfo; |
135 | const struct nf_queue_handler *qh; | 135 | const struct nf_queue_handler *qh; |
136 | 136 | ||
137 | /* QUEUE == DROP if noone is waiting, to be safe. */ | 137 | /* QUEUE == DROP if no one is waiting, to be safe. */ |
138 | rcu_read_lock(); | 138 | rcu_read_lock(); |
139 | 139 | ||
140 | qh = rcu_dereference(queue_handler[pf]); | 140 | qh = rcu_dereference(queue_handler[pf]); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index a9adf4c6b299..8a025a585d2f 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af) | |||
455 | vfree(xt[af].compat_tab); | 455 | vfree(xt[af].compat_tab); |
456 | xt[af].compat_tab = NULL; | 456 | xt[af].compat_tab = NULL; |
457 | xt[af].number = 0; | 457 | xt[af].number = 0; |
458 | xt[af].cur = 0; | ||
458 | } | 459 | } |
459 | } | 460 | } |
460 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); | 461 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); |
@@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset) | |||
473 | else | 474 | else |
474 | return mid ? tmp[mid - 1].delta : 0; | 475 | return mid ? tmp[mid - 1].delta : 0; |
475 | } | 476 | } |
476 | WARN_ON_ONCE(1); | 477 | return left ? tmp[left - 1].delta : 0; |
477 | return 0; | ||
478 | } | 478 | } |
479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); | 479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); |
480 | 480 | ||
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 0a229191e55b..ae8271652efa 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
99 | u_int8_t orig, nv; | 99 | u_int8_t orig, nv; |
100 | 100 | ||
101 | orig = ipv6_get_dsfield(iph); | 101 | orig = ipv6_get_dsfield(iph); |
102 | nv = (orig & info->tos_mask) ^ info->tos_value; | 102 | nv = (orig & ~info->tos_mask) ^ info->tos_value; |
103 | 103 | ||
104 | if (orig != nv) { | 104 | if (orig != nv) { |
105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) | 105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 6e6b46cb1db9..9e63b43faeed 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -166,7 +166,7 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb, | |||
166 | rcu_read_lock(); | 166 | rcu_read_lock(); |
167 | ai = nf_get_afinfo(family); | 167 | ai = nf_get_afinfo(family); |
168 | if (ai != NULL) | 168 | if (ai != NULL) |
169 | ai->route((struct dst_entry **)&rt, &fl); | 169 | ai->route(&init_net, (struct dst_entry **)&rt, &fl, false); |
170 | rcu_read_unlock(); | 170 | rcu_read_unlock(); |
171 | 171 | ||
172 | if (rt != NULL) { | 172 | if (rt != NULL) { |
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c index 2220b85e9519..b77d383cec78 100644 --- a/net/netfilter/xt_addrtype.c +++ b/net/netfilter/xt_addrtype.c | |||
@@ -32,11 +32,32 @@ MODULE_ALIAS("ipt_addrtype"); | |||
32 | MODULE_ALIAS("ip6t_addrtype"); | 32 | MODULE_ALIAS("ip6t_addrtype"); |
33 | 33 | ||
34 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 34 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
35 | static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt) | 35 | static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, |
36 | const struct in6_addr *addr) | ||
36 | { | 37 | { |
38 | const struct nf_afinfo *afinfo; | ||
39 | struct flowi6 flow; | ||
40 | struct rt6_info *rt; | ||
37 | u32 ret; | 41 | u32 ret; |
42 | int route_err; | ||
38 | 43 | ||
39 | if (!rt) | 44 | memset(&flow, 0, sizeof(flow)); |
45 | ipv6_addr_copy(&flow.daddr, addr); | ||
46 | if (dev) | ||
47 | flow.flowi6_oif = dev->ifindex; | ||
48 | |||
49 | rcu_read_lock(); | ||
50 | |||
51 | afinfo = nf_get_afinfo(NFPROTO_IPV6); | ||
52 | if (afinfo != NULL) | ||
53 | route_err = afinfo->route(net, (struct dst_entry **)&rt, | ||
54 | flowi6_to_flowi(&flow), !!dev); | ||
55 | else | ||
56 | route_err = 1; | ||
57 | |||
58 | rcu_read_unlock(); | ||
59 | |||
60 | if (route_err) | ||
40 | return XT_ADDRTYPE_UNREACHABLE; | 61 | return XT_ADDRTYPE_UNREACHABLE; |
41 | 62 | ||
42 | if (rt->rt6i_flags & RTF_REJECT) | 63 | if (rt->rt6i_flags & RTF_REJECT) |
@@ -48,6 +69,9 @@ static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt) | |||
48 | ret |= XT_ADDRTYPE_LOCAL; | 69 | ret |= XT_ADDRTYPE_LOCAL; |
49 | if (rt->rt6i_flags & RTF_ANYCAST) | 70 | if (rt->rt6i_flags & RTF_ANYCAST) |
50 | ret |= XT_ADDRTYPE_ANYCAST; | 71 | ret |= XT_ADDRTYPE_ANYCAST; |
72 | |||
73 | |||
74 | dst_release(&rt->dst); | ||
51 | return ret; | 75 | return ret; |
52 | } | 76 | } |
53 | 77 | ||
@@ -65,18 +89,8 @@ static bool match_type6(struct net *net, const struct net_device *dev, | |||
65 | return false; | 89 | return false; |
66 | 90 | ||
67 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | | 91 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | |
68 | XT_ADDRTYPE_UNREACHABLE) & mask) { | 92 | XT_ADDRTYPE_UNREACHABLE) & mask) |
69 | struct rt6_info *rt; | 93 | return !!(mask & match_lookup_rt6(net, dev, addr)); |
70 | u32 type; | ||
71 | int ifindex = dev ? dev->ifindex : 0; | ||
72 | |||
73 | rt = rt6_lookup(net, addr, NULL, ifindex, !!dev); | ||
74 | |||
75 | type = xt_addrtype_rt6_to_type(rt); | ||
76 | |||
77 | dst_release(&rt->dst); | ||
78 | return !!(mask & type); | ||
79 | } | ||
80 | return true; | 94 | return true; |
81 | } | 95 | } |
82 | 96 | ||
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 2c0086a4751e..61805d7b38aa 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -195,7 +195,7 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, | |||
195 | return info->match_flags & XT_CONNTRACK_STATE; | 195 | return info->match_flags & XT_CONNTRACK_STATE; |
196 | if ((info->match_flags & XT_CONNTRACK_DIRECTION) && | 196 | if ((info->match_flags & XT_CONNTRACK_DIRECTION) && |
197 | (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^ | 197 | (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^ |
198 | !!(info->invert_flags & XT_CONNTRACK_DIRECTION)) | 198 | !(info->invert_flags & XT_CONNTRACK_DIRECTION)) |
199 | return false; | 199 | return false; |
200 | 200 | ||
201 | if (info->match_flags & XT_CONNTRACK_ORIGSRC) | 201 | if (info->match_flags & XT_CONNTRACK_ORIGSRC) |
@@ -272,11 +272,6 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) | |||
272 | { | 272 | { |
273 | int ret; | 273 | int ret; |
274 | 274 | ||
275 | if (strcmp(par->table, "raw") == 0) { | ||
276 | pr_info("state is undetermined at the time of raw table\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | ret = nf_ct_l3proto_try_module_get(par->family); | 275 | ret = nf_ct_l3proto_try_module_get(par->family); |
281 | if (ret < 0) | 276 | if (ret < 0) |
282 | pr_info("cannot load conntrack support for proto=%u\n", | 277 | pr_info("cannot load conntrack support for proto=%u\n", |
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 061d48cec137..b3babaed7719 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c | |||
@@ -81,6 +81,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) | |||
81 | if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { | 81 | if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { |
82 | pr_warning("Protocol error: set match dimension " | 82 | pr_warning("Protocol error: set match dimension " |
83 | "is over the limit!\n"); | 83 | "is over the limit!\n"); |
84 | ip_set_nfnl_put(info->match_set.index); | ||
84 | return -ERANGE; | 85 | return -ERANGE; |
85 | } | 86 | } |
86 | 87 | ||
@@ -135,6 +136,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) | |||
135 | if (index == IPSET_INVALID_ID) { | 136 | if (index == IPSET_INVALID_ID) { |
136 | pr_warning("Cannot find del_set index %u as target\n", | 137 | pr_warning("Cannot find del_set index %u as target\n", |
137 | info->del_set.index); | 138 | info->del_set.index); |
139 | if (info->add_set.index != IPSET_INVALID_ID) | ||
140 | ip_set_nfnl_put(info->add_set.index); | ||
138 | return -ENOENT; | 141 | return -ENOENT; |
139 | } | 142 | } |
140 | } | 143 | } |
@@ -142,6 +145,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) | |||
142 | info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { | 145 | info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { |
143 | pr_warning("Protocol error: SET target dimension " | 146 | pr_warning("Protocol error: SET target dimension " |
144 | "is over the limit!\n"); | 147 | "is over the limit!\n"); |
148 | if (info->add_set.index != IPSET_INVALID_ID) | ||
149 | ip_set_nfnl_put(info->add_set.index); | ||
150 | if (info->del_set.index != IPSET_INVALID_ID) | ||
151 | ip_set_nfnl_put(info->del_set.index); | ||
145 | return -ERANGE; | 152 | return -ERANGE; |
146 | } | 153 | } |
147 | 154 | ||
@@ -192,6 +199,7 @@ set_match_checkentry(const struct xt_mtchk_param *par) | |||
192 | if (info->match_set.dim > IPSET_DIM_MAX) { | 199 | if (info->match_set.dim > IPSET_DIM_MAX) { |
193 | pr_warning("Protocol error: set match dimension " | 200 | pr_warning("Protocol error: set match dimension " |
194 | "is over the limit!\n"); | 201 | "is over the limit!\n"); |
202 | ip_set_nfnl_put(info->match_set.index); | ||
195 | return -ERANGE; | 203 | return -ERANGE; |
196 | } | 204 | } |
197 | 205 | ||
@@ -219,7 +227,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
219 | if (info->del_set.index != IPSET_INVALID_ID) | 227 | if (info->del_set.index != IPSET_INVALID_ID) |
220 | ip_set_del(info->del_set.index, | 228 | ip_set_del(info->del_set.index, |
221 | skb, par->family, | 229 | skb, par->family, |
222 | info->add_set.dim, | 230 | info->del_set.dim, |
223 | info->del_set.flags); | 231 | info->del_set.flags); |
224 | 232 | ||
225 | return XT_CONTINUE; | 233 | return XT_CONTINUE; |
@@ -245,13 +253,19 @@ set_target_checkentry(const struct xt_tgchk_param *par) | |||
245 | if (index == IPSET_INVALID_ID) { | 253 | if (index == IPSET_INVALID_ID) { |
246 | pr_warning("Cannot find del_set index %u as target\n", | 254 | pr_warning("Cannot find del_set index %u as target\n", |
247 | info->del_set.index); | 255 | info->del_set.index); |
256 | if (info->add_set.index != IPSET_INVALID_ID) | ||
257 | ip_set_nfnl_put(info->add_set.index); | ||
248 | return -ENOENT; | 258 | return -ENOENT; |
249 | } | 259 | } |
250 | } | 260 | } |
251 | if (info->add_set.dim > IPSET_DIM_MAX || | 261 | if (info->add_set.dim > IPSET_DIM_MAX || |
252 | info->del_set.flags > IPSET_DIM_MAX) { | 262 | info->del_set.dim > IPSET_DIM_MAX) { |
253 | pr_warning("Protocol error: SET target dimension " | 263 | pr_warning("Protocol error: SET target dimension " |
254 | "is over the limit!\n"); | 264 | "is over the limit!\n"); |
265 | if (info->add_set.index != IPSET_INVALID_ID) | ||
266 | ip_set_nfnl_put(info->add_set.index); | ||
267 | if (info->del_set.index != IPSET_INVALID_ID) | ||
268 | ip_set_nfnl_put(info->del_set.index); | ||
255 | return -ERANGE; | 269 | return -ERANGE; |
256 | } | 270 | } |
257 | 271 | ||
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index d37b7f80fa37..de0d8e4cbfb6 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -109,7 +109,7 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) | |||
109 | * | 109 | * |
110 | * Description: | 110 | * Description: |
111 | * This is the hashing function for the domain hash table, it returns the | 111 | * This is the hashing function for the domain hash table, it returns the |
112 | * correct bucket number for the domain. The caller is responsibile for | 112 | * correct bucket number for the domain. The caller is responsible for |
113 | * ensuring that the hash table is protected with either a RCU read lock or the | 113 | * ensuring that the hash table is protected with either a RCU read lock or the |
114 | * hash table lock. | 114 | * hash table lock. |
115 | * | 115 | * |
@@ -134,7 +134,7 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
134 | * | 134 | * |
135 | * Description: | 135 | * Description: |
136 | * Searches the domain hash table and returns a pointer to the hash table | 136 | * Searches the domain hash table and returns a pointer to the hash table |
137 | * entry if found, otherwise NULL is returned. The caller is responsibile for | 137 | * entry if found, otherwise NULL is returned. The caller is responsible for |
138 | * ensuring that the hash table is protected with either a RCU read lock or the | 138 | * ensuring that the hash table is protected with either a RCU read lock or the |
139 | * hash table lock. | 139 | * hash table lock. |
140 | * | 140 | * |
@@ -165,7 +165,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
165 | * Searches the domain hash table and returns a pointer to the hash table | 165 | * Searches the domain hash table and returns a pointer to the hash table |
166 | * entry if an exact match is found, if an exact match is not present in the | 166 | * entry if an exact match is found, if an exact match is not present in the |
167 | * hash table then the default entry is returned if valid otherwise NULL is | 167 | * hash table then the default entry is returned if valid otherwise NULL is |
168 | * returned. The caller is responsibile ensuring that the hash table is | 168 | * returned. The caller is responsible ensuring that the hash table is |
169 | * protected with either a RCU read lock or the hash table lock. | 169 | * protected with either a RCU read lock or the hash table lock. |
170 | * | 170 | * |
171 | */ | 171 | */ |
@@ -193,7 +193,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | |||
193 | * | 193 | * |
194 | * Description: | 194 | * Description: |
195 | * Generate an audit record for adding a new NetLabel/LSM mapping entry with | 195 | * Generate an audit record for adding a new NetLabel/LSM mapping entry with |
196 | * the given information. Caller is responsibile for holding the necessary | 196 | * the given information. Caller is responsible for holding the necessary |
197 | * locks. | 197 | * locks. |
198 | * | 198 | * |
199 | */ | 199 | */ |
@@ -605,7 +605,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) | |||
605 | * | 605 | * |
606 | * Description: | 606 | * Description: |
607 | * Look through the domain hash table searching for an entry to match @domain, | 607 | * Look through the domain hash table searching for an entry to match @domain, |
608 | * return a pointer to a copy of the entry or NULL. The caller is responsibile | 608 | * return a pointer to a copy of the entry or NULL. The caller is responsible |
609 | * for ensuring that rcu_read_[un]lock() is called. | 609 | * for ensuring that rcu_read_[un]lock() is called. |
610 | * | 610 | * |
611 | */ | 611 | */ |
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 998e85e895d0..4f251b19fbcc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c | |||
@@ -259,7 +259,7 @@ add_failure: | |||
259 | * | 259 | * |
260 | * Description: | 260 | * Description: |
261 | * This function is a helper function used by the LISTALL and LISTDEF command | 261 | * This function is a helper function used by the LISTALL and LISTDEF command |
262 | * handlers. The caller is responsibile for ensuring that the RCU read lock | 262 | * handlers. The caller is responsible for ensuring that the RCU read lock |
263 | * is held. Returns zero on success, negative values on failure. | 263 | * is held. Returns zero on success, negative values on failure. |
264 | * | 264 | * |
265 | */ | 265 | */ |
diff --git a/net/rds/cong.c b/net/rds/cong.c index 75ea686f27d5..6daaa49d133f 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c | |||
@@ -33,8 +33,7 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/rbtree.h> | 35 | #include <linux/rbtree.h> |
36 | 36 | #include <linux/bitops.h> | |
37 | #include <asm-generic/bitops/le.h> | ||
38 | 37 | ||
39 | #include "rds.h" | 38 | #include "rds.h" |
40 | 39 | ||
@@ -285,7 +284,7 @@ void rds_cong_set_bit(struct rds_cong_map *map, __be16 port) | |||
285 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; | 284 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; |
286 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; | 285 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; |
287 | 286 | ||
288 | generic___set_le_bit(off, (void *)map->m_page_addrs[i]); | 287 | __set_bit_le(off, (void *)map->m_page_addrs[i]); |
289 | } | 288 | } |
290 | 289 | ||
291 | void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) | 290 | void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) |
@@ -299,7 +298,7 @@ void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) | |||
299 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; | 298 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; |
300 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; | 299 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; |
301 | 300 | ||
302 | generic___clear_le_bit(off, (void *)map->m_page_addrs[i]); | 301 | __clear_bit_le(off, (void *)map->m_page_addrs[i]); |
303 | } | 302 | } |
304 | 303 | ||
305 | static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) | 304 | static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) |
@@ -310,7 +309,7 @@ static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) | |||
310 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; | 309 | i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; |
311 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; | 310 | off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; |
312 | 311 | ||
313 | return generic_test_le_bit(off, (void *)map->m_page_addrs[i]); | 312 | return test_bit_le(off, (void *)map->m_page_addrs[i]); |
314 | } | 313 | } |
315 | 314 | ||
316 | void rds_cong_add_socket(struct rds_sock *rs) | 315 | void rds_cong_add_socket(struct rds_sock *rs) |
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index c47a511f203d..7c4dce8fa5e6 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c | |||
@@ -355,7 +355,7 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
355 | * | 355 | * |
356 | * Conceptually, we have two counters: | 356 | * Conceptually, we have two counters: |
357 | * - send credits: this tells us how many WRs we're allowed | 357 | * - send credits: this tells us how many WRs we're allowed |
358 | * to submit without overruning the reciever's queue. For | 358 | * to submit without overruning the receiver's queue. For |
359 | * each SEND WR we post, we decrement this by one. | 359 | * each SEND WR we post, we decrement this by one. |
360 | * | 360 | * |
361 | * - posted credits: this tells us how many WRs we recently | 361 | * - posted credits: this tells us how many WRs we recently |
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 712cf2d1f28e..3a60a15d1b4a 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c | |||
@@ -181,7 +181,7 @@ static int rds_iw_init_qp_attrs(struct ib_qp_init_attr *attr, | |||
181 | unsigned int send_size, recv_size; | 181 | unsigned int send_size, recv_size; |
182 | int ret; | 182 | int ret; |
183 | 183 | ||
184 | /* The offset of 1 is to accomodate the additional ACK WR. */ | 184 | /* The offset of 1 is to accommodate the additional ACK WR. */ |
185 | send_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_send_wr + 1); | 185 | send_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_send_wr + 1); |
186 | recv_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_recv_wr + 1); | 186 | recv_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_recv_wr + 1); |
187 | rds_iw_ring_resize(send_ring, send_size - 1); | 187 | rds_iw_ring_resize(send_ring, send_size - 1); |
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index 59509e9a9e72..6deaa77495e3 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c | |||
@@ -122,7 +122,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd | |||
122 | #else | 122 | #else |
123 | /* FIXME - needs to compare the local and remote | 123 | /* FIXME - needs to compare the local and remote |
124 | * ipaddr/port tuple, but the ipaddr is the only | 124 | * ipaddr/port tuple, but the ipaddr is the only |
125 | * available infomation in the rds_sock (as the rest are | 125 | * available information in the rds_sock (as the rest are |
126 | * zero'ed. It doesn't appear to be properly populated | 126 | * zero'ed. It doesn't appear to be properly populated |
127 | * during connection setup... | 127 | * during connection setup... |
128 | */ | 128 | */ |
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 6280ea020d4e..545d8ee3efb1 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c | |||
@@ -307,7 +307,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
307 | * | 307 | * |
308 | * Conceptually, we have two counters: | 308 | * Conceptually, we have two counters: |
309 | * - send credits: this tells us how many WRs we're allowed | 309 | * - send credits: this tells us how many WRs we're allowed |
310 | * to submit without overruning the reciever's queue. For | 310 | * to submit without overruning the receiver's queue. For |
311 | * each SEND WR we post, we decrement this by one. | 311 | * each SEND WR we post, we decrement this by one. |
312 | * | 312 | * |
313 | * - posted credits: this tells us how many WRs we recently | 313 | * - posted credits: this tells us how many WRs we recently |
diff --git a/net/rds/send.c b/net/rds/send.c index 35b9c2e9caf1..d58ae5f9339e 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -116,7 +116,7 @@ static void release_in_xmit(struct rds_connection *conn) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * We're making the concious trade-off here to only send one message | 119 | * We're making the conscious trade-off here to only send one message |
120 | * down the connection at a time. | 120 | * down the connection at a time. |
121 | * Pro: | 121 | * Pro: |
122 | * - tx queueing is a simple fifo list | 122 | * - tx queueing is a simple fifo list |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5ee0c62046a0..a80aef6e3d1f 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
978 | struct sock *make; | 978 | struct sock *make; |
979 | struct rose_sock *make_rose; | 979 | struct rose_sock *make_rose; |
980 | struct rose_facilities_struct facilities; | 980 | struct rose_facilities_struct facilities; |
981 | int n, len; | 981 | int n; |
982 | 982 | ||
983 | skb->sk = NULL; /* Initially we don't know who it's for */ | 983 | skb->sk = NULL; /* Initially we don't know who it's for */ |
984 | 984 | ||
@@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
987 | */ | 987 | */ |
988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
989 | 989 | ||
990 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | 990 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
991 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | 991 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, |
992 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 992 | &facilities)) { |
993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); | 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); |
994 | return 0; | 994 | return 0; |
995 | } | 995 | } |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index ae4a9d99aec7..344456206b70 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
@@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) | |||
73 | unsigned int lci_i, lci_o; | 73 | unsigned int lci_i, lci_o; |
74 | 74 | ||
75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { | 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { |
76 | if (skb->len < ROSE_MIN_LEN) { | ||
77 | kfree_skb(skb); | ||
78 | continue; | ||
79 | } | ||
76 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 80 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
77 | frametype = skb->data[2]; | 81 | frametype = skb->data[2]; |
78 | dest = (rose_address *)(skb->data + 4); | 82 | if (frametype == ROSE_CALL_REQUEST && |
83 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || | ||
84 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
85 | ROSE_CALL_REQ_ADDR_LEN_VAL)) { | ||
86 | kfree_skb(skb); | ||
87 | continue; | ||
88 | } | ||
89 | dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
79 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; | 90 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; |
80 | 91 | ||
81 | skb_reset_transport_header(skb); | 92 | skb_reset_transport_header(skb); |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 88a77e90e7e8..479cae57d187 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -587,7 +587,7 @@ static int rose_clear_routes(void) | |||
587 | 587 | ||
588 | /* | 588 | /* |
589 | * Check that the device given is a valid AX.25 interface that is "up". | 589 | * Check that the device given is a valid AX.25 interface that is "up". |
590 | * called whith RTNL | 590 | * called with RTNL |
591 | */ | 591 | */ |
592 | static struct net_device *rose_ax25_dev_find(char *devname) | 592 | static struct net_device *rose_ax25_dev_find(char *devname) |
593 | { | 593 | { |
@@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
861 | unsigned int lci, new_lci; | 861 | unsigned int lci, new_lci; |
862 | unsigned char cause, diagnostic; | 862 | unsigned char cause, diagnostic; |
863 | struct net_device *dev; | 863 | struct net_device *dev; |
864 | int len, res = 0; | 864 | int res = 0; |
865 | char buf[11]; | 865 | char buf[11]; |
866 | 866 | ||
867 | #if 0 | 867 | #if 0 |
@@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
869 | return res; | 869 | return res; |
870 | #endif | 870 | #endif |
871 | 871 | ||
872 | if (skb->len < ROSE_MIN_LEN) | ||
873 | return res; | ||
872 | frametype = skb->data[2]; | 874 | frametype = skb->data[2]; |
873 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 875 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
874 | src_addr = (rose_address *)(skb->data + 9); | 876 | if (frametype == ROSE_CALL_REQUEST && |
875 | dest_addr = (rose_address *)(skb->data + 4); | 877 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || |
878 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
879 | ROSE_CALL_REQ_ADDR_LEN_VAL)) | ||
880 | return res; | ||
881 | src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF); | ||
882 | dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
876 | 883 | ||
877 | spin_lock_bh(&rose_neigh_list_lock); | 884 | spin_lock_bh(&rose_neigh_list_lock); |
878 | spin_lock_bh(&rose_route_list_lock); | 885 | spin_lock_bh(&rose_route_list_lock); |
@@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
1010 | goto out; | 1017 | goto out; |
1011 | } | 1018 | } |
1012 | 1019 | ||
1013 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | ||
1014 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | ||
1015 | |||
1016 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 1020 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
1017 | 1021 | ||
1018 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 1022 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
1023 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, | ||
1024 | &facilities)) { | ||
1019 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); | 1025 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); |
1020 | goto out; | 1026 | goto out; |
1021 | } | 1027 | } |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..f6c71caa94b9 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
142 | *dptr++ = ROSE_GFI | lci1; | 142 | *dptr++ = ROSE_GFI | lci1; |
143 | *dptr++ = lci2; | 143 | *dptr++ = lci2; |
144 | *dptr++ = frametype; | 144 | *dptr++ = frametype; |
145 | *dptr++ = 0xAA; | 145 | *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL; |
146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); | 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); |
147 | dptr += ROSE_ADDR_LEN; | 147 | dptr += ROSE_ADDR_LEN; |
148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
@@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
246 | do { | 246 | do { |
247 | switch (*p & 0xC0) { | 247 | switch (*p & 0xC0) { |
248 | case 0x00: | 248 | case 0x00: |
249 | if (len < 2) | ||
250 | return -1; | ||
249 | p += 2; | 251 | p += 2; |
250 | n += 2; | 252 | n += 2; |
251 | len -= 2; | 253 | len -= 2; |
252 | break; | 254 | break; |
253 | 255 | ||
254 | case 0x40: | 256 | case 0x40: |
257 | if (len < 3) | ||
258 | return -1; | ||
255 | if (*p == FAC_NATIONAL_RAND) | 259 | if (*p == FAC_NATIONAL_RAND) |
256 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); | 260 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); |
257 | p += 3; | 261 | p += 3; |
@@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
260 | break; | 264 | break; |
261 | 265 | ||
262 | case 0x80: | 266 | case 0x80: |
267 | if (len < 4) | ||
268 | return -1; | ||
263 | p += 4; | 269 | p += 4; |
264 | n += 4; | 270 | n += 4; |
265 | len -= 4; | 271 | len -= 4; |
266 | break; | 272 | break; |
267 | 273 | ||
268 | case 0xC0: | 274 | case 0xC0: |
275 | if (len < 2) | ||
276 | return -1; | ||
269 | l = p[1]; | 277 | l = p[1]; |
278 | if (len < 2 + l) | ||
279 | return -1; | ||
270 | if (*p == FAC_NATIONAL_DEST_DIGI) { | 280 | if (*p == FAC_NATIONAL_DEST_DIGI) { |
271 | if (!fac_national_digis_received) { | 281 | if (!fac_national_digis_received) { |
282 | if (l < AX25_ADDR_LEN) | ||
283 | return -1; | ||
272 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); | 284 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); |
273 | facilities->source_ndigis = 1; | 285 | facilities->source_ndigis = 1; |
274 | } | 286 | } |
275 | } | 287 | } |
276 | else if (*p == FAC_NATIONAL_SRC_DIGI) { | 288 | else if (*p == FAC_NATIONAL_SRC_DIGI) { |
277 | if (!fac_national_digis_received) { | 289 | if (!fac_national_digis_received) { |
290 | if (l < AX25_ADDR_LEN) | ||
291 | return -1; | ||
278 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); | 292 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); |
279 | facilities->dest_ndigis = 1; | 293 | facilities->dest_ndigis = 1; |
280 | } | 294 | } |
281 | } | 295 | } |
282 | else if (*p == FAC_NATIONAL_FAIL_CALL) { | 296 | else if (*p == FAC_NATIONAL_FAIL_CALL) { |
297 | if (l < AX25_ADDR_LEN) | ||
298 | return -1; | ||
283 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); | 299 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); |
284 | } | 300 | } |
285 | else if (*p == FAC_NATIONAL_FAIL_ADD) { | 301 | else if (*p == FAC_NATIONAL_FAIL_ADD) { |
302 | if (l < 1 + ROSE_ADDR_LEN) | ||
303 | return -1; | ||
286 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); | 304 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); |
287 | } | 305 | } |
288 | else if (*p == FAC_NATIONAL_DIGIS) { | 306 | else if (*p == FAC_NATIONAL_DIGIS) { |
307 | if (l % AX25_ADDR_LEN) | ||
308 | return -1; | ||
289 | fac_national_digis_received = 1; | 309 | fac_national_digis_received = 1; |
290 | facilities->source_ndigis = 0; | 310 | facilities->source_ndigis = 0; |
291 | facilities->dest_ndigis = 0; | 311 | facilities->dest_ndigis = 0; |
292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 312 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
293 | if (pt[6] & AX25_HBIT) | 313 | if (pt[6] & AX25_HBIT) { |
314 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
315 | return -1; | ||
294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 316 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
295 | else | 317 | } else { |
318 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
319 | return -1; | ||
296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 320 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
321 | } | ||
297 | } | 322 | } |
298 | } | 323 | } |
299 | p += l + 2; | 324 | p += l + 2; |
@@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
314 | do { | 339 | do { |
315 | switch (*p & 0xC0) { | 340 | switch (*p & 0xC0) { |
316 | case 0x00: | 341 | case 0x00: |
342 | if (len < 2) | ||
343 | return -1; | ||
317 | p += 2; | 344 | p += 2; |
318 | n += 2; | 345 | n += 2; |
319 | len -= 2; | 346 | len -= 2; |
320 | break; | 347 | break; |
321 | 348 | ||
322 | case 0x40: | 349 | case 0x40: |
350 | if (len < 3) | ||
351 | return -1; | ||
323 | p += 3; | 352 | p += 3; |
324 | n += 3; | 353 | n += 3; |
325 | len -= 3; | 354 | len -= 3; |
326 | break; | 355 | break; |
327 | 356 | ||
328 | case 0x80: | 357 | case 0x80: |
358 | if (len < 4) | ||
359 | return -1; | ||
329 | p += 4; | 360 | p += 4; |
330 | n += 4; | 361 | n += 4; |
331 | len -= 4; | 362 | len -= 4; |
332 | break; | 363 | break; |
333 | 364 | ||
334 | case 0xC0: | 365 | case 0xC0: |
366 | if (len < 2) | ||
367 | return -1; | ||
335 | l = p[1]; | 368 | l = p[1]; |
369 | |||
370 | /* Prevent overflows*/ | ||
371 | if (l < 10 || l > 20) | ||
372 | return -1; | ||
373 | |||
336 | if (*p == FAC_CCITT_DEST_NSAP) { | 374 | if (*p == FAC_CCITT_DEST_NSAP) { |
337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 375 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
338 | memcpy(callsign, p + 12, l - 10); | 376 | memcpy(callsign, p + 12, l - 10); |
@@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
355 | return n; | 393 | return n; |
356 | } | 394 | } |
357 | 395 | ||
358 | int rose_parse_facilities(unsigned char *p, | 396 | int rose_parse_facilities(unsigned char *p, unsigned packet_len, |
359 | struct rose_facilities_struct *facilities) | 397 | struct rose_facilities_struct *facilities) |
360 | { | 398 | { |
361 | int facilities_len, len; | 399 | int facilities_len, len; |
362 | 400 | ||
363 | facilities_len = *p++; | 401 | facilities_len = *p++; |
364 | 402 | ||
365 | if (facilities_len == 0) | 403 | if (facilities_len == 0 || (unsigned)facilities_len > packet_len) |
366 | return 0; | 404 | return 0; |
367 | 405 | ||
368 | while (facilities_len > 0) { | 406 | while (facilities_len >= 3 && *p == 0x00) { |
369 | if (*p == 0x00) { | 407 | facilities_len--; |
370 | facilities_len--; | 408 | p++; |
371 | p++; | 409 | |
372 | 410 | switch (*p) { | |
373 | switch (*p) { | 411 | case FAC_NATIONAL: /* National */ |
374 | case FAC_NATIONAL: /* National */ | 412 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 413 | break; |
376 | facilities_len -= len + 1; | 414 | |
377 | p += len + 1; | 415 | case FAC_CCITT: /* CCITT */ |
378 | break; | 416 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
379 | 417 | break; | |
380 | case FAC_CCITT: /* CCITT */ | 418 | |
381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 419 | default: |
382 | facilities_len -= len + 1; | 420 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); |
383 | p += len + 1; | 421 | len = 1; |
384 | break; | 422 | break; |
385 | 423 | } | |
386 | default: | 424 | |
387 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); | 425 | if (len < 0) |
388 | facilities_len--; | 426 | return 0; |
389 | p++; | 427 | if (WARN_ON(len >= facilities_len)) |
390 | break; | 428 | return 0; |
391 | } | 429 | facilities_len -= len + 1; |
392 | } else | 430 | p += len + 1; |
393 | break; /* Error in facilities format */ | ||
394 | } | 431 | } |
395 | 432 | ||
396 | return 1; | 433 | return facilities_len == 0; |
397 | } | 434 | } |
398 | 435 | ||
399 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) | 436 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 15873e14cb54..14b42f4ad791 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -999,7 +999,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
999 | switch (n->nlmsg_type) { | 999 | switch (n->nlmsg_type) { |
1000 | case RTM_NEWACTION: | 1000 | case RTM_NEWACTION: |
1001 | /* we are going to assume all other flags | 1001 | /* we are going to assume all other flags |
1002 | * imply create only if it doesnt exist | 1002 | * imply create only if it doesn't exist |
1003 | * Note that CREATE | EXCL implies that | 1003 | * Note that CREATE | EXCL implies that |
1004 | * but since we want avoid ambiguity (eg when flags | 1004 | * but since we want avoid ambiguity (eg when flags |
1005 | * is zero) then just set this | 1005 | * is zero) then just set this |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 50c7c06c019d..7affe9a92757 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -161,7 +161,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
161 | } | 161 | } |
162 | if (offset > 0 && offset > skb->len) { | 162 | if (offset > 0 && offset > skb->len) { |
163 | pr_info("tc filter pedit" | 163 | pr_info("tc filter pedit" |
164 | " offset %d cant exceed pkt length %d\n", | 164 | " offset %d can't exceed pkt length %d\n", |
165 | offset, skb->len); | 165 | offset, skb->len); |
166 | goto bad; | 166 | goto bad; |
167 | } | 167 | } |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index a4de67eca824..49130e8abff0 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * on the meta type. Obviously, the length of the data must also | 47 | * on the meta type. Obviously, the length of the data must also |
48 | * be provided for non-numeric types. | 48 | * be provided for non-numeric types. |
49 | * | 49 | * |
50 | * Additionaly, type dependant modifiers such as shift operators | 50 | * Additionally, type dependent modifiers such as shift operators |
51 | * or mask may be applied to extend the functionaliy. As of now, | 51 | * or mask may be applied to extend the functionaliy. As of now, |
52 | * the variable length type supports shifting the byte string to | 52 | * the variable length type supports shifting the byte string to |
53 | * the right, eating up any number of octets and thus supporting | 53 | * the right, eating up any number of octets and thus supporting |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index e1429a85091f..29b942ce9e82 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -183,7 +183,7 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) | |||
183 | * filters in qdisc and in inner nodes (if higher filter points to the inner | 183 | * filters in qdisc and in inner nodes (if higher filter points to the inner |
184 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special | 184 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special |
185 | * internal fifo (direct). These packets then go directly thru. If we still | 185 | * internal fifo (direct). These packets then go directly thru. If we still |
186 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull | 186 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful |
187 | * then finish and return direct queue. | 187 | * then finish and return direct queue. |
188 | */ | 188 | */ |
189 | #define HTB_DIRECT ((struct htb_class *)-1L) | 189 | #define HTB_DIRECT ((struct htb_class *)-1L) |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index edbbf7ad6623..69c35f6cd13f 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -160,7 +160,7 @@ static bool loss_4state(struct netem_sched_data *q) | |||
160 | u32 rnd = net_random(); | 160 | u32 rnd = net_random(); |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * Makes a comparision between rnd and the transition | 163 | * Makes a comparison between rnd and the transition |
164 | * probabilities outgoing from the current state, then decides the | 164 | * probabilities outgoing from the current state, then decides the |
165 | * next state and if the next packet has to be transmitted or lost. | 165 | * next state and if the next packet has to be transmitted or lost. |
166 | * The four states correspond to: | 166 | * The four states correspond to: |
@@ -212,9 +212,9 @@ static bool loss_4state(struct netem_sched_data *q) | |||
212 | * Generates losses according to the Gilbert-Elliot loss model or | 212 | * Generates losses according to the Gilbert-Elliot loss model or |
213 | * its special cases (Gilbert or Simple Gilbert) | 213 | * its special cases (Gilbert or Simple Gilbert) |
214 | * | 214 | * |
215 | * Makes a comparision between random number and the transition | 215 | * Makes a comparison between random number and the transition |
216 | * probabilities outgoing from the current state, then decides the | 216 | * probabilities outgoing from the current state, then decides the |
217 | * next state. A second random number is extracted and the comparision | 217 | * next state. A second random number is extracted and the comparison |
218 | * with the loss probability of the current state decides if the next | 218 | * with the loss probability of the current state decides if the next |
219 | * packet will be transmitted or lost. | 219 | * packet will be transmitted or lost. |
220 | */ | 220 | */ |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 6b04287913cd..1a21c571aa03 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -569,6 +569,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, | |||
569 | sctp_assoc_set_primary(asoc, transport); | 569 | sctp_assoc_set_primary(asoc, transport); |
570 | if (asoc->peer.active_path == peer) | 570 | if (asoc->peer.active_path == peer) |
571 | asoc->peer.active_path = transport; | 571 | asoc->peer.active_path = transport; |
572 | if (asoc->peer.retran_path == peer) | ||
573 | asoc->peer.retran_path = transport; | ||
572 | if (asoc->peer.last_data_from == peer) | 574 | if (asoc->peer.last_data_from == peer) |
573 | asoc->peer.last_data_from = transport; | 575 | asoc->peer.last_data_from = transport; |
574 | 576 | ||
@@ -1323,6 +1325,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1323 | 1325 | ||
1324 | if (t) | 1326 | if (t) |
1325 | asoc->peer.retran_path = t; | 1327 | asoc->peer.retran_path = t; |
1328 | else | ||
1329 | t = asoc->peer.retran_path; | ||
1326 | 1330 | ||
1327 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | 1331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" |
1328 | " %p addr: ", | 1332 | " %p addr: ", |
@@ -1593,7 +1597,7 @@ void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc) | |||
1593 | struct sctp_chunk *ack; | 1597 | struct sctp_chunk *ack; |
1594 | struct sctp_chunk *tmp; | 1598 | struct sctp_chunk *tmp; |
1595 | 1599 | ||
1596 | /* We can remove all the entries from the queue upto | 1600 | /* We can remove all the entries from the queue up to |
1597 | * the "Peer-Sequence-Number". | 1601 | * the "Peer-Sequence-Number". |
1598 | */ | 1602 | */ |
1599 | list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list, | 1603 | list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list, |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index ddbbf7c81fa1..865e68fef21c 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -113,7 +113,7 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) | |||
113 | return new; | 113 | return new; |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Free the shared key stucture */ | 116 | /* Free the shared key structure */ |
117 | static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) | 117 | static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) |
118 | { | 118 | { |
119 | BUG_ON(!list_empty(&sh_key->key_list)); | 119 | BUG_ON(!list_empty(&sh_key->key_list)); |
@@ -122,7 +122,7 @@ static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) | |||
122 | kfree(sh_key); | 122 | kfree(sh_key); |
123 | } | 123 | } |
124 | 124 | ||
125 | /* Destory the entire key list. This is done during the | 125 | /* Destroy the entire key list. This is done during the |
126 | * associon and endpoint free process. | 126 | * associon and endpoint free process. |
127 | */ | 127 | */ |
128 | void sctp_auth_destroy_keys(struct list_head *keys) | 128 | void sctp_auth_destroy_keys(struct list_head *keys) |
@@ -324,7 +324,7 @@ static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( | |||
324 | if (!peer_key_vector || !local_key_vector) | 324 | if (!peer_key_vector || !local_key_vector) |
325 | goto out; | 325 | goto out; |
326 | 326 | ||
327 | /* Figure out the order in wich the key_vectors will be | 327 | /* Figure out the order in which the key_vectors will be |
328 | * added to the endpoint shared key. | 328 | * added to the endpoint shared key. |
329 | * SCTP-AUTH, Section 6.1: | 329 | * SCTP-AUTH, Section 6.1: |
330 | * This is performed by selecting the numerically smaller key | 330 | * This is performed by selecting the numerically smaller key |
diff --git a/net/sctp/input.c b/net/sctp/input.c index 826661be73e7..5436c6921167 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -1034,7 +1034,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( | |||
1034 | * association. | 1034 | * association. |
1035 | * | 1035 | * |
1036 | * This means that any chunks that can help us identify the association need | 1036 | * This means that any chunks that can help us identify the association need |
1037 | * to be looked at to find this assocation. | 1037 | * to be looked at to find this association. |
1038 | */ | 1038 | */ |
1039 | static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, | 1039 | static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, |
1040 | const union sctp_addr *laddr, | 1040 | const union sctp_addr *laddr, |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 60600d337a3a..b4f3cf06d8da 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -510,7 +510,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
510 | sh->checksum = sctp_end_cksum(crc32); | 510 | sh->checksum = sctp_end_cksum(crc32); |
511 | } else { | 511 | } else { |
512 | if (dst->dev->features & NETIF_F_SCTP_CSUM) { | 512 | if (dst->dev->features & NETIF_F_SCTP_CSUM) { |
513 | /* no need to seed psuedo checksum for SCTP */ | 513 | /* no need to seed pseudo checksum for SCTP */ |
514 | nskb->ip_summed = CHECKSUM_PARTIAL; | 514 | nskb->ip_summed = CHECKSUM_PARTIAL; |
515 | nskb->csum_start = (skb_transport_header(nskb) - | 515 | nskb->csum_start = (skb_transport_header(nskb) - |
516 | nskb->head); | 516 | nskb->head); |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 26dc005113a0..bf92a5b68f8b 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -177,13 +177,13 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn) | |||
177 | * 3) If the missing report count for TSN t is to be | 177 | * 3) If the missing report count for TSN t is to be |
178 | * incremented according to [RFC2960] and | 178 | * incremented according to [RFC2960] and |
179 | * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, | 179 | * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, |
180 | * then the sender MUST futher execute steps 3.1 and | 180 | * then the sender MUST further execute steps 3.1 and |
181 | * 3.2 to determine if the missing report count for | 181 | * 3.2 to determine if the missing report count for |
182 | * TSN t SHOULD NOT be incremented. | 182 | * TSN t SHOULD NOT be incremented. |
183 | * | 183 | * |
184 | * 3.3) If 3.1 and 3.2 do not dictate that the missing | 184 | * 3.3) If 3.1 and 3.2 do not dictate that the missing |
185 | * report count for t should not be incremented, then | 185 | * report count for t should not be incremented, then |
186 | * the sender SOULD increment missing report count for | 186 | * the sender SHOULD increment missing report count for |
187 | * t (according to [RFC2960] and [SCTP_STEWART_2002]). | 187 | * t (according to [RFC2960] and [SCTP_STEWART_2002]). |
188 | */ | 188 | */ |
189 | static inline int sctp_cacc_skip(struct sctp_transport *primary, | 189 | static inline int sctp_cacc_skip(struct sctp_transport *primary, |
@@ -843,7 +843,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
843 | case SCTP_CID_ECN_CWR: | 843 | case SCTP_CID_ECN_CWR: |
844 | case SCTP_CID_ASCONF_ACK: | 844 | case SCTP_CID_ASCONF_ACK: |
845 | one_packet = 1; | 845 | one_packet = 1; |
846 | /* Fall throught */ | 846 | /* Fall through */ |
847 | 847 | ||
848 | case SCTP_CID_SACK: | 848 | case SCTP_CID_SACK: |
849 | case SCTP_CID_HEARTBEAT: | 849 | case SCTP_CID_HEARTBEAT: |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 152976ec0b74..d5bf91d04f63 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -1205,7 +1205,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1205 | if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) | 1205 | if ((sctp_assoc_hashsize > (64 * 1024)) && order > 0) |
1206 | continue; | 1206 | continue; |
1207 | sctp_assoc_hashtable = (struct sctp_hashbucket *) | 1207 | sctp_assoc_hashtable = (struct sctp_hashbucket *) |
1208 | __get_free_pages(GFP_ATOMIC, order); | 1208 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); |
1209 | } while (!sctp_assoc_hashtable && --order > 0); | 1209 | } while (!sctp_assoc_hashtable && --order > 0); |
1210 | if (!sctp_assoc_hashtable) { | 1210 | if (!sctp_assoc_hashtable) { |
1211 | pr_err("Failed association hash alloc\n"); | 1211 | pr_err("Failed association hash alloc\n"); |
@@ -1238,7 +1238,7 @@ SCTP_STATIC __init int sctp_init(void) | |||
1238 | if ((sctp_port_hashsize > (64 * 1024)) && order > 0) | 1238 | if ((sctp_port_hashsize > (64 * 1024)) && order > 0) |
1239 | continue; | 1239 | continue; |
1240 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) | 1240 | sctp_port_hashtable = (struct sctp_bind_hashbucket *) |
1241 | __get_free_pages(GFP_ATOMIC, order); | 1241 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, order); |
1242 | } while (!sctp_port_hashtable && --order > 0); | 1242 | } while (!sctp_port_hashtable && --order > 0); |
1243 | if (!sctp_port_hashtable) { | 1243 | if (!sctp_port_hashtable) { |
1244 | pr_err("Failed bind hash alloc\n"); | 1244 | pr_err("Failed bind hash alloc\n"); |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index de98665db524..b3434cc7d0cf 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -3106,10 +3106,10 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, | |||
3106 | 3106 | ||
3107 | /* create an ASCONF_ACK chunk. | 3107 | /* create an ASCONF_ACK chunk. |
3108 | * Based on the definitions of parameters, we know that the size of | 3108 | * Based on the definitions of parameters, we know that the size of |
3109 | * ASCONF_ACK parameters are less than or equal to the twice of ASCONF | 3109 | * ASCONF_ACK parameters are less than or equal to the fourfold of ASCONF |
3110 | * parameters. | 3110 | * parameters. |
3111 | */ | 3111 | */ |
3112 | asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 2); | 3112 | asconf_ack = sctp_make_asconf_ack(asoc, serial, chunk_len * 4); |
3113 | if (!asconf_ack) | 3113 | if (!asconf_ack) |
3114 | goto done; | 3114 | goto done; |
3115 | 3115 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index b21b218d564f..5f86ee4b54c1 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -482,7 +482,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
482 | * If the timer was a heartbeat, we only increment error counts | 482 | * If the timer was a heartbeat, we only increment error counts |
483 | * when we already have an outstanding HEARTBEAT that has not | 483 | * when we already have an outstanding HEARTBEAT that has not |
484 | * been acknowledged. | 484 | * been acknowledged. |
485 | * Additionaly, some tranport states inhibit error increments. | 485 | * Additionally, some tranport states inhibit error increments. |
486 | */ | 486 | */ |
487 | if (!is_hb) { | 487 | if (!is_hb) { |
488 | asoc->overall_error_count++; | 488 | asoc->overall_error_count++; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 4b4eb7c96bbd..76792083c379 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -551,7 +551,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
551 | * | 551 | * |
552 | * This means that if we only want to abort associations | 552 | * This means that if we only want to abort associations |
553 | * in an authenticated way (i.e AUTH+ABORT), then we | 553 | * in an authenticated way (i.e AUTH+ABORT), then we |
554 | * can't destroy this association just becuase the packet | 554 | * can't destroy this association just because the packet |
555 | * was malformed. | 555 | * was malformed. |
556 | */ | 556 | */ |
557 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 557 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
@@ -1546,7 +1546,7 @@ cleanup: | |||
1546 | } | 1546 | } |
1547 | 1547 | ||
1548 | /* | 1548 | /* |
1549 | * Handle simultanous INIT. | 1549 | * Handle simultaneous INIT. |
1550 | * This means we started an INIT and then we got an INIT request from | 1550 | * This means we started an INIT and then we got an INIT request from |
1551 | * our peer. | 1551 | * our peer. |
1552 | * | 1552 | * |
@@ -2079,7 +2079,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2079 | * RFC 2960, Section 3.3.7 | 2079 | * RFC 2960, Section 3.3.7 |
2080 | * If an endpoint receives an ABORT with a format error or for an | 2080 | * If an endpoint receives an ABORT with a format error or for an |
2081 | * association that doesn't exist, it MUST silently discard it. | 2081 | * association that doesn't exist, it MUST silently discard it. |
2082 | * Becasue the length is "invalid", we can't really discard just | 2082 | * Because the length is "invalid", we can't really discard just |
2083 | * as we do not know its true length. So, to be safe, discard the | 2083 | * as we do not know its true length. So, to be safe, discard the |
2084 | * packet. | 2084 | * packet. |
2085 | */ | 2085 | */ |
@@ -2120,7 +2120,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2120 | * RFC 2960, Section 3.3.7 | 2120 | * RFC 2960, Section 3.3.7 |
2121 | * If an endpoint receives an ABORT with a format error or for an | 2121 | * If an endpoint receives an ABORT with a format error or for an |
2122 | * association that doesn't exist, it MUST silently discard it. | 2122 | * association that doesn't exist, it MUST silently discard it. |
2123 | * Becasue the length is "invalid", we can't really discard just | 2123 | * Because the length is "invalid", we can't really discard just |
2124 | * as we do not know its true length. So, to be safe, discard the | 2124 | * as we do not know its true length. So, to be safe, discard the |
2125 | * packet. | 2125 | * packet. |
2126 | */ | 2126 | */ |
@@ -2381,7 +2381,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2381 | * RFC 2960, Section 3.3.7 | 2381 | * RFC 2960, Section 3.3.7 |
2382 | * If an endpoint receives an ABORT with a format error or for an | 2382 | * If an endpoint receives an ABORT with a format error or for an |
2383 | * association that doesn't exist, it MUST silently discard it. | 2383 | * association that doesn't exist, it MUST silently discard it. |
2384 | * Becasue the length is "invalid", we can't really discard just | 2384 | * Because the length is "invalid", we can't really discard just |
2385 | * as we do not know its true length. So, to be safe, discard the | 2385 | * as we do not know its true length. So, to be safe, discard the |
2386 | * packet. | 2386 | * packet. |
2387 | */ | 2387 | */ |
@@ -2448,7 +2448,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2448 | * RFC 2960, Section 3.3.7 | 2448 | * RFC 2960, Section 3.3.7 |
2449 | * If an endpoint receives an ABORT with a format error or for an | 2449 | * If an endpoint receives an ABORT with a format error or for an |
2450 | * association that doesn't exist, it MUST silently discard it. | 2450 | * association that doesn't exist, it MUST silently discard it. |
2451 | * Becasue the length is "invalid", we can't really discard just | 2451 | * Because the length is "invalid", we can't really discard just |
2452 | * as we do not know its true length. So, to be safe, discard the | 2452 | * as we do not know its true length. So, to be safe, discard the |
2453 | * packet. | 2453 | * packet. |
2454 | */ | 2454 | */ |
@@ -3855,7 +3855,7 @@ gen_shutdown: | |||
3855 | } | 3855 | } |
3856 | 3856 | ||
3857 | /* | 3857 | /* |
3858 | * SCTP-AUTH Section 6.3 Receving authenticated chukns | 3858 | * SCTP-AUTH Section 6.3 Receiving authenticated chukns |
3859 | * | 3859 | * |
3860 | * The receiver MUST use the HMAC algorithm indicated in the HMAC | 3860 | * The receiver MUST use the HMAC algorithm indicated in the HMAC |
3861 | * Identifier field. If this algorithm was not specified by the | 3861 | * Identifier field. If this algorithm was not specified by the |
@@ -4231,7 +4231,7 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4231 | * | 4231 | * |
4232 | * This means that if we only want to abort associations | 4232 | * This means that if we only want to abort associations |
4233 | * in an authenticated way (i.e AUTH+ABORT), then we | 4233 | * in an authenticated way (i.e AUTH+ABORT), then we |
4234 | * can't destroy this association just becuase the packet | 4234 | * can't destroy this association just because the packet |
4235 | * was malformed. | 4235 | * was malformed. |
4236 | */ | 4236 | */ |
4237 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 4237 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
@@ -4402,9 +4402,9 @@ static sctp_disposition_t sctp_sf_violation_ctsn( | |||
4402 | } | 4402 | } |
4403 | 4403 | ||
4404 | /* Handle protocol violation of an invalid chunk bundling. For example, | 4404 | /* Handle protocol violation of an invalid chunk bundling. For example, |
4405 | * when we have an association and we recieve bundled INIT-ACK, or | 4405 | * when we have an association and we receive bundled INIT-ACK, or |
4406 | * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" | 4406 | * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" |
4407 | * statement from the specs. Additinally, there might be an attacker | 4407 | * statement from the specs. Additionally, there might be an attacker |
4408 | * on the path and we may not want to continue this communication. | 4408 | * on the path and we may not want to continue this communication. |
4409 | */ | 4409 | */ |
4410 | static sctp_disposition_t sctp_sf_violation_chunk( | 4410 | static sctp_disposition_t sctp_sf_violation_chunk( |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3951a10605bc..deb82e35a107 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1193,7 +1193,7 @@ out_free: | |||
1193 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | 1193 | * an endpoint that is multi-homed. Much like sctp_bindx() this call |
1194 | * allows a caller to specify multiple addresses at which a peer can be | 1194 | * allows a caller to specify multiple addresses at which a peer can be |
1195 | * reached. The way the SCTP stack uses the list of addresses to set up | 1195 | * reached. The way the SCTP stack uses the list of addresses to set up |
1196 | * the association is implementation dependant. This function only | 1196 | * the association is implementation dependent. This function only |
1197 | * specifies that the stack will try to make use of all the addresses in | 1197 | * specifies that the stack will try to make use of all the addresses in |
1198 | * the list when needed. | 1198 | * the list when needed. |
1199 | * | 1199 | * |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index aa72e89c3ee1..61b1f5ada96a 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -554,7 +554,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( | |||
554 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); | 554 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); |
555 | 555 | ||
556 | /* Per TSVWG discussion with Randy. Allow the application to | 556 | /* Per TSVWG discussion with Randy. Allow the application to |
557 | * ressemble a fragmented message. | 557 | * reassemble a fragmented message. |
558 | */ | 558 | */ |
559 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; | 559 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; |
560 | 560 | ||
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 17678189d054..f2d1de7f2ffb 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -240,7 +240,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
240 | } else { | 240 | } else { |
241 | /* | 241 | /* |
242 | * If fragment interleave is enabled, we | 242 | * If fragment interleave is enabled, we |
243 | * can queue this to the recieve queue instead | 243 | * can queue this to the receive queue instead |
244 | * of the lobby. | 244 | * of the lobby. |
245 | */ | 245 | */ |
246 | if (sctp_sk(sk)->frag_interleave) | 246 | if (sctp_sk(sk)->frag_interleave) |
diff --git a/net/socket.c b/net/socket.c index 937d0fcf74bc..310d16b1b3c9 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2588,23 +2588,123 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | |||
2588 | 2588 | ||
2589 | static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | 2589 | static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) |
2590 | { | 2590 | { |
2591 | struct compat_ethtool_rxnfc __user *compat_rxnfc; | ||
2592 | bool convert_in = false, convert_out = false; | ||
2593 | size_t buf_size = ALIGN(sizeof(struct ifreq), 8); | ||
2594 | struct ethtool_rxnfc __user *rxnfc; | ||
2591 | struct ifreq __user *ifr; | 2595 | struct ifreq __user *ifr; |
2596 | u32 rule_cnt = 0, actual_rule_cnt; | ||
2597 | u32 ethcmd; | ||
2592 | u32 data; | 2598 | u32 data; |
2593 | void __user *datap; | 2599 | int ret; |
2600 | |||
2601 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | ||
2602 | return -EFAULT; | ||
2594 | 2603 | ||
2595 | ifr = compat_alloc_user_space(sizeof(*ifr)); | 2604 | compat_rxnfc = compat_ptr(data); |
2596 | 2605 | ||
2597 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | 2606 | if (get_user(ethcmd, &compat_rxnfc->cmd)) |
2598 | return -EFAULT; | 2607 | return -EFAULT; |
2599 | 2608 | ||
2600 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | 2609 | /* Most ethtool structures are defined without padding. |
2610 | * Unfortunately struct ethtool_rxnfc is an exception. | ||
2611 | */ | ||
2612 | switch (ethcmd) { | ||
2613 | default: | ||
2614 | break; | ||
2615 | case ETHTOOL_GRXCLSRLALL: | ||
2616 | /* Buffer size is variable */ | ||
2617 | if (get_user(rule_cnt, &compat_rxnfc->rule_cnt)) | ||
2618 | return -EFAULT; | ||
2619 | if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32)) | ||
2620 | return -ENOMEM; | ||
2621 | buf_size += rule_cnt * sizeof(u32); | ||
2622 | /* fall through */ | ||
2623 | case ETHTOOL_GRXRINGS: | ||
2624 | case ETHTOOL_GRXCLSRLCNT: | ||
2625 | case ETHTOOL_GRXCLSRULE: | ||
2626 | convert_out = true; | ||
2627 | /* fall through */ | ||
2628 | case ETHTOOL_SRXCLSRLDEL: | ||
2629 | case ETHTOOL_SRXCLSRLINS: | ||
2630 | buf_size += sizeof(struct ethtool_rxnfc); | ||
2631 | convert_in = true; | ||
2632 | break; | ||
2633 | } | ||
2634 | |||
2635 | ifr = compat_alloc_user_space(buf_size); | ||
2636 | rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8); | ||
2637 | |||
2638 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||
2601 | return -EFAULT; | 2639 | return -EFAULT; |
2602 | 2640 | ||
2603 | datap = compat_ptr(data); | 2641 | if (put_user(convert_in ? rxnfc : compat_ptr(data), |
2604 | if (put_user(datap, &ifr->ifr_ifru.ifru_data)) | 2642 | &ifr->ifr_ifru.ifru_data)) |
2605 | return -EFAULT; | 2643 | return -EFAULT; |
2606 | 2644 | ||
2607 | return dev_ioctl(net, SIOCETHTOOL, ifr); | 2645 | if (convert_in) { |
2646 | /* We expect there to be holes between fs.m_u and | ||
2647 | * fs.ring_cookie and at the end of fs, but nowhere else. | ||
2648 | */ | ||
2649 | BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) + | ||
2650 | sizeof(compat_rxnfc->fs.m_u) != | ||
2651 | offsetof(struct ethtool_rxnfc, fs.m_u) + | ||
2652 | sizeof(rxnfc->fs.m_u)); | ||
2653 | BUILD_BUG_ON( | ||
2654 | offsetof(struct compat_ethtool_rxnfc, fs.location) - | ||
2655 | offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != | ||
2656 | offsetof(struct ethtool_rxnfc, fs.location) - | ||
2657 | offsetof(struct ethtool_rxnfc, fs.ring_cookie)); | ||
2658 | |||
2659 | if (copy_in_user(rxnfc, compat_rxnfc, | ||
2660 | (void *)(&rxnfc->fs.m_u + 1) - | ||
2661 | (void *)rxnfc) || | ||
2662 | copy_in_user(&rxnfc->fs.ring_cookie, | ||
2663 | &compat_rxnfc->fs.ring_cookie, | ||
2664 | (void *)(&rxnfc->fs.location + 1) - | ||
2665 | (void *)&rxnfc->fs.ring_cookie) || | ||
2666 | copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt, | ||
2667 | sizeof(rxnfc->rule_cnt))) | ||
2668 | return -EFAULT; | ||
2669 | } | ||
2670 | |||
2671 | ret = dev_ioctl(net, SIOCETHTOOL, ifr); | ||
2672 | if (ret) | ||
2673 | return ret; | ||
2674 | |||
2675 | if (convert_out) { | ||
2676 | if (copy_in_user(compat_rxnfc, rxnfc, | ||
2677 | (const void *)(&rxnfc->fs.m_u + 1) - | ||
2678 | (const void *)rxnfc) || | ||
2679 | copy_in_user(&compat_rxnfc->fs.ring_cookie, | ||
2680 | &rxnfc->fs.ring_cookie, | ||
2681 | (const void *)(&rxnfc->fs.location + 1) - | ||
2682 | (const void *)&rxnfc->fs.ring_cookie) || | ||
2683 | copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt, | ||
2684 | sizeof(rxnfc->rule_cnt))) | ||
2685 | return -EFAULT; | ||
2686 | |||
2687 | if (ethcmd == ETHTOOL_GRXCLSRLALL) { | ||
2688 | /* As an optimisation, we only copy the actual | ||
2689 | * number of rules that the underlying | ||
2690 | * function returned. Since Mallory might | ||
2691 | * change the rule count in user memory, we | ||
2692 | * check that it is less than the rule count | ||
2693 | * originally given (as the user buffer size), | ||
2694 | * which has been range-checked. | ||
2695 | */ | ||
2696 | if (get_user(actual_rule_cnt, &rxnfc->rule_cnt)) | ||
2697 | return -EFAULT; | ||
2698 | if (actual_rule_cnt < rule_cnt) | ||
2699 | rule_cnt = actual_rule_cnt; | ||
2700 | if (copy_in_user(&compat_rxnfc->rule_locs[0], | ||
2701 | &rxnfc->rule_locs[0], | ||
2702 | rule_cnt * sizeof(u32))) | ||
2703 | return -EFAULT; | ||
2704 | } | ||
2705 | } | ||
2706 | |||
2707 | return 0; | ||
2608 | } | 2708 | } |
2609 | 2709 | ||
2610 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) | 2710 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) |
@@ -2886,7 +2986,7 @@ out: | |||
2886 | 2986 | ||
2887 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE | 2987 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE |
2888 | * for some operations; this forces use of the newer bridge-utils that | 2988 | * for some operations; this forces use of the newer bridge-utils that |
2889 | * use compatiable ioctls | 2989 | * use compatible ioctls |
2890 | */ | 2990 | */ |
2891 | static int old_bridge_ioctl(compat_ulong_t __user *argp) | 2991 | static int old_bridge_ioctl(compat_ulong_t __user *argp) |
2892 | { | 2992 | { |
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 8873fd8ddacd..b2198e65d8bb 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -18,14 +18,13 @@ config SUNRPC_XPRT_RDMA | |||
18 | If unsure, say N. | 18 | If unsure, say N. |
19 | 19 | ||
20 | config RPCSEC_GSS_KRB5 | 20 | config RPCSEC_GSS_KRB5 |
21 | tristate | 21 | tristate "Secure RPC: Kerberos V mechanism" |
22 | depends on SUNRPC && CRYPTO | 22 | depends on SUNRPC && CRYPTO |
23 | prompt "Secure RPC: Kerberos V mechanism" if !(NFS_V4 || NFSD_V4) | 23 | depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS |
24 | depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES | ||
25 | depends on CRYPTO_ARC4 | ||
24 | default y | 26 | default y |
25 | select SUNRPC_GSS | 27 | select SUNRPC_GSS |
26 | select CRYPTO_MD5 | ||
27 | select CRYPTO_DES | ||
28 | select CRYPTO_CBC | ||
29 | help | 28 | help |
30 | Choose Y here to enable Secure RPC using the Kerberos version 5 | 29 | Choose Y here to enable Secure RPC using the Kerberos version 5 |
31 | GSS-API mechanism (RFC 1964). | 30 | GSS-API mechanism (RFC 1964). |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index f3914d0c5079..339ba64cce1e 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -520,7 +520,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
520 | warn_gssd(); | 520 | warn_gssd(); |
521 | task->tk_timeout = 15*HZ; | 521 | task->tk_timeout = 15*HZ; |
522 | rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL); | 522 | rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL); |
523 | return 0; | 523 | return -EAGAIN; |
524 | } | 524 | } |
525 | if (IS_ERR(gss_msg)) { | 525 | if (IS_ERR(gss_msg)) { |
526 | err = PTR_ERR(gss_msg); | 526 | err = PTR_ERR(gss_msg); |
@@ -563,10 +563,12 @@ retry: | |||
563 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 563 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
564 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 564 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
565 | pipe_version >= 0, 15*HZ); | 565 | pipe_version >= 0, 15*HZ); |
566 | if (pipe_version < 0) { | ||
567 | warn_gssd(); | ||
568 | err = -EACCES; | ||
569 | } | ||
566 | if (err) | 570 | if (err) |
567 | goto out; | 571 | goto out; |
568 | if (pipe_version < 0) | ||
569 | warn_gssd(); | ||
570 | goto retry; | 572 | goto retry; |
571 | } | 573 | } |
572 | if (IS_ERR(gss_msg)) { | 574 | if (IS_ERR(gss_msg)) { |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9022f0a6503e..0a9a2ec2e469 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -427,7 +427,7 @@ static int | |||
427 | context_derive_keys_rc4(struct krb5_ctx *ctx) | 427 | context_derive_keys_rc4(struct krb5_ctx *ctx) |
428 | { | 428 | { |
429 | struct crypto_hash *hmac; | 429 | struct crypto_hash *hmac; |
430 | static const char sigkeyconstant[] = "signaturekey"; | 430 | char sigkeyconstant[] = "signaturekey"; |
431 | int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ | 431 | int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ |
432 | struct hash_desc desc; | 432 | struct hash_desc desc; |
433 | struct scatterlist sg[1]; | 433 | struct scatterlist sg[1]; |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 8b4061049d76..e3c36a274412 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -160,6 +160,28 @@ gss_mech_get_by_name(const char *name) | |||
160 | 160 | ||
161 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); | 161 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); |
162 | 162 | ||
163 | struct gss_api_mech * | ||
164 | gss_mech_get_by_OID(struct xdr_netobj *obj) | ||
165 | { | ||
166 | struct gss_api_mech *pos, *gm = NULL; | ||
167 | |||
168 | spin_lock(®istered_mechs_lock); | ||
169 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | ||
170 | if (obj->len == pos->gm_oid.len) { | ||
171 | if (0 == memcmp(obj->data, pos->gm_oid.data, obj->len)) { | ||
172 | if (try_module_get(pos->gm_owner)) | ||
173 | gm = pos; | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | spin_unlock(®istered_mechs_lock); | ||
179 | return gm; | ||
180 | |||
181 | } | ||
182 | |||
183 | EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); | ||
184 | |||
163 | static inline int | 185 | static inline int |
164 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) | 186 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) |
165 | { | 187 | { |
@@ -193,6 +215,22 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | |||
193 | 215 | ||
194 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); | 216 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); |
195 | 217 | ||
218 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) | ||
219 | { | ||
220 | struct gss_api_mech *pos = NULL; | ||
221 | int i = 0; | ||
222 | |||
223 | spin_lock(®istered_mechs_lock); | ||
224 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | ||
225 | array_ptr[i] = pos->gm_pfs->pseudoflavor; | ||
226 | i++; | ||
227 | } | ||
228 | spin_unlock(®istered_mechs_lock); | ||
229 | return i; | ||
230 | } | ||
231 | |||
232 | EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors); | ||
233 | |||
196 | u32 | 234 | u32 |
197 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) | 235 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) |
198 | { | 236 | { |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index bcdae78fdfc6..8d0f7d3c71c8 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1101,7 +1101,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1101 | 1101 | ||
1102 | /* credential is: | 1102 | /* credential is: |
1103 | * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle | 1103 | * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle |
1104 | * at least 5 u32s, and is preceeded by length, so that makes 6. | 1104 | * at least 5 u32s, and is preceded by length, so that makes 6. |
1105 | */ | 1105 | */ |
1106 | 1106 | ||
1107 | if (argv->iov_len < 5 * 4) | 1107 | if (argv->iov_len < 5 * 4) |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index e7a96e478f63..8d83f9d48713 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1508,7 +1508,10 @@ call_timeout(struct rpc_task *task) | |||
1508 | if (clnt->cl_chatty) | 1508 | if (clnt->cl_chatty) |
1509 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1509 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1510 | clnt->cl_protname, clnt->cl_server); | 1510 | clnt->cl_protname, clnt->cl_server); |
1511 | rpc_exit(task, -EIO); | 1511 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1512 | rpc_exit(task, -ETIMEDOUT); | ||
1513 | else | ||
1514 | rpc_exit(task, -EIO); | ||
1512 | return; | 1515 | return; |
1513 | } | 1516 | } |
1514 | 1517 | ||
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ffb687671da0..6b43ee7221d5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -860,8 +860,10 @@ static void rpc_release_resources_task(struct rpc_task *task) | |||
860 | { | 860 | { |
861 | if (task->tk_rqstp) | 861 | if (task->tk_rqstp) |
862 | xprt_release(task); | 862 | xprt_release(task); |
863 | if (task->tk_msg.rpc_cred) | 863 | if (task->tk_msg.rpc_cred) { |
864 | put_rpccred(task->tk_msg.rpc_cred); | 864 | put_rpccred(task->tk_msg.rpc_cred); |
865 | task->tk_msg.rpc_cred = NULL; | ||
866 | } | ||
865 | rpc_task_release_client(task); | 867 | rpc_task_release_client(task); |
866 | } | 868 | } |
867 | 869 | ||
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 30916b06c12b..c8e10216c113 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -38,6 +38,14 @@ struct unix_domain { | |||
38 | 38 | ||
39 | extern struct auth_ops svcauth_unix; | 39 | extern struct auth_ops svcauth_unix; |
40 | 40 | ||
41 | static void svcauth_unix_domain_release(struct auth_domain *dom) | ||
42 | { | ||
43 | struct unix_domain *ud = container_of(dom, struct unix_domain, h); | ||
44 | |||
45 | kfree(dom->name); | ||
46 | kfree(ud); | ||
47 | } | ||
48 | |||
41 | struct auth_domain *unix_domain_find(char *name) | 49 | struct auth_domain *unix_domain_find(char *name) |
42 | { | 50 | { |
43 | struct auth_domain *rv; | 51 | struct auth_domain *rv; |
@@ -47,7 +55,7 @@ struct auth_domain *unix_domain_find(char *name) | |||
47 | while(1) { | 55 | while(1) { |
48 | if (rv) { | 56 | if (rv) { |
49 | if (new && rv != &new->h) | 57 | if (new && rv != &new->h) |
50 | auth_domain_put(&new->h); | 58 | svcauth_unix_domain_release(&new->h); |
51 | 59 | ||
52 | if (rv->flavour != &svcauth_unix) { | 60 | if (rv->flavour != &svcauth_unix) { |
53 | auth_domain_put(rv); | 61 | auth_domain_put(rv); |
@@ -74,14 +82,6 @@ struct auth_domain *unix_domain_find(char *name) | |||
74 | } | 82 | } |
75 | EXPORT_SYMBOL_GPL(unix_domain_find); | 83 | EXPORT_SYMBOL_GPL(unix_domain_find); |
76 | 84 | ||
77 | static void svcauth_unix_domain_release(struct auth_domain *dom) | ||
78 | { | ||
79 | struct unix_domain *ud = container_of(dom, struct unix_domain, h); | ||
80 | |||
81 | kfree(dom->name); | ||
82 | kfree(ud); | ||
83 | } | ||
84 | |||
85 | 85 | ||
86 | /************************************************** | 86 | /************************************************** |
87 | * cache for IP address to unix_domain | 87 | * cache for IP address to unix_domain |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 9494c3767356..ce5eb68a9664 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -906,6 +906,7 @@ void xprt_transmit(struct rpc_task *task) | |||
906 | } | 906 | } |
907 | 907 | ||
908 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); | 908 | dprintk("RPC: %5u xmit complete\n", task->tk_pid); |
909 | task->tk_flags |= RPC_TASK_SENT; | ||
909 | spin_lock_bh(&xprt->transport_lock); | 910 | spin_lock_bh(&xprt->transport_lock); |
910 | 911 | ||
911 | xprt->ops->set_retrans_timeout(task); | 912 | xprt->ops->set_retrans_timeout(task); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index be96d429b475..bf005d3c65ef 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -504,7 +504,7 @@ static int xs_nospace(struct rpc_task *task) | |||
504 | * EAGAIN: The socket was blocked, please call again later to | 504 | * EAGAIN: The socket was blocked, please call again later to |
505 | * complete the request | 505 | * complete the request |
506 | * ENOTCONN: Caller needs to invoke connect logic then call again | 506 | * ENOTCONN: Caller needs to invoke connect logic then call again |
507 | * other: Some other error occured, the request was not sent | 507 | * other: Some other error occurred, the request was not sent |
508 | */ | 508 | */ |
509 | static int xs_udp_send_request(struct rpc_task *task) | 509 | static int xs_udp_send_request(struct rpc_task *task) |
510 | { | 510 | { |
@@ -590,7 +590,7 @@ static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | |||
590 | * EAGAIN: The socket was blocked, please call again later to | 590 | * EAGAIN: The socket was blocked, please call again later to |
591 | * complete the request | 591 | * complete the request |
592 | * ENOTCONN: Caller needs to invoke connect logic then call again | 592 | * ENOTCONN: Caller needs to invoke connect logic then call again |
593 | * other: Some other error occured, the request was not sent | 593 | * other: Some other error occurred, the request was not sent |
594 | * | 594 | * |
595 | * XXX: In the case of soft timeouts, should we eventually give up | 595 | * XXX: In the case of soft timeouts, should we eventually give up |
596 | * if sendmsg is not able to make progress? | 596 | * if sendmsg is not able to make progress? |
@@ -710,6 +710,8 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
710 | if (sk == NULL) | 710 | if (sk == NULL) |
711 | return; | 711 | return; |
712 | 712 | ||
713 | transport->srcport = 0; | ||
714 | |||
713 | write_lock_bh(&sk->sk_callback_lock); | 715 | write_lock_bh(&sk->sk_callback_lock); |
714 | transport->inet = NULL; | 716 | transport->inet = NULL; |
715 | transport->sock = NULL; | 717 | transport->sock = NULL; |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 43639ff1cbec..ebf338f7b14e 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -2471,7 +2471,7 @@ exit: | |||
2471 | * A pending message being re-assembled must store certain values | 2471 | * A pending message being re-assembled must store certain values |
2472 | * to handle subsequent fragments correctly. The following functions | 2472 | * to handle subsequent fragments correctly. The following functions |
2473 | * help storing these values in unused, available fields in the | 2473 | * help storing these values in unused, available fields in the |
2474 | * pending message. This makes dynamic memory allocation unecessary. | 2474 | * pending message. This makes dynamic memory allocation unnecessary. |
2475 | */ | 2475 | */ |
2476 | 2476 | ||
2477 | static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) | 2477 | static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c9fa6dfcf287..80025a1b3bfd 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -160,7 +160,7 @@ void tipc_named_withdraw(struct publication *publ) | |||
160 | 160 | ||
161 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); | 161 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); |
162 | if (!buf) { | 162 | if (!buf) { |
163 | warn("Withdrawl distribution failure\n"); | 163 | warn("Withdrawal distribution failure\n"); |
164 | return; | 164 | return; |
165 | } | 165 | } |
166 | 166 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1663e1a2efdd..b1d75beb7e20 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -207,7 +207,7 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) | |||
207 | /* | 207 | /* |
208 | * This may look like an off by one error but it is a bit more | 208 | * This may look like an off by one error but it is a bit more |
209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. | 209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. |
210 | * sun_path[108] doesnt as such exist. However in kernel space | 210 | * sun_path[108] doesn't as such exist. However in kernel space |
211 | * we are guaranteed that it is a valid memory location in our | 211 | * we are guaranteed that it is a valid memory location in our |
212 | * kernel address buffer. | 212 | * kernel address buffer. |
213 | */ | 213 | */ |
@@ -524,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *, | |||
524 | int, int); | 524 | int, int); |
525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | 525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, |
526 | struct msghdr *, size_t); | 526 | struct msghdr *, size_t); |
527 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | ||
528 | struct msghdr *, size_t, int); | ||
527 | 529 | ||
528 | static const struct proto_ops unix_stream_ops = { | 530 | static const struct proto_ops unix_stream_ops = { |
529 | .family = PF_UNIX, | 531 | .family = PF_UNIX, |
@@ -583,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
583 | .setsockopt = sock_no_setsockopt, | 585 | .setsockopt = sock_no_setsockopt, |
584 | .getsockopt = sock_no_getsockopt, | 586 | .getsockopt = sock_no_getsockopt, |
585 | .sendmsg = unix_seqpacket_sendmsg, | 587 | .sendmsg = unix_seqpacket_sendmsg, |
586 | .recvmsg = unix_dgram_recvmsg, | 588 | .recvmsg = unix_seqpacket_recvmsg, |
587 | .mmap = sock_no_mmap, | 589 | .mmap = sock_no_mmap, |
588 | .sendpage = sock_no_sendpage, | 590 | .sendpage = sock_no_sendpage, |
589 | }; | 591 | }; |
@@ -1699,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1699 | return unix_dgram_sendmsg(kiocb, sock, msg, len); | 1701 | return unix_dgram_sendmsg(kiocb, sock, msg, len); |
1700 | } | 1702 | } |
1701 | 1703 | ||
1704 | static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
1705 | struct msghdr *msg, size_t size, | ||
1706 | int flags) | ||
1707 | { | ||
1708 | struct sock *sk = sock->sk; | ||
1709 | |||
1710 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1711 | return -ENOTCONN; | ||
1712 | |||
1713 | return unix_dgram_recvmsg(iocb, sock, msg, size, flags); | ||
1714 | } | ||
1715 | |||
1702 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) | 1716 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) |
1703 | { | 1717 | { |
1704 | struct unix_sock *u = unix_sk(sk); | 1718 | struct unix_sock *u = unix_sk(sk); |
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 11f25c7a7a05..f346395314ba 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Structures for interfacing with the /proc filesystem. | 53 | * Structures for interfacing with the /proc filesystem. |
54 | * Router creates its own directory /proc/net/router with the folowing | 54 | * Router creates its own directory /proc/net/router with the following |
55 | * entries: | 55 | * entries: |
56 | * config device configuration | 56 | * config device configuration |
57 | * status global device statistics | 57 | * status global device statistics |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3332d5bce317..ab801a1097b2 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -809,7 +809,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
809 | if (r) { | 809 | if (r) { |
810 | /* | 810 | /* |
811 | * We will disable all channels that do not match our | 811 | * We will disable all channels that do not match our |
812 | * recieved regulatory rule unless the hint is coming | 812 | * received regulatory rule unless the hint is coming |
813 | * from a Country IE and the Country IE had no information | 813 | * from a Country IE and the Country IE had no information |
814 | * about a band. The IEEE 802.11 spec allows for an AP | 814 | * about a band. The IEEE 802.11 spec allows for an AP |
815 | * to send only a subset of the regulatory rules allowed, | 815 | * to send only a subset of the regulatory rules allowed, |
@@ -838,7 +838,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
838 | request_wiphy && request_wiphy == wiphy && | 838 | request_wiphy && request_wiphy == wiphy && |
839 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 839 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
840 | /* | 840 | /* |
841 | * This gaurantees the driver's requested regulatory domain | 841 | * This guarantees the driver's requested regulatory domain |
842 | * will always be used as a base for further regulatory | 842 | * will always be used as a base for further regulatory |
843 | * settings | 843 | * settings |
844 | */ | 844 | */ |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index ea427f418f64..fbf6f33ae4d0 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -124,6 +124,15 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
124 | } | 124 | } |
125 | 125 | ||
126 | /* must hold dev->bss_lock! */ | 126 | /* must hold dev->bss_lock! */ |
127 | static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, | ||
128 | struct cfg80211_internal_bss *bss) | ||
129 | { | ||
130 | list_del_init(&bss->list); | ||
131 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
132 | kref_put(&bss->ref, bss_release); | ||
133 | } | ||
134 | |||
135 | /* must hold dev->bss_lock! */ | ||
127 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) | 136 | void cfg80211_bss_expire(struct cfg80211_registered_device *dev) |
128 | { | 137 | { |
129 | struct cfg80211_internal_bss *bss, *tmp; | 138 | struct cfg80211_internal_bss *bss, *tmp; |
@@ -134,9 +143,7 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *dev) | |||
134 | continue; | 143 | continue; |
135 | if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) | 144 | if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE)) |
136 | continue; | 145 | continue; |
137 | list_del(&bss->list); | 146 | __cfg80211_unlink_bss(dev, bss); |
138 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
139 | kref_put(&bss->ref, bss_release); | ||
140 | expired = true; | 147 | expired = true; |
141 | } | 148 | } |
142 | 149 | ||
@@ -585,16 +592,23 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
585 | struct cfg80211_internal_bss *res; | 592 | struct cfg80211_internal_bss *res; |
586 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 593 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
587 | u.probe_resp.variable); | 594 | u.probe_resp.variable); |
588 | size_t privsz = wiphy->bss_priv_size; | 595 | size_t privsz; |
596 | |||
597 | if (WARN_ON(!mgmt)) | ||
598 | return NULL; | ||
599 | |||
600 | if (WARN_ON(!wiphy)) | ||
601 | return NULL; | ||
589 | 602 | ||
590 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && | 603 | if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && |
591 | (signal < 0 || signal > 100))) | 604 | (signal < 0 || signal > 100))) |
592 | return NULL; | 605 | return NULL; |
593 | 606 | ||
594 | if (WARN_ON(!mgmt || !wiphy || | 607 | if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) |
595 | len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable))) | ||
596 | return NULL; | 608 | return NULL; |
597 | 609 | ||
610 | privsz = wiphy->bss_priv_size; | ||
611 | |||
598 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); | 612 | res = kzalloc(sizeof(*res) + privsz + ielen, gfp); |
599 | if (!res) | 613 | if (!res) |
600 | return NULL; | 614 | return NULL; |
@@ -662,11 +676,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
662 | 676 | ||
663 | spin_lock_bh(&dev->bss_lock); | 677 | spin_lock_bh(&dev->bss_lock); |
664 | if (!list_empty(&bss->list)) { | 678 | if (!list_empty(&bss->list)) { |
665 | list_del_init(&bss->list); | 679 | __cfg80211_unlink_bss(dev, bss); |
666 | dev->bss_generation++; | 680 | dev->bss_generation++; |
667 | rb_erase(&bss->rbn, &dev->bss_tree); | ||
668 | |||
669 | kref_put(&bss->ref, bss_release); | ||
670 | } | 681 | } |
671 | spin_unlock_bh(&dev->bss_lock); | 682 | spin_unlock_bh(&dev->bss_lock); |
672 | } | 683 | } |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 406207515b5e..f77e4e75f914 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * x25_parse_facilities - Parse facilities from skb into the facilities structs | 31 | * x25_parse_facilities - Parse facilities from skb into the facilities structs |
32 | * | 32 | * |
33 | * @skb: sk_buff to parse | 33 | * @skb: sk_buff to parse |
34 | * @facilities: Regular facilites, updated as facilities are found | 34 | * @facilities: Regular facilities, updated as facilities are found |
35 | * @dte_facs: ITU DTE facilities, updated as DTE facilities are found | 35 | * @dte_facs: ITU DTE facilities, updated as DTE facilities are found |
36 | * @vc_fac_mask: mask is updated with all facilities found | 36 | * @vc_fac_mask: mask is updated with all facilities found |
37 | * | 37 | * |
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 25a810793968..c541b622ae16 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -31,7 +31,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
31 | goto out_no_route; | 31 | goto out_no_route; |
32 | 32 | ||
33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { | 33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { |
34 | /* This shouldnt happen, if it occurs somehow | 34 | /* This shouldn't happen, if it occurs somehow |
35 | * do something sensible | 35 | * do something sensible |
36 | */ | 36 | */ |
37 | goto out_put_route; | 37 | goto out_put_route; |
@@ -45,7 +45,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /* Remote end sending a call request on an already | 47 | /* Remote end sending a call request on an already |
48 | * established LCI? It shouldnt happen, just in case.. | 48 | * established LCI? It shouldn't happen, just in case.. |
49 | */ | 49 | */ |
50 | read_lock_bh(&x25_forward_list_lock); | 50 | read_lock_bh(&x25_forward_list_lock); |
51 | list_for_each(entry, &x25_forward_list) { | 51 | list_for_each(entry, &x25_forward_list) { |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 872065ca7f8c..a026b0ef2443 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
173 | goto drop_unlock; | 173 | goto drop_unlock; |
174 | } | 174 | } |
175 | 175 | ||
176 | if (x->props.replay_window && x->repl->check(x, skb, seq)) { | 176 | if (x->repl->check(x, skb, seq)) { |
177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); | 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
178 | goto drop_unlock; | 178 | goto drop_unlock; |
179 | } | 179 | } |
@@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
190 | XFRM_SKB_CB(skb)->seq.input.low = seq; | 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; |
191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; | 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
192 | 192 | ||
193 | skb_dst_force(skb); | ||
194 | |||
193 | nexthdr = x->type->input(x, skb); | 195 | nexthdr = x->type->input(x, skb); |
194 | 196 | ||
195 | if (nexthdr == -EINPROGRESS) | 197 | if (nexthdr == -EINPROGRESS) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 1aba03f449cc..47bacd8c0250 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
78 | 78 | ||
79 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
80 | 80 | ||
81 | skb_dst_force(skb); | ||
82 | |||
81 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
82 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
83 | goto out_exit; | 85 | goto out_exit; |
@@ -94,7 +96,7 @@ resume: | |||
94 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
95 | goto error_nolock; | 97 | goto error_nolock; |
96 | } | 98 | } |
97 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
98 | x = dst->xfrm; | 100 | x = dst->xfrm; |
99 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
100 | 102 | ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 15792d8b6272..b4d745ea8ee1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1406,6 +1406,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1406 | struct net *net = xp_net(policy); | 1406 | struct net *net = xp_net(policy); |
1407 | unsigned long now = jiffies; | 1407 | unsigned long now = jiffies; |
1408 | struct net_device *dev; | 1408 | struct net_device *dev; |
1409 | struct xfrm_mode *inner_mode; | ||
1409 | struct dst_entry *dst_prev = NULL; | 1410 | struct dst_entry *dst_prev = NULL; |
1410 | struct dst_entry *dst0 = NULL; | 1411 | struct dst_entry *dst0 = NULL; |
1411 | int i = 0; | 1412 | int i = 0; |
@@ -1436,6 +1437,17 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1436 | goto put_states; | 1437 | goto put_states; |
1437 | } | 1438 | } |
1438 | 1439 | ||
1440 | if (xfrm[i]->sel.family == AF_UNSPEC) { | ||
1441 | inner_mode = xfrm_ip2inner_mode(xfrm[i], | ||
1442 | xfrm_af2proto(family)); | ||
1443 | if (!inner_mode) { | ||
1444 | err = -EAFNOSUPPORT; | ||
1445 | dst_release(dst); | ||
1446 | goto put_states; | ||
1447 | } | ||
1448 | } else | ||
1449 | inner_mode = xfrm[i]->inner_mode; | ||
1450 | |||
1439 | if (!dst_prev) | 1451 | if (!dst_prev) |
1440 | dst0 = dst1; | 1452 | dst0 = dst1; |
1441 | else { | 1453 | else { |
@@ -1464,7 +1476,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1464 | dst1->lastuse = now; | 1476 | dst1->lastuse = now; |
1465 | 1477 | ||
1466 | dst1->input = dst_discard; | 1478 | dst1->input = dst_discard; |
1467 | dst1->output = xfrm[i]->outer_mode->afinfo->output; | 1479 | dst1->output = inner_mode->afinfo->output; |
1468 | 1480 | ||
1469 | dst1->next = dst_prev; | 1481 | dst1->next = dst_prev; |
1470 | dst_prev = dst1; | 1482 | dst_prev = dst1; |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f5be5b15740..47f1b8638df9 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
118 | u32 diff; | 118 | u32 diff; |
119 | u32 seq = ntohl(net_seq); | 119 | u32 seq = ntohl(net_seq); |
120 | 120 | ||
121 | if (!x->props.replay_window) | ||
122 | return 0; | ||
123 | |||
121 | if (unlikely(seq == 0)) | 124 | if (unlikely(seq == 0)) |
122 | goto err; | 125 | goto err; |
123 | 126 | ||
@@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, | |||
193 | { | 196 | { |
194 | unsigned int bitnr, nr; | 197 | unsigned int bitnr, nr; |
195 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 198 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
199 | u32 pos; | ||
196 | u32 seq = ntohl(net_seq); | 200 | u32 seq = ntohl(net_seq); |
197 | u32 diff = replay_esn->seq - seq; | 201 | u32 diff = replay_esn->seq - seq; |
198 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | 202 | |
203 | if (!replay_esn->replay_window) | ||
204 | return 0; | ||
205 | |||
206 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
199 | 207 | ||
200 | if (unlikely(seq == 0)) | 208 | if (unlikely(seq == 0)) |
201 | goto err; | 209 | goto err; |
@@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, | |||
373 | unsigned int bitnr, nr; | 381 | unsigned int bitnr, nr; |
374 | u32 diff; | 382 | u32 diff; |
375 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 383 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
384 | u32 pos; | ||
376 | u32 seq = ntohl(net_seq); | 385 | u32 seq = ntohl(net_seq); |
377 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
378 | u32 wsize = replay_esn->replay_window; | 386 | u32 wsize = replay_esn->replay_window; |
379 | u32 top = replay_esn->seq; | 387 | u32 top = replay_esn->seq; |
380 | u32 bottom = top - wsize + 1; | 388 | u32 bottom = top - wsize + 1; |
381 | 389 | ||
390 | if (!wsize) | ||
391 | return 0; | ||
392 | |||
393 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
394 | |||
382 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && | 395 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && |
383 | (replay_esn->seq < replay_esn->replay_window - 1))) | 396 | (replay_esn->seq < replay_esn->replay_window - 1))) |
384 | goto err; | 397 | goto err; |
@@ -519,9 +532,12 @@ int xfrm_init_replay(struct xfrm_state *x) | |||
519 | 532 | ||
520 | if (replay_esn) { | 533 | if (replay_esn) { |
521 | if (replay_esn->replay_window > | 534 | if (replay_esn->replay_window > |
522 | replay_esn->bmp_len * sizeof(__u32)) | 535 | replay_esn->bmp_len * sizeof(__u32) * 8) |
523 | return -EINVAL; | 536 | return -EINVAL; |
524 | 537 | ||
538 | if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0) | ||
539 | return -EINVAL; | ||
540 | |||
525 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) | 541 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) |
526 | x->repl = &xfrm_replay_esn; | 542 | x->repl = &xfrm_replay_esn; |
527 | else | 543 | else |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d575f0534868..dd78536d40de 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
1181 | goto error; | 1181 | goto error; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | if (orig->replay_esn) { | ||
1185 | err = xfrm_replay_clone(x, orig); | ||
1186 | if (err) | ||
1187 | goto error; | ||
1188 | } | ||
1189 | |||
1184 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1190 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
1185 | 1191 | ||
1186 | err = xfrm_init_state(x); | 1192 | err = xfrm_init_state(x); |
@@ -1907,7 +1913,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
1907 | return res; | 1913 | return res; |
1908 | } | 1914 | } |
1909 | 1915 | ||
1910 | int xfrm_init_state(struct xfrm_state *x) | 1916 | int __xfrm_init_state(struct xfrm_state *x, bool init_replay) |
1911 | { | 1917 | { |
1912 | struct xfrm_state_afinfo *afinfo; | 1918 | struct xfrm_state_afinfo *afinfo; |
1913 | struct xfrm_mode *inner_mode; | 1919 | struct xfrm_mode *inner_mode; |
@@ -1980,12 +1986,25 @@ int xfrm_init_state(struct xfrm_state *x) | |||
1980 | if (x->outer_mode == NULL) | 1986 | if (x->outer_mode == NULL) |
1981 | goto error; | 1987 | goto error; |
1982 | 1988 | ||
1989 | if (init_replay) { | ||
1990 | err = xfrm_init_replay(x); | ||
1991 | if (err) | ||
1992 | goto error; | ||
1993 | } | ||
1994 | |||
1983 | x->km.state = XFRM_STATE_VALID; | 1995 | x->km.state = XFRM_STATE_VALID; |
1984 | 1996 | ||
1985 | error: | 1997 | error: |
1986 | return err; | 1998 | return err; |
1987 | } | 1999 | } |
1988 | 2000 | ||
2001 | EXPORT_SYMBOL(__xfrm_init_state); | ||
2002 | |||
2003 | int xfrm_init_state(struct xfrm_state *x) | ||
2004 | { | ||
2005 | return __xfrm_init_state(x, true); | ||
2006 | } | ||
2007 | |||
1989 | EXPORT_SYMBOL(xfrm_init_state); | 2008 | EXPORT_SYMBOL(xfrm_init_state); |
1990 | 2009 | ||
1991 | int __net_init xfrm_state_init(struct net *net) | 2010 | int __net_init xfrm_state_init(struct net *net) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 706385ae3e4b..c658cb3bc7c3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -124,9 +124,15 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
124 | { | 124 | { |
125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; | 125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; |
126 | 126 | ||
127 | if ((p->flags & XFRM_STATE_ESN) && !rt) | ||
128 | return -EINVAL; | ||
129 | |||
127 | if (!rt) | 130 | if (!rt) |
128 | return 0; | 131 | return 0; |
129 | 132 | ||
133 | if (p->id.proto != IPPROTO_ESP) | ||
134 | return -EINVAL; | ||
135 | |||
130 | if (p->replay_window != 0) | 136 | if (p->replay_window != 0) |
131 | return -EINVAL; | 137 | return -EINVAL; |
132 | 138 | ||
@@ -360,6 +366,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
360 | return 0; | 366 | return 0; |
361 | } | 367 | } |
362 | 368 | ||
369 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
370 | struct nlattr *rp) | ||
371 | { | ||
372 | struct xfrm_replay_state_esn *up; | ||
373 | |||
374 | if (!replay_esn || !rp) | ||
375 | return 0; | ||
376 | |||
377 | up = nla_data(rp); | ||
378 | |||
379 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
380 | xfrm_replay_state_esn_len(up)) | ||
381 | return -EINVAL; | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
363 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 386 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
364 | struct xfrm_replay_state_esn **preplay_esn, | 387 | struct xfrm_replay_state_esn **preplay_esn, |
365 | struct nlattr *rta) | 388 | struct nlattr *rta) |
@@ -511,7 +534,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
511 | 534 | ||
512 | xfrm_mark_get(attrs, &x->mark); | 535 | xfrm_mark_get(attrs, &x->mark); |
513 | 536 | ||
514 | err = xfrm_init_state(x); | 537 | err = __xfrm_init_state(x, false); |
515 | if (err) | 538 | if (err) |
516 | goto error; | 539 | goto error; |
517 | 540 | ||
@@ -874,7 +897,7 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
874 | u32 *f; | 897 | u32 *f; |
875 | 898 | ||
876 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 899 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
877 | if (nlh == NULL) /* shouldnt really happen ... */ | 900 | if (nlh == NULL) /* shouldn't really happen ... */ |
878 | return -EMSGSIZE; | 901 | return -EMSGSIZE; |
879 | 902 | ||
880 | f = nlmsg_data(nlh); | 903 | f = nlmsg_data(nlh); |
@@ -934,7 +957,7 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, | |||
934 | u32 *f; | 957 | u32 *f; |
935 | 958 | ||
936 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | 959 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
937 | if (nlh == NULL) /* shouldnt really happen ... */ | 960 | if (nlh == NULL) /* shouldn't really happen ... */ |
938 | return -EMSGSIZE; | 961 | return -EMSGSIZE; |
939 | 962 | ||
940 | f = nlmsg_data(nlh); | 963 | f = nlmsg_data(nlh); |
@@ -1341,7 +1364,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1341 | if (!xp) | 1364 | if (!xp) |
1342 | return err; | 1365 | return err; |
1343 | 1366 | ||
1344 | /* shouldnt excl be based on nlh flags?? | 1367 | /* shouldn't excl be based on nlh flags?? |
1345 | * Aha! this is anti-netlink really i.e more pfkey derived | 1368 | * Aha! this is anti-netlink really i.e more pfkey derived |
1346 | * in netlink excl is a flag and you wouldnt need | 1369 | * in netlink excl is a flag and you wouldnt need |
1347 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1370 | * a type XFRM_MSG_UPDPOLICY - JHS */ |
@@ -1766,6 +1789,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1766 | if (x->km.state != XFRM_STATE_VALID) | 1789 | if (x->km.state != XFRM_STATE_VALID) |
1767 | goto out; | 1790 | goto out; |
1768 | 1791 | ||
1792 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
1793 | if (err) | ||
1794 | goto out; | ||
1795 | |||
1769 | spin_lock_bh(&x->lock); | 1796 | spin_lock_bh(&x->lock); |
1770 | xfrm_update_ae_params(x, attrs); | 1797 | xfrm_update_ae_params(x, attrs); |
1771 | spin_unlock_bh(&x->lock); | 1798 | spin_unlock_bh(&x->lock); |