~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to slirp/ip_input.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2009-03-22 10:13:17 UTC
  • mfrom: (1.2.1 upstream) (6.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090322101317-iigjtnu5qil35dtb
Tags: 0.10.1-1
[ Aurelien Jarno ]
* New upstream stable release:
  - patches/80_stable-branch.patch: remove.
* debian/control: 
  - Remove depends on proll.
  - Move depends on device-tree-compiler to build-depends.
  - Bump Standards-Version to 3.8.1 (no changes).
* patches/82_qemu-img_decimal.patch: new patch from upstream to make
  qemu-img accept sizes with decimal values (closes: bug#501400).

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
11
 *    notice, this list of conditions and the following disclaimer in the
12
12
 *    documentation and/or other materials provided with the distribution.
13
 
 * 3. All advertising materials mentioning features or use of this software
14
 
 *    must display the following acknowledgement:
15
 
 *      This product includes software developed by the University of
16
 
 *      California, Berkeley and its contributors.
17
 
 * 4. Neither the name of the University nor the names of its contributors
 
13
 * 3. Neither the name of the University nor the names of its contributors
18
14
 *    may be used to endorse or promote products derived from this software
19
15
 *    without specific prior written permission.
20
16
 *
43
39
 */
44
40
 
45
41
#include <slirp.h>
 
42
#include <osdep.h>
46
43
#include "ip_icmp.h"
47
44
 
48
45
#ifdef LOG_ENABLED
51
48
 
52
49
struct ipq ipq;
53
50
 
54
 
static struct ip *ip_reass(register struct ipasfrag *ip,
 
51
static struct ip *ip_reass(register struct ip *ip,
55
52
                           register struct ipq *fp);
56
53
static void ip_freef(struct ipq *fp);
57
54
static void ip_enq(register struct ipasfrag *p,
65
62
void
66
63
ip_init()
67
64
{
68
 
        ipq.next = ipq.prev = (ipqp_32)&ipq;
 
65
        ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
69
66
        ip_id = tt.tv_sec & 0xffff;
70
67
        udp_init();
71
68
        tcp_init();
136
133
                STAT(ipstat.ips_tooshort++);
137
134
                goto bad;
138
135
        }
 
136
 
 
137
    if (slirp_restrict) {
 
138
        if (memcmp(&ip->ip_dst.s_addr, &special_addr, 3)) {
 
139
            if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
 
140
                goto bad;
 
141
        } else {
 
142
            int host = ntohl(ip->ip_dst.s_addr) & 0xff;
 
143
            struct ex_list *ex_ptr;
 
144
 
 
145
            if (host == 0xff)
 
146
                goto bad;
 
147
 
 
148
            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
 
149
                if (ex_ptr->ex_addr == host)
 
150
                    break;
 
151
 
 
152
            if (!ex_ptr)
 
153
                goto bad;
 
154
        }
 
155
    }
 
156
 
139
157
        /* Should drop packet if mbuf too long? hmmm... */
140
158
        if (m->m_len > ip->ip_len)
141
159
           m_adj(m, ip->ip_len - m->m_len);
167
185
         */
168
186
        if (ip->ip_off &~ IP_DF) {
169
187
          register struct ipq *fp;
 
188
      struct qlink *l;
170
189
                /*
171
190
                 * Look for queue of fragments
172
191
                 * of this datagram.
173
192
                 */
174
 
                for (fp = (struct ipq *) ipq.next; fp != &ipq;
175
 
                     fp = (struct ipq *) fp->next)
176
 
                  if (ip->ip_id == fp->ipq_id &&
177
 
                      ip->ip_src.s_addr == fp->ipq_src.s_addr &&
178
 
                      ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
179
 
                      ip->ip_p == fp->ipq_p)
 
193
                for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
 
194
            fp = container_of(l, struct ipq, ip_link);
 
195
            if (ip->ip_id == fp->ipq_id &&
 
196
                    ip->ip_src.s_addr == fp->ipq_src.s_addr &&
 
197
                    ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
 
198
                    ip->ip_p == fp->ipq_p)
180
199
                    goto found;
181
 
                fp = 0;
 
200
        }
 
201
        fp = NULL;
182
202
        found:
183
203
 
184
204
                /*
188
208
                 */
189
209
                ip->ip_len -= hlen;
190
210
                if (ip->ip_off & IP_MF)
191
 
                  ((struct ipasfrag *)ip)->ipf_mff |= 1;
 
211
                  ip->ip_tos |= 1;
192
212
                else
193
 
                  ((struct ipasfrag *)ip)->ipf_mff &= ~1;
 
213
                  ip->ip_tos &= ~1;
194
214
 
195
215
                ip->ip_off <<= 3;
196
216
 
199
219
                 * or if this is not the first fragment,
200
220
                 * attempt reassembly; if it succeeds, proceed.
201
221
                 */
202
 
                if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
 
222
                if (ip->ip_tos & 1 || ip->ip_off) {
203
223
                        STAT(ipstat.ips_fragments++);
204
 
                        ip = ip_reass((struct ipasfrag *)ip, fp);
 
224
                        ip = ip_reass(ip, fp);
205
225
                        if (ip == 0)
206
226
                                return;
207
227
                        STAT(ipstat.ips_reassembled++);
237
257
        return;
238
258
}
239
259
 
 
260
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
 
261
#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))
240
262
/*
241
263
 * Take incoming datagram fragment and try to
242
264
 * reassemble it into whole datagram.  If a chain for
244
266
 * is given as fp; otherwise have to make a chain.
245
267
 */
246
268
static struct ip *
247
 
ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
 
269
ip_reass(register struct ip *ip, register struct ipq *fp)
248
270
{
249
271
        register struct mbuf *m = dtom(ip);
250
272
        register struct ipasfrag *q;
271
293
          struct mbuf *t;
272
294
          if ((t = m_get()) == NULL) goto dropfrag;
273
295
          fp = mtod(t, struct ipq *);
274
 
          insque_32(fp, &ipq);
 
296
          insque(&fp->ip_link, &ipq.ip_link);
275
297
          fp->ipq_ttl = IPFRAGTTL;
276
298
          fp->ipq_p = ip->ip_p;
277
299
          fp->ipq_id = ip->ip_id;
278
 
          fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
279
 
          fp->ipq_src = ((struct ip *)ip)->ip_src;
280
 
          fp->ipq_dst = ((struct ip *)ip)->ip_dst;
 
300
          fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
 
301
          fp->ipq_src = ip->ip_src;
 
302
          fp->ipq_dst = ip->ip_dst;
281
303
          q = (struct ipasfrag *)fp;
282
304
          goto insert;
283
305
        }
285
307
        /*
286
308
         * Find a segment which begins after this one does.
287
309
         */
288
 
        for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
289
 
            q = (struct ipasfrag *)q->ipf_next)
290
 
                if (q->ip_off > ip->ip_off)
 
310
        for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
 
311
            q = q->ipf_next)
 
312
                if (q->ipf_off > ip->ip_off)
291
313
                        break;
292
314
 
293
315
        /*
295
317
         * our data already.  If so, drop the data from the incoming
296
318
         * segment.  If it provides all of our data, drop us.
297
319
         */
298
 
        if (q->ipf_prev != (ipasfragp_32)fp) {
299
 
                i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
300
 
                  ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
 
320
        if (q->ipf_prev != &fp->frag_link) {
 
321
        struct ipasfrag *pq = q->ipf_prev;
 
322
                i = pq->ipf_off + pq->ipf_len - ip->ip_off;
301
323
                if (i > 0) {
302
324
                        if (i >= ip->ip_len)
303
325
                                goto dropfrag;
311
333
         * While we overlap succeeding segments trim them or,
312
334
         * if they are completely covered, dequeue them.
313
335
         */
314
 
        while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
315
 
                i = (ip->ip_off + ip->ip_len) - q->ip_off;
316
 
                if (i < q->ip_len) {
317
 
                        q->ip_len -= i;
318
 
                        q->ip_off += i;
 
336
        while (q != (struct ipasfrag*)&fp->frag_link &&
 
337
            ip->ip_off + ip->ip_len > q->ipf_off) {
 
338
                i = (ip->ip_off + ip->ip_len) - q->ipf_off;
 
339
                if (i < q->ipf_len) {
 
340
                        q->ipf_len -= i;
 
341
                        q->ipf_off += i;
319
342
                        m_adj(dtom(q), i);
320
343
                        break;
321
344
                }
322
 
                q = (struct ipasfrag *) q->ipf_next;
323
 
                m_freem(dtom((struct ipasfrag *) q->ipf_prev));
324
 
                ip_deq((struct ipasfrag *) q->ipf_prev);
 
345
                q = q->ipf_next;
 
346
                m_freem(dtom(q->ipf_prev));
 
347
                ip_deq(q->ipf_prev);
325
348
        }
326
349
 
327
350
insert:
329
352
         * Stick new segment in its place;
330
353
         * check for complete reassembly.
331
354
         */
332
 
        ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
 
355
        ip_enq(iptofrag(ip), q->ipf_prev);
333
356
        next = 0;
334
 
        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
335
 
             q = (struct ipasfrag *) q->ipf_next) {
336
 
                if (q->ip_off != next)
 
357
        for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
 
358
            q = q->ipf_next) {
 
359
                if (q->ipf_off != next)
337
360
                        return (0);
338
 
                next += q->ip_len;
 
361
                next += q->ipf_len;
339
362
        }
340
 
        if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
 
363
        if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
341
364
                return (0);
342
365
 
343
366
        /*
344
367
         * Reassembly is complete; concatenate fragments.
345
368
         */
346
 
        q = (struct ipasfrag *) fp->ipq_next;
 
369
    q = fp->frag_link.next;
347
370
        m = dtom(q);
348
371
 
349
372
        q = (struct ipasfrag *) q->ipf_next;
350
 
        while (q != (struct ipasfrag *)fp) {
351
 
          struct mbuf *t;
352
 
          t = dtom(q);
 
373
        while (q != (struct ipasfrag*)&fp->frag_link) {
 
374
          struct mbuf *t = dtom(q);
353
375
          q = (struct ipasfrag *) q->ipf_next;
354
376
          m_cat(m, t);
355
377
        }
360
382
         * dequeue and discard fragment reassembly header.
361
383
         * Make header visible.
362
384
         */
363
 
        ip = (struct ipasfrag *) fp->ipq_next;
 
385
        q = fp->frag_link.next;
364
386
 
365
387
        /*
366
388
         * If the fragments concatenated to an mbuf that's
370
392
         * into the new buffer.
371
393
         */
372
394
        if (m->m_flags & M_EXT) {
373
 
          int delta;
374
 
          delta = (char *)ip - m->m_dat;
375
 
          ip = (struct ipasfrag *)(m->m_ext + delta);
 
395
          int delta = (char *)q - m->m_dat;
 
396
          q = (struct ipasfrag *)(m->m_ext + delta);
376
397
        }
377
398
 
378
399
        /* DEBUG_ARG("ip = %lx", (long)ip);
379
400
         * ip=(struct ipasfrag *)m->m_data; */
380
401
 
 
402
    ip = fragtoip(q);
381
403
        ip->ip_len = next;
382
 
        ip->ipf_mff &= ~1;
383
 
        ((struct ip *)ip)->ip_src = fp->ipq_src;
384
 
        ((struct ip *)ip)->ip_dst = fp->ipq_dst;
385
 
        remque_32(fp);
 
404
        ip->ip_tos &= ~1;
 
405
        ip->ip_src = fp->ipq_src;
 
406
        ip->ip_dst = fp->ipq_dst;
 
407
        remque(&fp->ip_link);
386
408
        (void) m_free(dtom(fp));
387
 
        m = dtom(ip);
388
409
        m->m_len += (ip->ip_hl << 2);
389
410
        m->m_data -= (ip->ip_hl << 2);
390
411
 
391
 
        return ((struct ip *)ip);
 
412
        return ip;
392
413
 
393
414
dropfrag:
394
415
        STAT(ipstat.ips_fragdropped++);
405
426
{
406
427
        register struct ipasfrag *q, *p;
407
428
 
408
 
        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
409
 
            q = p) {
410
 
                p = (struct ipasfrag *) q->ipf_next;
 
429
        for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
 
430
                p = q->ipf_next;
411
431
                ip_deq(q);
412
432
                m_freem(dtom(q));
413
433
        }
414
 
        remque_32(fp);
 
434
        remque(&fp->ip_link);
415
435
        (void) m_free(dtom(fp));
416
436
}
417
437
 
424
444
{
425
445
        DEBUG_CALL("ip_enq");
426
446
        DEBUG_ARG("prev = %lx", (long)prev);
427
 
        p->ipf_prev = (ipasfragp_32) prev;
 
447
        p->ipf_prev =  prev;
428
448
        p->ipf_next = prev->ipf_next;
429
 
        ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
430
 
        prev->ipf_next = (ipasfragp_32) p;
 
449
        ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
 
450
        prev->ipf_next = p;
431
451
}
432
452
 
433
453
/*
448
468
void
449
469
ip_slowtimo()
450
470
{
451
 
        register struct ipq *fp;
 
471
    struct qlink *l;
452
472
 
453
473
        DEBUG_CALL("ip_slowtimo");
454
474
 
455
 
        fp = (struct ipq *) ipq.next;
456
 
        if (fp == 0)
 
475
    l = ipq.ip_link.next;
 
476
 
 
477
        if (l == 0)
457
478
           return;
458
479
 
459
 
        while (fp != &ipq) {
460
 
                --fp->ipq_ttl;
461
 
                fp = (struct ipq *) fp->next;
462
 
                if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
 
480
        while (l != &ipq.ip_link) {
 
481
        struct ipq *fp = container_of(l, struct ipq, ip_link);
 
482
        l = l->next;
 
483
                if (--fp->ipq_ttl == 0) {
463
484
                        STAT(ipstat.ips_fragtimeout++);
464
 
                        ip_freef((struct ipq *) fp->prev);
 
485
                        ip_freef(fp);
465
486
                }
466
487
        }
467
488
}