aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2006-02-17 16:20:30 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-02-17 16:20:30 -0500
commitb04a92e1601eb6df3a3b6599e7fb7ee021eef2cb (patch)
treef190980d5bffae81a67c0cea0d913ed2444ceb0c /net/core
parent70c07e02625ec46d0ffbfce1acef42d660803528 (diff)
parentf5e2a7b22e7d7dfda8794906d0fddeaaa09bb944 (diff)
Merge branch 'upstream-fixes'
Diffstat (limited to 'net/core')
-rw-r--r--net/core/datagram.c81
-rw-r--r--net/core/rtnetlink.c2
2 files changed, 54 insertions, 29 deletions
diff --git a/net/core/datagram.c b/net/core/datagram.c
index f8d322e1ea92..b8ce6bf81188 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -247,49 +247,74 @@ EXPORT_SYMBOL(skb_kill_datagram);
247int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset, 247int skb_copy_datagram_iovec(const struct sk_buff *skb, int offset,
248 struct iovec *to, int len) 248 struct iovec *to, int len)
249{ 249{
250 int i, err, fraglen, end = 0; 250 int start = skb_headlen(skb);
251 struct sk_buff *next = skb_shinfo(skb)->frag_list; 251 int i, copy = start - offset;
252 252
253 if (!len) 253 /* Copy header. */
254 return 0; 254 if (copy > 0) {
255 if (copy > len)
256 copy = len;
257 if (memcpy_toiovec(to, skb->data + offset, copy))
258 goto fault;
259 if ((len -= copy) == 0)
260 return 0;
261 offset += copy;
262 }
255 263
256next_skb: 264 /* Copy paged appendix. Hmm... why does this look so complicated? */
257 fraglen = skb_headlen(skb); 265 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
258 i = -1; 266 int end;
259 267
260 while (1) { 268 BUG_TRAP(start <= offset + len);
261 int start = end;
262 269
263 if ((end += fraglen) > offset) { 270 end = start + skb_shinfo(skb)->frags[i].size;
264 int copy = end - offset, o = offset - start; 271 if ((copy = end - offset) > 0) {
272 int err;
273 u8 *vaddr;
274 skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
275 struct page *page = frag->page;
265 276
266 if (copy > len) 277 if (copy > len)
267 copy = len; 278 copy = len;
268 if (i == -1) 279 vaddr = kmap(page);
269 err = memcpy_toiovec(to, skb->data + o, copy); 280 err = memcpy_toiovec(to, vaddr + frag->page_offset +
270 else { 281 offset - start, copy);
271 skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 282 kunmap(page);
272 struct page *page = frag->page;
273 void *p = kmap(page) + frag->page_offset + o;
274 err = memcpy_toiovec(to, p, copy);
275 kunmap(page);
276 }
277 if (err) 283 if (err)
278 goto fault; 284 goto fault;
279 if (!(len -= copy)) 285 if (!(len -= copy))
280 return 0; 286 return 0;
281 offset += copy; 287 offset += copy;
282 } 288 }
283 if (++i >= skb_shinfo(skb)->nr_frags) 289 start = end;
284 break;
285 fraglen = skb_shinfo(skb)->frags[i].size;
286 } 290 }
287 if (next) { 291
288 skb = next; 292 if (skb_shinfo(skb)->frag_list) {
289 BUG_ON(skb_shinfo(skb)->frag_list); 293 struct sk_buff *list = skb_shinfo(skb)->frag_list;
290 next = skb->next; 294
291 goto next_skb; 295 for (; list; list = list->next) {
296 int end;
297
298 BUG_TRAP(start <= offset + len);
299
300 end = start + list->len;
301 if ((copy = end - offset) > 0) {
302 if (copy > len)
303 copy = len;
304 if (skb_copy_datagram_iovec(list,
305 offset - start,
306 to, copy))
307 goto fault;
308 if ((len -= copy) == 0)
309 return 0;
310 offset += copy;
311 }
312 start = end;
313 }
292 } 314 }
315 if (!len)
316 return 0;
317
293fault: 318fault:
294 return -EFAULT; 319 return -EFAULT;
295} 320}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 8700379685e0..eca2976abb25 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -455,7 +455,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
455 if (!skb) 455 if (!skb)
456 return; 456 return;
457 457
458 if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) { 458 if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) {
459 kfree_skb(skb); 459 kfree_skb(skb);
460 return; 460 return;
461 } 461 }