1.\" $OpenBSD: mbuf.9,v 1.43 2009/03/02 23:37:08 blambert Exp $ 2.\" 3.\" Copyright (c) 2001 Jean-Jacques Bernard-Gundol <jjbg@openbsd.org> 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 3. The name of the author may not be used to endorse or promote products 15.\" derived from this software without specific prior written permission 16.\" 17.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27.\" 28.Dd $Mdocdate: March 2 2009 $ 29.Dt MBUF 9 30.Os 31.Sh NAME 32.Nm mbuf 33.Nd Kernel memory management for networking protocols 34.Sh SYNOPSIS 35.Fd #include <sys/mbuf.h> 36.Ft struct mbuf * 37.Fn m_copym2 "struct mbuf *m" "int off" "int len" "int wait" 38.Ft struct mbuf * 39.Fn m_copym "struct mbuf *m" "int off" "int len" "int wait" 40.Ft struct mbuf * 41.Fn m_free "struct mbuf *m" 42.Fn MFREE "struct mbuf *m" "struct mbuf *n" 43.Ft struct mbuf * 44.Fn m_get "int how" "int type" 45.Fn MGET "struct mbuf *m" "int how" "int type" 46.Ft struct mbuf * 47.Fn m_getclr "int how" "int type" 48.Ft struct mbuf * 49.Fn m_gethdr "int how" "int type" 50.Fn MGETHDR "struct mbuf *m" "int how" "int type" 51.Ft struct mbuf * 52.Fn m_prepend "struct mbuf *m" "int len" "int how" 53.Fn M_PREPEND "struct mbuf *m" "int plen" "int how" 54.Ft struct mbuf * 55.Fn m_pulldown "struct mbuf *m" "int off" "int len" "int *offp" 56.Ft struct mbuf * 57.Fn m_pullup "struct mbuf *n" "int len" 58.Ft struct mbuf * 59.Fn m_pullup2 "struct mbuf *n" "int len" 60.Ft struct mbuf * 61.Fn m_split "struct mbuf *m0" "int len0" "int wait" 62.Ft struct mbuf * 63.Fn m_inject "struct mbuf *m0" "int len0" "int siz" "int wait" 64.Ft struct mbuf * 65.Fn m_getptr "struct mbuf *m" "int loc" "int *off" 66.Ft void 67.Fn m_adj "struct mbuf *mp" "int req_len" 68.Ft void 69.Fn m_copyback "struct mbuf *m0" "int off" "int len" "caddr_t cp" 70.Ft void 71.Fn m_freem "struct mbuf *m" 72.Ft void 73.Fn m_reclaim "void" 74.Ft void 75.Fn m_copydata "struct mbuf *m" "int off" "int len" "caddr_t cp" 76.Ft void 77.Fn m_cat "struct mbuf *m" "struct mbuf *n" 78.Ft struct mbuf * 79.Fn m_devget "char *buf" "int totlen" "int off" "struct ifnet *ifp" \ 80"void (*func)(const void *, void *, size_t)" 81.Ft void 82.Fn m_zero "struct mbuf *m" 83.Ft int 84.Fn m_apply "struct mbuf *m" "int off" "int len" \ 85"int (*func)(caddr_t, caddr_t, unsigned int)" "caddr_t fstate" 86.Fn MCLGET "struct mbuf *m" "int how" 87.Fn MCLGETI "struct mbuf *m" "int how" "struct ifnet *ifp" "int len" 88.Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int type" \ 89"void (*free)(caddr_t, u_int, void *)" "void *arg" 90.Fn M_ALIGN "struct mbuf *m" "int len" 91.Fn MH_ALIGN "struct mbuf *m" "int len" 92.Fn M_READONLY "struct mbuf *m" 93.Fn M_LEADINGSPACE "struct mbuf *m" 94.Fn M_TRAILINGSPACE "struct mbuf *m" 95.Pp 96.Bd -literal 97#define MLEN (MSIZE - sizeof(struct m_hdr)) 98#define MHLEN (MLEN - sizeof(struct pkthdr)) 99 100#define MINCLSIZE (MHLEN + MLEN + 1) 101#define M_MAXCOMPRESS (MHLEN / 2) 102 103#define mtod(m,t) ((t)((m)-\*(Gtm_data)) 104 105struct m_hdr { 106 struct mbuf *mh_next; 107 struct mbuf *mh_nextpkt; 108 caddr_t mh_data; 109 u_int mh_len; 110 short mh_type; 111 u_short mh_flags; 112}; 113 114struct pkthdr { 115 struct ifnet *rcvif; 116 SLIST_HEAD(packet_tags, m_tag) tags; 117 int len; 118 u_int16_t csum_flags; 119 u_int16_t ether_vtag; 120 struct pkthdr_pf pf; 121}; 122 123struct pkthdr_pf { 124 void *hdr; 125 u_int rtableid; 126 u_int32_t qid; 127 u_int16_t tag; 128 u_int8_t flags; 129 u_int8_t routed; 130}; 131 132struct m_ext { 133 caddr_t ext_buf; 134 void (*ext_free)(caddr_t, u_int, void *); 135 void *ext_arg; 136 u_int ext_size; 137 int ext_type; 138 struct mbuf *ext_nextref; 139 struct mbuf *ext_prevref; 140}; 141 142struct mbuf { 143 struct m_hdr m_hdr; 144 union { 145 struct { 146 struct pkthdr MH_pkthdr; 147 union { 148 struct m_ext MH_ext; 149 char MH_databuf[MHLEN]; 150 } MH_dat; 151 } MH; 152 char M_databuf[MLEN]; 153 } M_dat; 154}; 155 156#define m_next m_hdr.mh_next 157#define m_len m_hdr.mh_len 158#define m_data m_hdr.mh_data 159#define m_type m_hdr.mh_type 160#define m_flags m_hdr.mh_flags 161#define m_nextpkt m_hdr.mh_nextpkt 162#define m_act m_nextpkt 163#define m_pkthdr M_dat.MH.MH_pkthdr 164#define m_ext M_dat.MH.MH_dat.MH_ext 165#define m_pktdat M_dat.MH.MH_dat.MH_databuf 166#define m_dat M_dat.M_databuf 167.Ed 168.Sh DESCRIPTION 169The 170.Nm 171functions provide a way to manage the memory buffers used by the kernel's 172networking subsystem. 173Several functions and macros are used to allocate and deallocate mbufs, 174but also to get, inject, remove, copy, modify, prepend or append data 175inside these mbufs. 176The size of an 177.Nm 178is MSIZE 179.Pq defined in Aq Pa sys/param.h . 180.Pp 181An 182.Nm 183structure is defined as an 184.Fa m_hdr 185structure followed by a 186union. 187The header contains the following elements: 188.Bl -tag -width foobarmoocow 189.It Fa mh_next 190A pointer to the next mbuf in the mbuf chain. 191.It Fa mh_nextpkt 192A pointer to the next mbuf chain (i.e., packet) in the queue. 193.It Fa mh_data 194Indicates the address of the beginning of data in the mbuf. 195.It Fa mh_len 196Indicates the amount of data in the mbuf. 197.It Fa mh_type 198Indicates the type of data contained in the mbuf (see below). 199.It Fa mh_flags 200Flags (see below). 201.El 202.Pp 203The 204.Fa mh_type 205variable can take the following values: 206.Pp 207.Bl -tag -compact -offset indent -width XXXXXXXXXXXXXXXXXX 208.It Dv MT_FREE 209the mbuf should be on the free list. 210.It Dv MT_DATA 211the data in the mbuf was dynamically allocated. 212.It Dv MT_HEADER 213the data contains a packet header. 214.It Dv MT_SONAME 215the data is a socket name. 216.It Dv MT_SOOPTS 217the data are socket options. 218.It Dv MT_FTABLE 219the data is a fragment reassembly header. 220.It Dv MT_CONTROL 221the mbuf contains extra-data protocol message. 222.It Dv MT_OOBDATA 223the data consists of out-of-banddata. 224.El 225.Pp 226The 227.Fa mh_flags 228variable can take the following values: 229.Pp 230.Bl -tag -compact -offset indent -width XXXXXXXXXXXXXXXXXX 231.It Dv M_EXT 232mbuf has associated external storage. 233.It Dv M_PKTHDR 234the mbuf is the first that forms a packet. 235.It Dv M_EOR 236end of record. 237.It Dv M_CLUSTER 238the external storage is a cluster. 239.It Dv M_PROTO1 240protocol-specific. 241.It Dv M_BCAST 242packet send/received as link-level broadcast. 243.It Dv M_MCAST 244packet send/received as link-level multicast. 245.It Dv M_CONF 246packet was encrypted (ESP-transport). 247.It Dv M_AUTH 248packet was authenticated (AH or ESP). 249.It Dv M_AUTH_AH 250header was authenticated (AH). 251.It Dv M_TUNNEL 252header was IP-in-IP encapsulated by tunnel mode IPsec. 253.It Dv M_LINK0 254link layer specific flag. 255.It Dv M_LOOP 256for mbuf statistics. 257.It Dv M_FILDROP 258dropped by 259.Xr bpf 4 260filter. 261.It Dv M_VLANTAG 262.Fa m_pkthdr.ether_vtag 263variable is valid. 264.El 265.Pp 266An external cluster is used when the data to hold in the mbuf is 267large. 268The size of an external cluster is MCLBYTES 269.Pq also defined in Aq Pa sys/param.h . 270A cluster should be used when the size of the data reach MINCLSIZE 271(the minimum size to be held by an external cluster). 272.Pp 273The combination of the M_EXT and M_PKTHDR flags give four types of 274mbuf. 275When none of these constants are in use, the mbuf is a "normal" 276one, where the data part of the mbuf has the following elements: 277.Bl -tag -width foobarmoocow 278.It Fa m_dat 279buffer holding the data (size MLEN). 280.El 281.Pp 282When only M_PKTHDR is set, the data contained in the mbuf is a packet header. 283The data itself is contained in the mbuf (just like the previous case), 284but part of the mbuf is used to store a packet header. 285The data part has then the following elements: 286.Bl -tag -width foobarmoocow 287.It Fa m_pkthdr 288packet header, containing the length of the data, a pointer to the 289interface on which the data was received, checksum information 290and list of 291.Xr mbuf_tags 9 . 292.It Fa m_pktdat 293buffer holding the data (size MHLEN). 294.El 295.Pp 296The 297.Fa m_pkthdr.csum 298variable can take the following values: 299.Pp 300.Bl -tag -compact -offset indent -width XXXXXXXXXXXXXXXXXX 301.It Dv M_IPV4_CSUM_OUT 302IPv4 checksum needed. 303.It Dv M_TCPV4_CSUM_OUT 304TCP checksum needed. 305.It Dv M_UDPV4_CSUM_OUT 306UDP checksum needed. 307.It Dv M_IPV4_CSUM_IN_OK 308IPv4 checksum verified. 309.It Dv M_IPV4_CSUM_IN_BAD 310IPv4 checksum bad. 311.It Dv M_TCP_CSUM_IN_OK 312TCP/IPv4 checksum verified. 313.It Dv M_TCP_CSUM_IN_BAD 314TCP/IPv4 checksum bad. 315.It Dv M_UDP_CSUM_IN_OK 316UDP/IPv4 checksum verified. 317.It Dv M_UDP_CSUM_IN_BAD 318UDP/IPv4 checksum bad. 319.El 320.Pp 321When only M_EXT flag is set, an external storage buffer is being used to 322hold the data, which is no longer stored in the mbuf. 323The data part of the mbuf has now the following elements: 324.Bl -tag -width foobarmoocow 325.It Fa m_pkthdr 326a packet header, just like the previous case, but it is empty. 327No information is stored here 328.It Fa m_ext 329a structure containing information about the external storage 330buffer. 331The information consists of the address of the external buffer, 332a pointer to the function used to free the buffer, a pointer to the 333arguments of the function, the size of the buffer, the type of the 334buffer, and pointers to the previous and next mbufs using this 335cluster. 336.El 337.Pp 338When both the M_EXT and M_PKTHDR flags are set, an external storage buffer 339is being used to store the data and this data contains a packet header. 340The structure used is the same as the previous one except that the 341.Fa m_pkthdr 342element is not empty, it contains the same information as when 343M_PKTHDR is used alone. 344.Bl -tag -width Ds 345.It Fn m_copym "struct mbuf *m" "int off" "int len" "int wait" 346Copy an mbuf chain starting at 347.Fa off 348bytes from the beginning 349and continuing for 350.Fa len 351bytes. 352If 353.Fa off 354is zero and 355.Fa m 356has the M_PKTHDR flag set, 357the header is copied. 358If 359.Fa len 360is M_COPYALL 361the whole mbuf is copied. 362The 363.Fa wait 364parameter can be M_WAIT or 365M_DONTWAIT. 366It does not copy clusters, it just increases their reference count. 367.It Fn m_copym2 "struct mbuf *m" "int off" "int len" "int wait" 368The same as 369.Fn m_copym 370except that it copies cluster mbufs, whereas 371.Fn m_copym 372just increases the reference count of the clusters. 373.It Fn m_free "struct mbuf *m" 374Free the mbuf pointed to by 375.Fa m . 376A pointer to the successor of the mbuf, 377if it exists, is returned by the function. 378.It Fn MFREE "struct mbuf *m" "struct mbuf *n" 379Free the mbuf pointed to by 380.Fa m 381and use 382.Fa n 383to point to the next mbuf in 384the chain if it exists. 385See 386.Fn m_free . 387.It Fn m_get "int how" "int type" 388Return a pointer to an mbuf of the type specified. 389If the 390.Fa how 391argument is 392.Fa M_WAITOK , 393the function may call 394.Xr tsleep 9 395to await resources. 396If 397.Fa how 398is 399.Fa M_DONTWAIT 400and resources are not available, 401.Fn m_get 402returns NULL. 403.It Fn MGET "struct mbuf *m" "int how" "int type" 404Return a pointer to an mbuf in 405.Fa m 406of the type specified. 407See 408.Fn m_get 409for a description of 410.Fa how . 411.It Fn m_getclr "int how" "int type" 412Return a pointer to an mbuf of the type specified, and clear the data 413area of the mbuf. 414See 415.Fn m_get 416for a description of 417.Fa how . 418.It Fn m_gethdr "int how" "int type" 419Return a pointer to an mbuf of the type specified after initializing 420it to contain a packet header. 421See 422.Fn m_get 423for a description of 424.Fa how . 425.It Fn MGETHDR "struct mbuf *m" "int how" "int type" 426Return a pointer to an mbuf of the type specified after initializing 427it to contain a packet header. 428See 429.Fn m_get 430for a description of 431.Fa how . 432.It Fn m_prepend "struct mbuf *m" "int len" "int how" 433Allocate a new mbuf and prepend it to the mbuf chain pointed to by 434.Fa m . 435If 436.Fa m 437points to an mbuf with a packet header, it is moved to the new 438mbuf that has been prepended. 439The return value is a pointer on the new mbuf chain. 440If this function fails to allocate a new mbuf, 441.Fa m 442is freed. 443See 444.Fn m_get 445for a description of 446.Fa how . 447.Pp 448.Fn m_prepend 449should never be called directly. 450Use 451.Fn M_PREPEND 452instead. 453.It Fn M_PREPEND "struct mbuf *m" "int plen" "int how" 454Prepend space of size 455.Fa plen 456to the mbuf pointed to by 457.Fa m . 458If a new mbuf must be allocated, 459.Fa how 460specifies whether to wait or not. 461If this function fails to allocate a new mbuf, 462.Fa m 463is freed. 464.It Fn m_pulldown "struct mbuf *m" "int off" "int len" "int *offp" 465Ensure that the data in the mbuf chain starting at 466.Fa off 467and ending at 468.Fa off+len 469will be put in a continuous memory region. 470.Fa len 471must be smaller or equal than MCLBYTES. 472The pointer returned points to an mbuf in the chain and the new offset 473for data in this mbuf is 474.Fa *offp . 475If this function fails, 476.Fa m 477is freed. 478.It Fn m_pullup "struct mbuf *n" "int len" 479Ensure that the data in the mbuf chain starting at the beginning of 480the chain and ending at 481.Fa len 482will be put in continuous memory region. 483To avoid being called again, 484.Fn m_pullup 485will attempt to copy 486.Fa "max_protohdr - len" 487bytes into the first mbuf. 488The 489.Fa len 490argument must be smaller or equal than MHLEN. 491If this function fails, 492.Fa n 493is freed. 494.It Fn m_pullup2 "struct mbuf *n" "int len" 495Just like 496.Fn m_pullup , 497ensure that the data starting at the beginning of the mbuf chain and 498ending at 499.Fa len 500will be put in continuous memory region. 501The 502.Fa len 503argument can be up to MCLBYTES. 504.Fn m_pullup2 505will simply call 506.Fn m_pullup 507if 508.Fa len 509is smaller or equal to MHLEN. 510.It Fn m_split "struct mbuf *m0" "int len0" "int wait" 511Split an mbuf chain in two pieces, returning a pointer to 512the tail (which is made of the previous mbuf chain except the first 513.Fa len0 514bytes). 515.It Fn m_inject "struct mbuf *m0" "int len0" "int siz" "int wait" 516Inject a new mbuf chain of length 517.Fa siz 518into the mbuf chain pointed to by 519.Fa m0 520at position 521.Fa len0 . 522If there is enough space for an object of size 523.Fa siz 524in the appropriate location, no memory will be allocated. 525On failure, the function returns NULL (the mbuf is left untouched) and 526on success, a pointer to the first injected mbuf is returned. 527.It Fn m_getptr "struct mbuf *m" "int loc" "int *off" 528Returns a pointer to the mbuf containing the data located at 529.Fa loc 530bytes of the beginning. 531The offset in the new mbuf is pointed to by 532.Fa off . 533.It Fn m_adj "struct mbuf *mp" "int req_len" 534Trims 535.Fa req_len 536bytes of data from the mbuf chain pointed to by 537.Fa mp . 538If 539.Fa req_len 540is positive, the data will be trimmed from the head of the mbuf chain 541and if it is negative, it will be trimmed from the tail of the mbuf 542chain. 543.It Fn m_copyback "struct mbuf *m0" "int off" "int len" "caddr_t cp" 544Copy data from a buffer pointed to by 545.Fa cp 546back into the mbuf chain pointed to by 547.Fa m0 548starting at 549.Fa off 550bytes from the beginning, extending the mbuf chain if 551necessary. 552The mbuf chain must be initialized properly, including setting 553.Fa m_len . 554.It Fn m_freem "struct mbuf *m" 555Free the mbuf chain pointed to by 556.Fa m . 557.It Fn m_reclaim "void" 558Ask protocols to free unused memory space. 559.It Fn m_copydata "struct mbuf *m" "int off" "int len" "caddr_t cp" 560Copy data from the mbuf chain pointed to by 561.Fa m 562starting at 563.Fa off 564bytes from the beginning and continuing for 565.Fa len 566bytes into the buffer pointed to by 567.Fa cp . 568.It Fn m_cat "struct mbuf *m" "struct mbuf *n" 569Concatenate the mbuf chain pointed to by 570.Fa n 571to the mbuf chain pointed to by 572.Fa m . 573The mbuf chains must be of the same type. 574.It Fn m_devget "char *buf" "int totlen" "int off" "struct ifnet *ifp" \ 575"void (*func)(const void *, void *, size_t)" 576Copy 577.Fa totlen 578bytes of data from device local memory pointed to by 579.Fa buf 580using the function 581.Fa func 582or 583.Fn bcopy 584if 585.Fa func 586is NULL. 587The data is copied into an mbuf chain at offset 588.Fa off 589and a pointer to the head of the chain is returned. 590Returns NULL on failure. 591.It Fn m_zero "struct mbuf *m" 592Zeroize the data part of the mbufs in the mbuf chain pointed to by 593.Fa m . 594.It Fn m_apply "struct mbuf *m" "int off" "int len" \ 595"int (*func)(caddr_t, caddr_t, unsigned int)" "caddr_t fstate" 596Apply the function 597.Fa func 598to the data in the mbuf chain pointed to by 599.Fa m 600starting at 601.Fa off 602bytes from the beginning and continuing for 603.Fa len 604bytes. 605.It Fn mtod "struct mbuf *m" "datatype" 606Return a pointer to the data contained in the specified mbuf 607.Fa m 608cast to 609.Fa datatype . 610.It Fn MCLGET "struct mbuf *m" "int how" 611Allocate and add an mbuf cluster to the mbuf pointed to by 612.Fa m . 613On success, the flag M_EXT is set in the mbuf. 614See 615.Fn m_get 616for a description of 617.Fa how . 618.It Fn MCLGETI "struct mbuf *m" "int how" "struct ifnet *ifp" "int len" 619If 620.Fa m 621is NULL, allocate it. 622Then allocate and add an mbuf cluster of length 623.Fa len 624to the mbuf pointed to by 625.Fa m . 626If 627.Fa ifp 628is passed in, then per-interface accounting for the mbuf will occur, 629and thus mbuf allocation can fail when limits are reached. 630Returns either the mbuf 631.Fa m 632that was passed in, or the newly allocated one which was allocated; in 633either case the flag M_EXT is set in the mbuf. 634See 635.Fn m_get 636for a description of 637.Fa how . 638.It Fn MEXTADD "struct mbuf *m" "caddr_t buf" "u_int size" "int type" \ 639"void (*free)(caddr_t, u_int, void *)" "void *arg" 640Add pre-allocated storage to the mbuf pointed to by 641.Fa m . 642On success, the flag M_EXT is set in the mbuf. 643.It Fn M_ALIGN "struct mbuf *m" "int len" 644Set the 645.Fa m_data 646pointer of the newly allocated mbuf with 647.Fn m_get 648or 649.Fn MGET 650pointed to by 651.Fa m 652to an object of the specified size 653.Fa len 654at the end of the mbuf, longword aligned. 655.It Fn MH_ALIGN "m" "len" 656Same as 657.Fn M_ALIGN 658except it is for an mbuf allocated with 659.Fn m_gethdr 660or 661.Fn MGETHDR . 662.It Fn M_READONLY "struct mbuf *m" 663Check if the data of the mbuf pointed to by 664.Fa m 665is read-only. 666This is true for non-cluster external storage and for clusters that 667are being referenced by more than one mbuf. 668.It Fn M_LEADINGSPACE "struct mbuf *m" 669Compute the amount of space available before the current start of data 670in the mbuf pointed to by 671.Fa m . 672.It Fn M_TRAILINGSPACE "struct mbuf *m" 673Compute the amount of space available after the end of data in the 674mbuf pointed to by 675.El 676.Sh CODE REFERENCES 677The mbuf management functions are implemented in the files 678.Pa sys/kern/uipc_mbuf.c 679and 680.Pa sys/kern/uipc_mbuf2.c . 681The function prototypes and the macros are located in 682.Pa sys/sys/mbuf.h . 683.Sh SEE ALSO 684.Xr netstat 1 , 685.Xr mbuf_tags 9 686.Pp 687"Networking Implementation Notes", 688.Pa /usr/share/doc/smm/18.net . 689.Rs 690.%A Jun-Ichiro Hagino 691.%T "Mbuf issues in 4.4BSD IPv6/IPsec support (experiences from KAME IPv6/IPsec implementation)" 692.%B "Proceedings of the Freenix Track: 2000 USENIX Annual Technical Conference" 693.%D June 2000 694.Re 695