]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/tcpip/v2_0/src/sys/kern/uipc_mbuf.c
Initial revision
[karo-tx-redboot.git] / packages / net / tcpip / v2_0 / src / sys / kern / uipc_mbuf.c
1 //==========================================================================
2 //
3 //      sys/kern/uipc_mbuf.c
4 //
5 //     
6 //
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 //
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
14 //
15 // -------------------------------------------
16 //
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
20 //
21 // Author(s):    gthomas
22 // Contributors: gthomas
23 // Date:         2000-01-10
24 // Purpose:      
25 // Description:  
26 //              
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32
33 /*      $OpenBSD: uipc_mbuf.c,v 1.18 1999/12/05 07:30:31 angelos Exp $  */
34 /*      $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $   */
35
36 /*
37  * Copyright (c) 1982, 1986, 1988, 1991, 1993
38  *      The Regents of the University of California.  All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. All advertising materials mentioning features or use of this software
49  *    must display the following acknowledgement:
50  *      This product includes software developed by the University of
51  *      California, Berkeley and its contributors.
52  * 4. Neither the name of the University nor the names of its contributors
53  *    may be used to endorse or promote products derived from this software
54  *    without specific prior written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66  * SUCH DAMAGE.
67  *
68  *      @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
69  */
70
71 /*
72 %%% portions-copyright-nrl-95
73 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
74 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
75 Reserved. All rights under this copyright have been assigned to the US
76 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
77 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
78 software.
79 You should have received a copy of the license with this software. If you
80 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
81 */
82
83 #include <sys/param.h>
84 #ifndef __ECOS
85 #include <sys/systm.h>
86 #include <sys/proc.h>
87 #endif
88 #include <sys/malloc.h>
89 #ifndef __ECOS
90 #include <sys/map.h>
91 #endif
92 #define MBTYPES
93 #include <sys/mbuf.h>
94 #include <sys/kernel.h>
95 #ifndef __ECOS
96 #include <sys/syslog.h>
97 #endif
98 #include <sys/domain.h>
99 #include <sys/protosw.h>
100
101 #include <machine/cpu.h>
102
103 #ifndef __ECOS
104 #include <vm/vm.h>
105 #endif
106
107 #if defined(UVM)
108 #include <uvm/uvm_extern.h>
109 #endif
110
111 #ifndef __ECOS
112 extern  vm_map_t mb_map;
113 #endif
114 struct  mbuf *mbutl;
115 char    *mclrefcnt;
116 int     needqueuedrain;
117
118 #ifdef __ECOS
119 extern void setsoftnet(void);
120 extern void *cyg_net_cluster_alloc(void);
121 #endif
122
123 /* Declarations of variables move from mbuf.h to keep g++ happy */
124 #ifdef __ECOS
125 struct mbstat mbstat;
126 union  mcluster *mclfree;
127 int    max_linkhdr;                    /* largest link-level header */
128 int    max_protohdr;                   /* largest protocol header */
129 int    max_hdr;                        /* largest link+protocol header */
130 int    max_datalen;                    /* MHLEN - max_hdr */
131 #ifdef MBTYPES
132 int mbtypes[] = {                              /* XXX */
133        M_FREE,         /* MT_FREE      0          should be on free list */
134        M_MBUF,         /* MT_DATA      1          dynamic (data) allocation */
135        M_MBUF,         /* MT_HEADER    2          packet header */
136        M_SOCKET,       /* MT_SOCKET    3          socket structure */
137        M_PCB,          /* MT_PCB       4          protocol control block */
138        M_RTABLE,       /* MT_RTABLE    5          routing tables */
139        M_HTABLE,       /* MT_HTABLE    6          IMP host tables */
140        0,              /* MT_ATABLE    7          address resolution tables */
141        M_MBUF,         /* MT_SONAME    8          socket name */
142        0,              /*              9 */
143        M_SOOPTS,       /* MT_SOOPTS    10         socket options */
144        M_FTABLE,       /* MT_FTABLE    11         fragment reassembly header */
145        M_MBUF,         /* MT_RIGHTS    12         access rights */
146        M_IFADDR,       /* MT_IFADDR    13         interface address */
147        M_MBUF,         /* MT_CONTROL   14         extra-data protocol message */
148        M_MBUF,         /* MT_OOBDATA   15         expedited data  */
149 #ifdef DATAKIT
150        25, 26, 27, 28, 29, 30, 31, 32          /* datakit ugliness */
151 #endif
152 };
153 #endif
154 #endif // __ECOS
155
156 void
157 mbinit()
158 {
159         int s;
160
161         s = splimp();
162 #ifdef __ECOS
163         if (m_clalloc(1, M_DONTWAIT) == 0)
164 #else
165         if (m_clalloc(max(4096 / CLBYTES, 1), M_DONTWAIT) == 0)
166 #endif
167                 goto bad;
168         splx(s);
169         return;
170 bad:
171         panic("mbinit");
172 }
173
174 /*
175  * Allocate some number of mbuf clusters
176  * and place on cluster free list.
177  * Must be called at splimp.
178  */
179 /* ARGSUSED */
180 int
181 m_clalloc(ncl, nowait)
182         register int ncl;
183         int nowait;
184 {
185 #ifdef __ECOS
186         caddr_t p;
187         int i;
188
189         if (ncl != 1) {
190             panic("Allocate multiple clusters!");
191         }
192         p = (caddr_t)cyg_net_cluster_alloc();
193         if (p == NULL) {
194                 m_reclaim();
195                 return (mclfree != NULL);
196         }
197         for (i = 0; i < ncl; i++) {
198                 ((union mcluster *)p)->mcl_next = mclfree;
199                 mclfree = (union mcluster *)p;
200                 p += MCLBYTES;
201                 mbstat.m_clfree++;
202         }
203         mbstat.m_clusters += ncl;
204         return (1);
205 #else // __ECOS
206         volatile static struct timeval lastlogged;
207         struct timeval curtime, logdiff;
208         register caddr_t p;
209         register int i;
210         int npg, s;
211
212         npg = ncl * CLSIZE;
213 #if defined(UVM)
214         p = (caddr_t)uvm_km_kmemalloc(mb_map, uvmexp.mb_object, ctob(npg),
215             nowait ? 0 : UVM_KMF_NOWAIT);
216 #else
217         p = (caddr_t)kmem_malloc(mb_map, ctob(npg), !nowait);
218 #endif
219         if (p == NULL) {
220                 s = splclock();
221                 curtime = time;
222                 splx(s);
223                 timersub(&curtime, &lastlogged, &logdiff);
224                 if (logdiff.tv_sec >= 60) {
225                         lastlogged = curtime;
226                         log(LOG_ERR, "mb_map full\n");
227                 }
228                 m_reclaim();
229                 return (mclfree != NULL);
230         }
231         ncl = ncl * CLBYTES / MCLBYTES;
232         for (i = 0; i < ncl; i++) {
233                 ((union mcluster *)p)->mcl_next = mclfree;
234                 mclfree = (union mcluster *)p;
235                 p += MCLBYTES;
236                 mbstat.m_clfree++;
237         }
238         mbstat.m_clusters += ncl;
239         return (1);
240 #endif // __ECOS
241 }
242
243 /*
244  * When MGET failes, ask protocols to free space when short of memory,
245  * then re-attempt to allocate an mbuf.
246  */
247 struct mbuf *
248 m_retry(i, t)
249         int i, t;
250 {
251         register struct mbuf *m;
252
253         if (i & M_DONTWAIT) {
254                 needqueuedrain = 1;
255                 setsoftnet();
256                 return (NULL);
257         }
258         m_reclaim();
259 #define m_retry(i, t)   NULL
260         MGET(m, i, t);
261 #undef m_retry
262         return (m);
263 }
264
265 /*
266  * As above; retry an MGETHDR.
267  */
268 struct mbuf *
269 m_retryhdr(i, t)
270         int i, t;
271 {
272         register struct mbuf *m;
273
274         if (i & M_DONTWAIT) {
275                 needqueuedrain = 1;
276                 setsoftnet();
277                 return (NULL);
278         }
279         m_reclaim();
280 #define m_retryhdr(i, t) NULL
281         MGETHDR(m, i, t);
282 #undef m_retryhdr
283         return (m);
284 }
285
286 void
287 m_reclaim()
288 {
289         register struct domain *dp;
290         register struct protosw *pr;
291         int s = splimp();
292
293         needqueuedrain = 0;
294         for (dp = domains; dp; dp = dp->dom_next)
295                 for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
296                         if (pr->pr_drain)
297                                 (*pr->pr_drain)();
298         splx(s);
299         mbstat.m_drain++;
300 }
301
302 /*
303  * Space allocation routines.
304  * These are also available as macros
305  * for critical paths.
306  */
307 struct mbuf *
308 m_get(nowait, type)
309         int nowait, type;
310 {
311         register struct mbuf *m;
312
313         MGET(m, nowait, type);
314         return (m);
315 }
316
317 struct mbuf *
318 m_gethdr(nowait, type)
319         int nowait, type;
320 {
321         register struct mbuf *m;
322
323         MGETHDR(m, nowait, type);
324         return (m);
325 }
326
327 struct mbuf *
328 m_getclr(nowait, type)
329         int nowait, type;
330 {
331         register struct mbuf *m;
332
333         MGET(m, nowait, type);
334         if (m == NULL)
335                 return (NULL);
336         bzero(mtod(m, caddr_t), MLEN);
337         return (m);
338 }
339
340 struct mbuf *
341 m_free(m)
342         struct mbuf *m;
343 {
344         register struct mbuf *n;
345
346         MFREE(m, n);
347         return (n);
348 }
349
350 void
351 m_freem(m)
352         register struct mbuf *m;
353 {
354         register struct mbuf *n;
355
356         if (m == NULL)
357                 return;
358         do {
359                 MFREE(m, n);
360         } while ((m = n) != NULL);
361 }
362
363 /*
364  * Mbuffer utility routines.
365  */
366
367 /*
368  * Lesser-used path for M_PREPEND:
369  * allocate new mbuf to prepend to chain,
370  * copy junk along.
371  */
372 struct mbuf *
373 m_prepend(m, len, how)
374         register struct mbuf *m;
375         int len, how;
376 {
377         struct mbuf *mn;
378
379         MGET(mn, how, m->m_type);
380         if (mn == NULL) {
381                 m_freem(m);
382                 return (NULL);
383         }
384         if (m->m_flags & M_PKTHDR) {
385                 M_COPY_PKTHDR(mn, m);
386                 m->m_flags &= ~M_PKTHDR;
387         }
388         mn->m_next = m;
389         m = mn;
390         if (len < MHLEN)
391                 MH_ALIGN(m, len);
392         m->m_len = len;
393         return (m);
394 }
395
396 /*
397  * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
398  * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
399  * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
400  */
401 int MCFail;
402
403 struct mbuf *
404 m_copym(m, off0, len, wait)
405         register struct mbuf *m;
406         int off0, wait;
407         register int len;
408 {
409         register struct mbuf *n, **np;
410         register int off = off0;
411         struct mbuf *top;
412         int copyhdr = 0;
413
414         if (off < 0)
415                 panic("m_copym: off %d < 0", off);
416         if (len < 0)
417                 panic("m_copym: len %d < 0", len);
418         if (off == 0 && m->m_flags & M_PKTHDR)
419                 copyhdr = 1;
420         while (off > 0) {
421                 if (m == NULL)
422                         panic("m_copym: null mbuf");
423                 if (off < m->m_len)
424                         break;
425                 off -= m->m_len;
426                 m = m->m_next;
427         }
428         np = &top;
429         top = NULL;
430         while (len > 0) {
431                 if (m == NULL) {
432                         if (len != M_COPYALL)
433                                 panic("m_copym: %d not M_COPYALL", len);
434                         break;
435                 }
436                 MGET(n, wait, m->m_type);
437                 *np = n;
438                 if (n == NULL)
439                         goto nospace;
440                 if (copyhdr) {
441                         M_COPY_PKTHDR(n, m);
442                         if (len == M_COPYALL)
443                                 n->m_pkthdr.len -= off0;
444                         else
445                                 n->m_pkthdr.len = len;
446                         copyhdr = 0;
447                 }
448                 n->m_len = min(len, m->m_len - off);
449                 if (m->m_flags & M_EXT) {
450                         n->m_data = m->m_data + off;
451                         if (!m->m_ext.ext_ref)
452                                 mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
453                         else
454                                 (*(m->m_ext.ext_ref))(m);
455                         n->m_ext = m->m_ext;
456                         n->m_flags |= M_EXT;
457                 } else
458                         bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
459                             (unsigned)n->m_len);
460                 if (len != M_COPYALL)
461                         len -= n->m_len;
462                 off = 0;
463                 m = m->m_next;
464                 np = &n->m_next;
465         }
466         if (top == NULL)
467                 MCFail++;
468         return (top);
469 nospace:
470         m_freem(top);
471         MCFail++;
472         return (NULL);
473 }
474
475 /*
476  * m_copym2() is like m_copym(), except it COPIES cluster mbufs, instead
477  * of merely bumping the reference count.
478  */
479 struct mbuf *
480 m_copym2(m, off0, len, wait)
481         register struct mbuf *m;
482         int off0, wait;
483         register int len;
484 {
485         register struct mbuf *n, **np;
486         register int off = off0;
487         struct mbuf *top;
488         int copyhdr = 0;
489
490         if (len < 0)
491                 panic("m_copym2: len %d < 0", len);
492         if (off < 0)
493                 panic("m_copym2: off %d < 0", off);
494         if (off == 0 && m->m_flags & M_PKTHDR)
495                 copyhdr = 1;
496         while (off > 0) {
497                 if (m == NULL)
498                         panic("m_copym2: null mbuf");
499                 if (off < m->m_len)
500                         break;
501                 off -= m->m_len;
502                 m = m->m_next;
503         }
504         np = &top;
505         top = NULL;
506         while (len > 0) {
507                 if (m == NULL) {
508                         if (len != M_COPYALL)
509                                 panic("m_copym2: %d != M_COPYALL", len);
510                         break;
511                 }
512                 MGET(n, wait, m->m_type);
513                 *np = n;
514                 if (n == NULL)
515                         goto nospace;
516                 if (copyhdr) {
517                         M_COPY_PKTHDR(n, m);
518                         if (len == M_COPYALL)
519                                 n->m_pkthdr.len -= off0;
520                         else
521                                 n->m_pkthdr.len = len;
522                         copyhdr = 0;
523                 }
524                 n->m_len = min(len, m->m_len - off);
525                 if ((m->m_flags & M_EXT) && (n->m_len > MHLEN)) {
526                         /* This is a cheesy hack. */
527                         MCLGET(n, wait);
528                         if (n->m_flags & M_EXT)
529                                 bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t),
530                                     (unsigned)n->m_len);
531                         else
532                                 goto nospace;
533                 } else
534                         bcopy(mtod(m, caddr_t) + off, mtod(n, caddr_t),
535                             (unsigned)n->m_len);
536                 if (len != M_COPYALL)
537                         len -= n->m_len;
538                 off = 0;
539                 m = m->m_next;
540                 np = &n->m_next;
541         }
542         if (top == NULL)
543                 MCFail++;
544         return (top);
545 nospace:
546         m_freem(top);
547         MCFail++;
548         return (NULL);
549 }
550
551 /*
552  * Copy data from an mbuf chain starting "off" bytes from the beginning,
553  * continuing for "len" bytes, into the indicated buffer.
554  */
555 void
556 m_copydata(m, off, len, cp)
557         register struct mbuf *m;
558         register int off;
559         register int len;
560         caddr_t cp;
561 {
562         register unsigned count;
563
564         if (off < 0)
565                 panic("m_copydata: off %d < 0", off);
566         if (len < 0)
567                 panic("m_copydata: len %d < 0", len);
568         while (off > 0) {
569                 if (m == NULL)
570                         panic("m_copydata: null mbuf in skip");
571                 if (off < m->m_len)
572                         break;
573                 off -= m->m_len;
574                 m = m->m_next;
575         }
576         while (len > 0) {
577                 if (m == NULL)
578                         panic("m_copydata: null mbuf");
579                 count = min(m->m_len - off, len);
580                 bcopy(mtod(m, caddr_t) + off, cp, count);
581                 len -= count;
582                 cp += count;
583                 off = 0;
584                 m = m->m_next;
585         }
586 }
587
588 /*
589  * Concatenate mbuf chain n to m.
590  * Both chains must be of the same type (e.g. MT_DATA).
591  * Any m_pkthdr is not updated.
592  */
593 void
594 m_cat(m, n)
595         register struct mbuf *m, *n;
596 {
597         while (m->m_next)
598                 m = m->m_next;
599         while (n) {
600                 if (m->m_flags & M_EXT ||
601                     m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
602                         /* just join the two chains */
603                         m->m_next = n;
604                         return;
605                 }
606                 /* splat the data from one into the other */
607                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
608                     (u_int)n->m_len);
609                 m->m_len += n->m_len;
610                 n = m_free(n);
611         }
612 }
613
614 void
615 m_adj(mp, req_len)
616         struct mbuf *mp;
617         int req_len;
618 {
619         register int len = req_len;
620         register struct mbuf *m;
621         register int count;
622
623         if ((m = mp) == NULL)
624                 return;
625         if (len >= 0) {
626                 /*
627                  * Trim from head.
628                  */
629                 while (m != NULL && len > 0) {
630                         if (m->m_len <= len) {
631                                 len -= m->m_len;
632                                 m->m_len = 0;
633                                 m = m->m_next;
634                         } else {
635                                 m->m_len -= len;
636                                 m->m_data += len;
637                                 len = 0;
638                         }
639                 }
640                 m = mp;
641                 if (mp->m_flags & M_PKTHDR)
642                         m->m_pkthdr.len -= (req_len - len);
643         } else {
644                 /*
645                  * Trim from tail.  Scan the mbuf chain,
646                  * calculating its length and finding the last mbuf.
647                  * If the adjustment only affects this mbuf, then just
648                  * adjust and return.  Otherwise, rescan and truncate
649                  * after the remaining size.
650                  */
651                 len = -len;
652                 count = 0;
653                 for (;;) {
654                         count += m->m_len;
655                         if (m->m_next == NULL)
656                                 break;
657                         m = m->m_next;
658                 }
659                 if (m->m_len >= len) {
660                         m->m_len -= len;
661                         if (mp->m_flags & M_PKTHDR)
662                                 mp->m_pkthdr.len -= len;
663                         return;
664                 }
665                 count -= len;
666                 if (count < 0)
667                         count = 0;
668                 /*
669                  * Correct length for chain is "count".
670                  * Find the mbuf with last data, adjust its length,
671                  * and toss data from remaining mbufs on chain.
672                  */
673                 m = mp;
674                 if (m->m_flags & M_PKTHDR)
675                         m->m_pkthdr.len = count;
676                 for (; m; m = m->m_next) {
677                         if (m->m_len >= count) {
678                                 m->m_len = count;
679                                 break;
680                         }
681                         count -= m->m_len;
682                 }
683                 while ((m = m->m_next) != NULL)
684                         m->m_len = 0;
685         }
686 }
687
688 /*
689  * Rearange an mbuf chain so that len bytes are contiguous
690  * and in the data area of an mbuf (so that mtod and dtom
691  * will work for a structure of size len).  Returns the resulting
692  * mbuf chain on success, frees it and returns null on failure.
693  * If there is room, it will add up to max_protohdr-len extra bytes to the
694  * contiguous region in an attempt to avoid being called next time.
695  */
696 int MPFail;
697
698 struct mbuf *
699 m_pullup(n, len)
700         register struct mbuf *n;
701         int len;
702 {
703         register struct mbuf *m;
704         register int count;
705         int space;
706
707         /*
708          * If first mbuf has no cluster, and has room for len bytes
709          * without shifting current data, pullup into it,
710          * otherwise allocate a new mbuf to prepend to the chain.
711          */
712         if ((n->m_flags & M_EXT) == 0 &&
713             n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
714                 if (n->m_len >= len)
715                         return (n);
716                 m = n;
717                 n = n->m_next;
718                 len -= m->m_len;
719         } else {
720                 if (len > MHLEN)
721                         goto bad;
722                 MGET(m, M_DONTWAIT, n->m_type);
723                 if (m == NULL)
724                         goto bad;
725                 m->m_len = 0;
726                 if (n->m_flags & M_PKTHDR) {
727                         M_COPY_PKTHDR(m, n);
728                         n->m_flags &= ~M_PKTHDR;
729                 }
730         }
731         space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
732         do {
733                 count = min(min(max(len, max_protohdr), space), n->m_len);
734                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
735                     (unsigned)count);
736                 len -= count;
737                 m->m_len += count;
738                 n->m_len -= count;
739                 space -= count;
740                 if (n->m_len)
741                         n->m_data += count;
742                 else
743                         n = m_free(n);
744         } while (len > 0 && n);
745         if (len > 0) {
746                 (void)m_free(m);
747                 goto bad;
748         }
749         m->m_next = n;
750         return (m);
751 bad:
752         m_freem(n);
753         MPFail++;
754         return (NULL);
755 }
756
757 /*
758  * m_pullup2() works like m_pullup, save that len can be <= MCLBYTES.
759  * m_pullup2() only works on values of len such that MHLEN < len <= MCLBYTES,
760  * it calls m_pullup() for values <= MHLEN.  It also only coagulates the
761  * reqested number of bytes.  (For those of us who expect unwieldly option
762  * headers.     
763  *                    
764  * KEBE SAYS:  Remember that dtom() calls with data in clusters does not work!
765  */
766 struct mbuf *   
767 m_pullup2(n, len)       
768         register struct mbuf *n;
769         int len;
770 {
771         register struct mbuf *m;
772         register int count;
773         int space; 
774         if (len <= MHLEN)
775                 return m_pullup(n, len);
776  
777         if ((n->m_flags & M_EXT) != 0 &&
778             n->m_data + len < &n->m_data[MCLBYTES] && n->m_next) {
779                 if (n->m_len >= len)
780                         return (n);
781                 m = n;
782                 n = n->m_next;
783                 len -= m->m_len;
784         } else {
785                 if (len > MCLBYTES)
786                         goto bad;
787                 MGET(m, M_DONTWAIT, n->m_type);
788                 if (m == NULL)
789                         goto bad; 
790                 MCLGET(m, M_DONTWAIT);
791                 if ((m->m_flags & M_EXT) == 0)
792                         goto bad;
793                 m->m_len = 0;
794                 if (n->m_flags & M_PKTHDR) {
795                         /* M_COPY_PKTHDR(m, n);*//* Too many adverse side effects. */
796                         m->m_pkthdr = n->m_pkthdr;
797                         m->m_flags = (n->m_flags & M_COPYFLAGS) | M_EXT;
798                         n->m_flags &= ~M_PKTHDR;
799                         /* n->m_data is cool. */
800                 }
801         }
802
803         do {
804                 count = min(len, n->m_len);
805                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
806                     (unsigned)count);
807                 len -= count;
808                 m->m_len += count;
809                 n->m_len -= count;
810                 space -= count;
811                 if (n->m_len)
812                         n->m_data += count;
813                 else
814                         n = m_free(n);
815         } while (len > 0 && n);
816         if (len > 0) {
817                 (void)m_free(m);
818                 goto bad;
819         }        
820         m->m_next = n;
821                 
822         return (m);
823 bad:        
824         m_freem(n);
825         MPFail++;
826         return (NULL);
827 }
828
829 /*
830  * Inject a new mbuf chain of length siz in mbuf chain m0 at
831  * position len0. Returns a pointer to the first injected mbuf, or
832  * NULL on failure (m0 is left undisturbed). Note that if there is
833  * enough space for an object of size siz in the appropriate position,
834  * no memory will be allocated. Also, there will be no data movement in
835  * the first len0 bytes (pointers to that will remain valid).
836  *
837  * XXX It is assumed that siz is less than the size of an mbuf at the moment.
838  */
839 struct mbuf *
840 m_inject(m0, len0, siz, wait)
841         register struct mbuf *m0;
842         int len0, siz, wait;
843 {
844         register struct mbuf *m, *n, *n2 = NULL, *n3;
845         unsigned len = len0, remain;
846
847         if ((siz >= MHLEN) || (len0 <= 0))
848                 return (NULL);
849         for (m = m0; m && len > m->m_len; m = m->m_next)
850                 len -= m->m_len;
851         if (m == NULL)
852                 return (NULL);
853         remain = m->m_len - len;
854         if (remain == 0) {
855                 if ((m->m_next) &&  (M_LEADINGSPACE(m->m_next) >= siz)) {
856                         m->m_next->m_len += siz;
857                         m0->m_pkthdr.len += siz;
858                         m->m_next->m_data -= siz;
859                         return m->m_next;
860                 }
861         } else {
862                 n2 = m_copym2(m, len, remain, wait);
863                 if (n2 == NULL)
864                         return (NULL);
865         }
866
867         MGET(n, wait, MT_DATA);
868         if (n == NULL) {
869                 if (n2)
870                         m_freem(n2);
871                 return (NULL);
872         }
873
874         n->m_len = siz;
875         m0->m_pkthdr.len += siz;
876         m->m_len -= remain; /* Trim */
877         if (n2) {
878                 for (n3 = n; n3->m_next != NULL; n3 = n3->m_next)
879                         ;
880                 n3->m_next = n2;
881         } else
882                 n3 = n;
883         for (; n3->m_next != NULL; n3 = n3->m_next)
884                 ;
885         n3->m_next = m->m_next;
886         m->m_next = n;
887         return n;
888 }
889
890 /*
891  * Partition an mbuf chain in two pieces, returning the tail --
892  * all but the first len0 bytes.  In case of failure, it returns NULL and
893  * attempts to restore the chain to its original state.
894  */
895 struct mbuf *
896 m_split(m0, len0, wait)
897         register struct mbuf *m0;
898         int len0, wait;
899 {
900         register struct mbuf *m, *n;
901         unsigned len = len0, remain, olen;
902
903         for (m = m0; m && len > m->m_len; m = m->m_next)
904                 len -= m->m_len;
905         if (m == NULL)
906                 return (NULL);
907         remain = m->m_len - len;
908         if (m0->m_flags & M_PKTHDR) {
909                 MGETHDR(n, wait, m0->m_type);
910                 if (n == NULL)
911                         return (NULL);
912                 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
913                 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
914                 olen = m0->m_pkthdr.len;
915                 m0->m_pkthdr.len = len0;
916                 if (m->m_flags & M_EXT)
917                         goto extpacket;
918                 if (remain > MHLEN) {
919                         /* m can't be the lead packet */
920                         MH_ALIGN(n, 0);
921                         n->m_next = m_split(m, len, wait);
922                         if (n->m_next == NULL) {
923                                 (void) m_free(n);
924                                 m0->m_pkthdr.len = olen;
925                                 return (NULL);
926                         } else
927                                 return (n);
928                 } else
929                         MH_ALIGN(n, remain);
930         } else if (remain == 0) {
931                 n = m->m_next;
932                 m->m_next = NULL;
933                 return (n);
934         } else {
935                 MGET(n, wait, m->m_type);
936                 if (n == NULL)
937                         return (NULL);
938                 M_ALIGN(n, remain);
939         }
940 extpacket:
941         if (m->m_flags & M_EXT) {
942                 n->m_flags |= M_EXT;
943                 n->m_ext = m->m_ext;
944                 if(!m->m_ext.ext_ref)
945                         mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
946                 else
947                         (*(m->m_ext.ext_ref))(m);
948                 m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
949                 n->m_data = m->m_data + len;
950         } else {
951                 bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
952         }
953         n->m_len = remain;
954         m->m_len = len;
955         n->m_next = m->m_next;
956         m->m_next = NULL;
957         return (n);
958 }
959 /*
960  * Routine to copy from device local memory into mbufs.
961  */
962 struct mbuf *
963 m_devget(buf, totlen, off0, ifp, copy)
964         char *buf;
965         int totlen, off0;
966         struct ifnet *ifp;
967         void (*copy) __P((const void *, void *, size_t));
968 {
969         register struct mbuf *m;
970         struct mbuf *top = NULL, **mp = &top;
971         register int off = off0, len;
972         register char *cp;
973         char *epkt;
974
975         cp = buf;
976         epkt = cp + totlen;
977         if (off) {
978                 /*
979                  * If 'off' is non-zero, packet is trailer-encapsulated,
980                  * so we have to skip the type and length fields.
981                  */
982                 cp += off + 2 * sizeof(u_int16_t);
983                 totlen -= 2 * sizeof(u_int16_t);
984         }
985         MGETHDR(m, M_DONTWAIT, MT_DATA);
986         if (m == NULL)
987                 return (NULL);
988         m->m_pkthdr.rcvif = ifp;
989         m->m_pkthdr.len = totlen;
990         m->m_len = MHLEN;
991
992         while (totlen > 0) {
993                 if (top != NULL) {
994                         MGET(m, M_DONTWAIT, MT_DATA);
995                         if (m == NULL) {
996                                 m_freem(top);
997                                 return (NULL);
998                         }
999                         m->m_len = MLEN;
1000                 }
1001                 len = min(totlen, epkt - cp);
1002                 if (len >= MINCLSIZE) {
1003                         MCLGET(m, M_DONTWAIT);
1004                         if (m->m_flags & M_EXT)
1005                                 m->m_len = len = min(len, MCLBYTES);
1006                         else
1007                                 len = m->m_len;
1008                 } else {
1009                         /*
1010                          * Place initial small packet/header at end of mbuf.
1011                          */
1012                         if (len < m->m_len) {
1013                                 if (top == NULL &&
1014                                     len + max_linkhdr <= m->m_len)
1015                                         m->m_data += max_linkhdr;
1016                                 m->m_len = len;
1017                         } else
1018                                 len = m->m_len;
1019                 }
1020                 if (copy)
1021                         copy(cp, mtod(m, caddr_t), (size_t)len);
1022                 else
1023                         bcopy(cp, mtod(m, caddr_t), (size_t)len);
1024                 cp += len;
1025                 *mp = m;
1026                 mp = &m->m_next;
1027                 totlen -= len;
1028                 if (cp == epkt)
1029                         cp = buf;
1030         }
1031         return (top);
1032 }
1033
1034 void
1035 m_zero(m)
1036         struct mbuf *m;
1037 {
1038     while (m) {
1039         if (m->m_flags & M_PKTHDR)
1040             bzero((unsigned char *)m + sizeof(struct m_hdr) +
1041                   sizeof(struct pkthdr), MHLEN);
1042         else
1043             bzero((unsigned char *)m + sizeof(struct m_hdr), MLEN);
1044         if ((m->m_flags & M_EXT) &&
1045             (m->m_ext.ext_free == NULL) &&
1046             !mclrefcnt[mtocl((m)->m_ext.ext_buf)])
1047             bzero(m->m_ext.ext_buf, m->m_ext.ext_size);
1048         m = m->m_next;
1049     }
1050 }
1051
1052 /*
1053  * Apply function f to the data in an mbuf chain starting "off" bytes from the
1054  * beginning, continuing for "len" bytes.
1055  */
1056 int
1057 m_apply(m, off, len, f, fstate)
1058         struct mbuf *m;
1059         int off;
1060         int len;
1061         /* fstate, data, len */
1062         int (*f)(caddr_t, caddr_t, unsigned int);
1063         caddr_t fstate;
1064 {
1065         int rval;
1066         unsigned int count;
1067
1068         if (len < 0)
1069                 panic("m_apply: len %d < 0", len);
1070         if (off < 0)
1071                 panic("m_apply: off %d < 0", off);
1072         while (off > 0) {
1073                 if (m == NULL)
1074                         panic("m_apply: null mbuf in skip");
1075                 if (off < m->m_len)
1076                         break;
1077                 off -= m->m_len;
1078                 m = m->m_next;
1079         }
1080         while (len > 0) {
1081                 if (m == NULL)
1082                         panic("m_apply: null mbuf");
1083                 count = min(m->m_len - off, len);
1084
1085                 rval = f(fstate, mtod(m, caddr_t) + off, count);
1086                 if (rval)
1087                         return (rval);
1088
1089                 len -= count;
1090                 off = 0;
1091                 m = m->m_next;
1092         }
1093
1094         return (0);
1095 }
1096