~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to slirp/ip_input.c

  • Committer: blueswir1
  • Date: 2009-01-13 19:48:42 UTC
  • Revision ID: git-v1:429d0a3db8138ae6a545500b92dbe532629a24e1
Fix 64 bit issue in slirp

Signed-off-by: Gleb Natapov <gleb@redhat.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6288 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
 */
44
44
 
45
45
#include <slirp.h>
 
46
#include <osdep.h>
46
47
#include "ip_icmp.h"
47
48
 
48
49
#ifdef LOG_ENABLED
51
52
 
52
53
struct ipq ipq;
53
54
 
54
 
static struct ip *ip_reass(register struct ipasfrag *ip,
 
55
static struct ip *ip_reass(register struct ip *ip,
55
56
                           register struct ipq *fp);
56
57
static void ip_freef(struct ipq *fp);
57
58
static void ip_enq(register struct ipasfrag *p,
65
66
void
66
67
ip_init()
67
68
{
68
 
        ipq.next = ipq.prev = (ipqp_32)&ipq;
 
69
        ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
69
70
        ip_id = tt.tv_sec & 0xffff;
70
71
        udp_init();
71
72
        tcp_init();
188
189
         */
189
190
        if (ip->ip_off &~ IP_DF) {
190
191
          register struct ipq *fp;
 
192
      struct qlink *l;
191
193
                /*
192
194
                 * Look for queue of fragments
193
195
                 * of this datagram.
194
196
                 */
195
 
                for (fp = (struct ipq *) ipq.next; fp != &ipq;
196
 
                     fp = (struct ipq *) fp->next)
197
 
                  if (ip->ip_id == fp->ipq_id &&
198
 
                      ip->ip_src.s_addr == fp->ipq_src.s_addr &&
199
 
                      ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
200
 
                      ip->ip_p == fp->ipq_p)
 
197
                for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
 
198
            fp = container_of(l, struct ipq, ip_link);
 
199
            if (ip->ip_id == fp->ipq_id &&
 
200
                    ip->ip_src.s_addr == fp->ipq_src.s_addr &&
 
201
                    ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
 
202
                    ip->ip_p == fp->ipq_p)
201
203
                    goto found;
202
 
                fp = 0;
 
204
        }
 
205
        fp = NULL;
203
206
        found:
204
207
 
205
208
                /*
209
212
                 */
210
213
                ip->ip_len -= hlen;
211
214
                if (ip->ip_off & IP_MF)
212
 
                  ((struct ipasfrag *)ip)->ipf_mff |= 1;
 
215
                  ip->ip_tos |= 1;
213
216
                else
214
 
                  ((struct ipasfrag *)ip)->ipf_mff &= ~1;
 
217
                  ip->ip_tos &= ~1;
215
218
 
216
219
                ip->ip_off <<= 3;
217
220
 
220
223
                 * or if this is not the first fragment,
221
224
                 * attempt reassembly; if it succeeds, proceed.
222
225
                 */
223
 
                if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
 
226
                if (ip->ip_tos & 1 || ip->ip_off) {
224
227
                        STAT(ipstat.ips_fragments++);
225
 
                        ip = ip_reass((struct ipasfrag *)ip, fp);
 
228
                        ip = ip_reass(ip, fp);
226
229
                        if (ip == 0)
227
230
                                return;
228
231
                        STAT(ipstat.ips_reassembled++);
258
261
        return;
259
262
}
260
263
 
 
264
#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
 
265
#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))
261
266
/*
262
267
 * Take incoming datagram fragment and try to
263
268
 * reassemble it into whole datagram.  If a chain for
265
270
 * is given as fp; otherwise have to make a chain.
266
271
 */
267
272
static struct ip *
268
 
ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
 
273
ip_reass(register struct ip *ip, register struct ipq *fp)
269
274
{
270
275
        register struct mbuf *m = dtom(ip);
271
276
        register struct ipasfrag *q;
292
297
          struct mbuf *t;
293
298
          if ((t = m_get()) == NULL) goto dropfrag;
294
299
          fp = mtod(t, struct ipq *);
295
 
          insque_32(fp, &ipq);
 
300
          insque(&fp->ip_link, &ipq.ip_link);
296
301
          fp->ipq_ttl = IPFRAGTTL;
297
302
          fp->ipq_p = ip->ip_p;
298
303
          fp->ipq_id = ip->ip_id;
299
 
          fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
300
 
          fp->ipq_src = ((struct ip *)ip)->ip_src;
301
 
          fp->ipq_dst = ((struct ip *)ip)->ip_dst;
 
304
          fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
 
305
          fp->ipq_src = ip->ip_src;
 
306
          fp->ipq_dst = ip->ip_dst;
302
307
          q = (struct ipasfrag *)fp;
303
308
          goto insert;
304
309
        }
306
311
        /*
307
312
         * Find a segment which begins after this one does.
308
313
         */
309
 
        for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
310
 
            q = (struct ipasfrag *)q->ipf_next)
311
 
                if (q->ip_off > ip->ip_off)
 
314
        for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
 
315
            q = q->ipf_next)
 
316
                if (q->ipf_off > ip->ip_off)
312
317
                        break;
313
318
 
314
319
        /*
316
321
         * our data already.  If so, drop the data from the incoming
317
322
         * segment.  If it provides all of our data, drop us.
318
323
         */
319
 
        if (q->ipf_prev != (ipasfragp_32)fp) {
320
 
                i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
321
 
                  ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
 
324
        if (q->ipf_prev != &fp->frag_link) {
 
325
        struct ipasfrag *pq = q->ipf_prev;
 
326
                i = pq->ipf_off + pq->ipf_len - ip->ip_off;
322
327
                if (i > 0) {
323
328
                        if (i >= ip->ip_len)
324
329
                                goto dropfrag;
332
337
         * While we overlap succeeding segments trim them or,
333
338
         * if they are completely covered, dequeue them.
334
339
         */
335
 
        while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
336
 
                i = (ip->ip_off + ip->ip_len) - q->ip_off;
337
 
                if (i < q->ip_len) {
338
 
                        q->ip_len -= i;
339
 
                        q->ip_off += i;
 
340
        while (q != (struct ipasfrag*)&fp->frag_link &&
 
341
            ip->ip_off + ip->ip_len > q->ipf_off) {
 
342
                i = (ip->ip_off + ip->ip_len) - q->ipf_off;
 
343
                if (i < q->ipf_len) {
 
344
                        q->ipf_len -= i;
 
345
                        q->ipf_off += i;
340
346
                        m_adj(dtom(q), i);
341
347
                        break;
342
348
                }
343
 
                q = (struct ipasfrag *) q->ipf_next;
344
 
                m_freem(dtom((struct ipasfrag *) q->ipf_prev));
345
 
                ip_deq((struct ipasfrag *) q->ipf_prev);
 
349
                q = q->ipf_next;
 
350
                m_freem(dtom(q->ipf_prev));
 
351
                ip_deq(q->ipf_prev);
346
352
        }
347
353
 
348
354
insert:
350
356
         * Stick new segment in its place;
351
357
         * check for complete reassembly.
352
358
         */
353
 
        ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
 
359
        ip_enq(iptofrag(ip), q->ipf_prev);
354
360
        next = 0;
355
 
        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
356
 
             q = (struct ipasfrag *) q->ipf_next) {
357
 
                if (q->ip_off != next)
 
361
        for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
 
362
            q = q->ipf_next) {
 
363
                if (q->ipf_off != next)
358
364
                        return (0);
359
 
                next += q->ip_len;
 
365
                next += q->ipf_len;
360
366
        }
361
 
        if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
 
367
        if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
362
368
                return (0);
363
369
 
364
370
        /*
365
371
         * Reassembly is complete; concatenate fragments.
366
372
         */
367
 
        q = (struct ipasfrag *) fp->ipq_next;
 
373
    q = fp->frag_link.next;
368
374
        m = dtom(q);
369
375
 
370
376
        q = (struct ipasfrag *) q->ipf_next;
371
 
        while (q != (struct ipasfrag *)fp) {
372
 
          struct mbuf *t;
373
 
          t = dtom(q);
 
377
        while (q != (struct ipasfrag*)&fp->frag_link) {
 
378
          struct mbuf *t = dtom(q);
374
379
          q = (struct ipasfrag *) q->ipf_next;
375
380
          m_cat(m, t);
376
381
        }
381
386
         * dequeue and discard fragment reassembly header.
382
387
         * Make header visible.
383
388
         */
384
 
        ip = (struct ipasfrag *) fp->ipq_next;
 
389
        q = fp->frag_link.next;
385
390
 
386
391
        /*
387
392
         * If the fragments concatenated to an mbuf that's
393
398
        if (m->m_flags & M_EXT) {
394
399
          int delta;
395
400
          delta = (char *)ip - m->m_dat;
396
 
          ip = (struct ipasfrag *)(m->m_ext + delta);
 
401
          q = (struct ipasfrag *)(m->m_ext + delta);
397
402
        }
398
403
 
399
404
        /* DEBUG_ARG("ip = %lx", (long)ip);
400
405
         * ip=(struct ipasfrag *)m->m_data; */
401
406
 
 
407
    ip = fragtoip(q);
402
408
        ip->ip_len = next;
403
 
        ip->ipf_mff &= ~1;
404
 
        ((struct ip *)ip)->ip_src = fp->ipq_src;
405
 
        ((struct ip *)ip)->ip_dst = fp->ipq_dst;
406
 
        remque_32(fp);
 
409
        ip->ip_tos &= ~1;
 
410
        ip->ip_src = fp->ipq_src;
 
411
        ip->ip_dst = fp->ipq_dst;
 
412
        remque(&fp->ip_link);
407
413
        (void) m_free(dtom(fp));
408
 
        m = dtom(ip);
409
414
        m->m_len += (ip->ip_hl << 2);
410
415
        m->m_data -= (ip->ip_hl << 2);
411
416
 
412
 
        return ((struct ip *)ip);
 
417
        return ip;
413
418
 
414
419
dropfrag:
415
420
        STAT(ipstat.ips_fragdropped++);
426
431
{
427
432
        register struct ipasfrag *q, *p;
428
433
 
429
 
        for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
430
 
            q = p) {
431
 
                p = (struct ipasfrag *) q->ipf_next;
 
434
        for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
 
435
                p = q->ipf_next;
432
436
                ip_deq(q);
433
437
                m_freem(dtom(q));
434
438
        }
435
 
        remque_32(fp);
 
439
        remque(&fp->ip_link);
436
440
        (void) m_free(dtom(fp));
437
441
}
438
442
 
445
449
{
446
450
        DEBUG_CALL("ip_enq");
447
451
        DEBUG_ARG("prev = %lx", (long)prev);
448
 
        p->ipf_prev = (ipasfragp_32) prev;
 
452
        p->ipf_prev =  prev;
449
453
        p->ipf_next = prev->ipf_next;
450
 
        ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
451
 
        prev->ipf_next = (ipasfragp_32) p;
 
454
        ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
 
455
        prev->ipf_next = p;
452
456
}
453
457
 
454
458
/*
469
473
void
470
474
ip_slowtimo()
471
475
{
472
 
        register struct ipq *fp;
 
476
    struct qlink *l;
473
477
 
474
478
        DEBUG_CALL("ip_slowtimo");
475
479
 
476
 
        fp = (struct ipq *) ipq.next;
477
 
        if (fp == 0)
 
480
    l = ipq.ip_link.next;
 
481
 
 
482
        if (l == 0)
478
483
           return;
479
484
 
480
 
        while (fp != &ipq) {
481
 
                --fp->ipq_ttl;
482
 
                fp = (struct ipq *) fp->next;
483
 
                if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
 
485
        while (l != &ipq.ip_link) {
 
486
        struct ipq *fp = container_of(l, struct ipq, ip_link);
 
487
        l = l->next;
 
488
                if (--fp->ipq_ttl == 0) {
484
489
                        STAT(ipstat.ips_fragtimeout++);
485
 
                        ip_freef((struct ipq *) fp->prev);
 
490
                        ip_freef(fp);
486
491
                }
487
492
        }
488
493
}