uipc_mbuf2.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* $OpenBSD: uipc_mbuf2.c,v 1.41 2015/06/30 15:30:17 mpi Exp $ */
  2. /* $KAME: uipc_mbuf2.c,v 1.29 2001/02/14 13:42:10 itojun Exp $ */
  3. /* $NetBSD: uipc_mbuf.c,v 1.40 1999/04/01 00:23:25 thorpej Exp $ */
  4. /*
  5. * Copyright (C) 1999 WIDE Project.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the project nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. */
  32. /*
  33. * Copyright (c) 1982, 1986, 1988, 1991, 1993
  34. * The Regents of the University of California. All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. * 1. Redistributions of source code must retain the above copyright
  40. * notice, this list of conditions and the following disclaimer.
  41. * 2. Redistributions in binary form must reproduce the above copyright
  42. * notice, this list of conditions and the following disclaimer in the
  43. * documentation and/or other materials provided with the distribution.
  44. * 3. Neither the name of the University nor the names of its contributors
  45. * may be used to endorse or promote products derived from this software
  46. * without specific prior written permission.
  47. *
  48. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  49. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  51. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  52. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  53. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  54. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  55. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  56. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  57. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  58. * SUCH DAMAGE.
  59. *
  60. * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95
  61. */
  62. #include <sys/param.h>
  63. #include <sys/systm.h>
  64. #include <sys/malloc.h>
  65. #include <sys/pool.h>
  66. #include <sys/mbuf.h>
  67. extern struct pool mtagpool;
  68. /* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */
  69. static struct mbuf *m_dup1(struct mbuf *, int, int, int);
  70. /*
  71. * ensure that [off, off + len] is contiguous on the mbuf chain "m".
  72. * packet chain before "off" is kept untouched.
  73. * if offp == NULL, the target will start at <retval, 0> on resulting chain.
  74. * if offp != NULL, the target will start at <retval, *offp> on resulting chain.
  75. *
  76. * on error return (NULL return value), original "m" will be freed.
  77. *
  78. * XXX M_TRAILINGSPACE/M_LEADINGSPACE on shared cluster (sharedcluster)
  79. */
  80. struct mbuf *
  81. m_pulldown(struct mbuf *m, int off, int len, int *offp)
  82. {
  83. struct mbuf *n, *o;
  84. int hlen, tlen, olen;
  85. int sharedcluster;
  86. /* check invalid arguments. */
  87. if (m == NULL)
  88. panic("m == NULL in m_pulldown()");
  89. if ((n = m_getptr(m, off, &off)) == NULL) {
  90. m_freem(m);
  91. return (NULL); /* mbuf chain too short */
  92. }
  93. sharedcluster = M_READONLY(n);
  94. /*
  95. * the target data is on <n, off>.
  96. * if we got enough data on the mbuf "n", we're done.
  97. */
  98. if ((off == 0 || offp) && len <= n->m_len - off && !sharedcluster)
  99. goto ok;
  100. /*
  101. * when len <= n->m_len - off and off != 0, it is a special case.
  102. * len bytes from <n, off> sits in single mbuf, but the caller does
  103. * not like the starting position (off).
  104. * chop the current mbuf into two pieces, set off to 0.
  105. */
  106. if (len <= n->m_len - off) {
  107. struct mbuf *mlast;
  108. o = m_dup1(n, off, n->m_len - off, M_DONTWAIT);
  109. if (o == NULL) {
  110. m_freem(m);
  111. return (NULL); /* ENOBUFS */
  112. }
  113. for (mlast = o; mlast->m_next != NULL; mlast = mlast->m_next)
  114. ;
  115. n->m_len = off;
  116. mlast->m_next = n->m_next;
  117. n->m_next = o;
  118. n = o;
  119. off = 0;
  120. goto ok;
  121. }
  122. /*
  123. * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
  124. * and construct contiguous mbuf with m_len == len.
  125. * note that hlen + tlen == len, and tlen > 0.
  126. */
  127. hlen = n->m_len - off;
  128. tlen = len - hlen;
  129. /*
  130. * ensure that we have enough trailing data on mbuf chain.
  131. * if not, we can do nothing about the chain.
  132. */
  133. olen = 0;
  134. for (o = n->m_next; o != NULL; o = o->m_next)
  135. olen += o->m_len;
  136. if (hlen + olen < len) {
  137. m_freem(m);
  138. return (NULL); /* mbuf chain too short */
  139. }
  140. /*
  141. * easy cases first.
  142. * we need to use m_copydata() to get data from <n->m_next, 0>.
  143. */
  144. if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen &&
  145. !sharedcluster) {
  146. m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
  147. n->m_len += tlen;
  148. m_adj(n->m_next, tlen);
  149. goto ok;
  150. }
  151. if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen &&
  152. !sharedcluster && n->m_next->m_len >= tlen) {
  153. n->m_next->m_data -= hlen;
  154. n->m_next->m_len += hlen;
  155. memmove(mtod(n->m_next, caddr_t), mtod(n, caddr_t) + off, hlen);
  156. n->m_len -= hlen;
  157. n = n->m_next;
  158. off = 0;
  159. goto ok;
  160. }
  161. /*
  162. * now, we need to do the hard way. don't m_copym as there's no room
  163. * on both ends.
  164. */
  165. if (len > MAXMCLBYTES) {
  166. m_freem(m);
  167. return (NULL);
  168. }
  169. MGET(o, M_DONTWAIT, m->m_type);
  170. if (o && len > MLEN) {
  171. MCLGETI(o, M_DONTWAIT, NULL, len);
  172. if ((o->m_flags & M_EXT) == 0) {
  173. m_free(o);
  174. o = NULL;
  175. }
  176. }
  177. if (!o) {
  178. m_freem(m);
  179. return (NULL); /* ENOBUFS */
  180. }
  181. /* get hlen from <n, off> into <o, 0> */
  182. o->m_len = hlen;
  183. memmove(mtod(o, caddr_t), mtod(n, caddr_t) + off, hlen);
  184. n->m_len -= hlen;
  185. /* get tlen from <n->m_next, 0> into <o, hlen> */
  186. m_copydata(n->m_next, 0, tlen, mtod(o, caddr_t) + o->m_len);
  187. o->m_len += tlen;
  188. m_adj(n->m_next, tlen);
  189. o->m_next = n->m_next;
  190. n->m_next = o;
  191. n = o;
  192. off = 0;
  193. ok:
  194. if (offp)
  195. *offp = off;
  196. return (n);
  197. }
  198. static struct mbuf *
  199. m_dup1(struct mbuf *m, int off, int len, int wait)
  200. {
  201. struct mbuf *n;
  202. int l;
  203. if (len > MAXMCLBYTES)
  204. return (NULL);
  205. if (off == 0 && (m->m_flags & M_PKTHDR) != 0) {
  206. MGETHDR(n, wait, m->m_type);
  207. if (n == NULL)
  208. return (NULL);
  209. if (m_dup_pkthdr(n, m, wait)) {
  210. m_free(n);
  211. return (NULL);
  212. }
  213. l = MHLEN;
  214. } else {
  215. MGET(n, wait, m->m_type);
  216. l = MLEN;
  217. }
  218. if (n && len > l) {
  219. MCLGETI(n, wait, NULL, len);
  220. if ((n->m_flags & M_EXT) == 0) {
  221. m_free(n);
  222. n = NULL;
  223. }
  224. }
  225. if (!n)
  226. return (NULL);
  227. m_copydata(m, off, len, mtod(n, caddr_t));
  228. n->m_len = len;
  229. return (n);
  230. }
  231. /* Get a packet tag structure along with specified data following. */
  232. struct m_tag *
  233. m_tag_get(int type, int len, int wait)
  234. {
  235. struct m_tag *t;
  236. if (len < 0)
  237. return (NULL);
  238. if (len > PACKET_TAG_MAXSIZE)
  239. panic("requested tag size for pool %#x is too big", type);
  240. t = pool_get(&mtagpool, wait == M_WAITOK ? PR_WAITOK : PR_NOWAIT);
  241. if (t == NULL)
  242. return (NULL);
  243. t->m_tag_id = type;
  244. t->m_tag_len = len;
  245. return (t);
  246. }
  247. /* Prepend a packet tag. */
  248. void
  249. m_tag_prepend(struct mbuf *m, struct m_tag *t)
  250. {
  251. SLIST_INSERT_HEAD(&m->m_pkthdr.tags, t, m_tag_link);
  252. m->m_pkthdr.tagsset |= t->m_tag_id;
  253. }
  254. /* Unlink and free a packet tag. */
  255. void
  256. m_tag_delete(struct mbuf *m, struct m_tag *t)
  257. {
  258. u_int32_t tagsset = 0;
  259. struct m_tag *p;
  260. SLIST_REMOVE(&m->m_pkthdr.tags, t, m_tag, m_tag_link);
  261. pool_put(&mtagpool, t);
  262. SLIST_FOREACH(p, &m->m_pkthdr.tags, m_tag_link)
  263. tagsset |= p->m_tag_id;
  264. m->m_pkthdr.tagsset = tagsset;
  265. }
  266. /* Unlink and free a packet tag chain. */
  267. void
  268. m_tag_delete_chain(struct mbuf *m)
  269. {
  270. struct m_tag *p;
  271. while ((p = SLIST_FIRST(&m->m_pkthdr.tags)) != NULL) {
  272. SLIST_REMOVE_HEAD(&m->m_pkthdr.tags, m_tag_link);
  273. pool_put(&mtagpool, p);
  274. }
  275. m->m_pkthdr.tagsset = 0;
  276. }
  277. /* Find a tag, starting from a given position. */
  278. struct m_tag *
  279. m_tag_find(struct mbuf *m, int type, struct m_tag *t)
  280. {
  281. struct m_tag *p;
  282. if (!(m->m_pkthdr.tagsset & type))
  283. return (NULL);
  284. if (t == NULL)
  285. p = SLIST_FIRST(&m->m_pkthdr.tags);
  286. else
  287. p = SLIST_NEXT(t, m_tag_link);
  288. while (p != NULL) {
  289. if (p->m_tag_id == type)
  290. return (p);
  291. p = SLIST_NEXT(p, m_tag_link);
  292. }
  293. return (NULL);
  294. }
  295. /* Copy a single tag. */
  296. struct m_tag *
  297. m_tag_copy(struct m_tag *t, int wait)
  298. {
  299. struct m_tag *p;
  300. p = m_tag_get(t->m_tag_id, t->m_tag_len, wait);
  301. if (p == NULL)
  302. return (NULL);
  303. memcpy(p + 1, t + 1, t->m_tag_len); /* Copy the data */
  304. return (p);
  305. }
  306. /*
  307. * Copy two tag chains. The destination mbuf (to) loses any attached
  308. * tags even if the operation fails. This should not be a problem, as
  309. * m_tag_copy_chain() is typically called with a newly-allocated
  310. * destination mbuf.
  311. */
  312. int
  313. m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int wait)
  314. {
  315. struct m_tag *p, *t, *tprev = NULL;
  316. m_tag_delete_chain(to);
  317. SLIST_FOREACH(p, &from->m_pkthdr.tags, m_tag_link) {
  318. t = m_tag_copy(p, wait);
  319. if (t == NULL) {
  320. m_tag_delete_chain(to);
  321. return (ENOBUFS);
  322. }
  323. if (tprev == NULL)
  324. SLIST_INSERT_HEAD(&to->m_pkthdr.tags, t, m_tag_link);
  325. else
  326. SLIST_INSERT_AFTER(tprev, t, m_tag_link);
  327. tprev = t;
  328. to->m_pkthdr.tagsset |= t->m_tag_id;
  329. }
  330. return (0);
  331. }
  332. /* Initialize tags on an mbuf. */
  333. void
  334. m_tag_init(struct mbuf *m)
  335. {
  336. SLIST_INIT(&m->m_pkthdr.tags);
  337. }
  338. /* Get first tag in chain. */
  339. struct m_tag *
  340. m_tag_first(struct mbuf *m)
  341. {
  342. return (SLIST_FIRST(&m->m_pkthdr.tags));
  343. }
  344. /* Get next tag in chain. */
  345. struct m_tag *
  346. m_tag_next(struct mbuf *m, struct m_tag *t)
  347. {
  348. return (SLIST_NEXT(t, m_tag_link));
  349. }