xform_ipcomp.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */
  2. /*-
  3. * SPDX-License-Identifier: BSD-3-Clause
  4. *
  5. * Copyright (c) 2001 Jean-Jacques Bernard-Gundol (jj@wabbitt.org)
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  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. The name of the author may not be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /* IP payload compression protocol (IPComp), see RFC 2393 */
  31. #include "opt_inet.h"
  32. #include "opt_inet6.h"
  33. #include "opt_ipsec.h"
  34. #include <sys/param.h>
  35. #include <sys/systm.h>
  36. #include <sys/malloc.h>
  37. #include <sys/mbuf.h>
  38. #include <sys/lock.h>
  39. #include <sys/mutex.h>
  40. #include <sys/socket.h>
  41. #include <sys/kernel.h>
  42. #include <sys/protosw.h>
  43. #include <sys/sysctl.h>
  44. #include <netinet/in.h>
  45. #include <netinet/in_systm.h>
  46. #include <netinet/ip.h>
  47. #include <netinet/ip_var.h>
  48. #include <netinet/ip_encap.h>
  49. #include <net/netisr.h>
  50. #include <net/vnet.h>
  51. #include <net/if.h> /* XXXGL: net_epoch should move out there */
  52. #include <net/if_var.h> /* XXXGL: net_epoch should move out there */
  53. #include <netipsec/ipsec.h>
  54. #include <netipsec/xform.h>
  55. #ifdef INET6
  56. #include <netinet/ip6.h>
  57. #include <netinet6/ip6_var.h>
  58. #include <netipsec/ipsec6.h>
  59. #endif
  60. #include <netipsec/ipcomp.h>
  61. #include <netipsec/ipcomp_var.h>
  62. #include <netipsec/key.h>
  63. #include <netipsec/key_debug.h>
  64. #include <opencrypto/cryptodev.h>
  65. #include <opencrypto/deflate.h>
  66. #include <opencrypto/xform.h>
  67. VNET_DEFINE(int, ipcomp_enable) = 1;
  68. VNET_PCPUSTAT_DEFINE(struct ipcompstat, ipcompstat);
  69. VNET_PCPUSTAT_SYSINIT(ipcompstat);
  70. #ifdef VIMAGE
  71. VNET_PCPUSTAT_SYSUNINIT(ipcompstat);
  72. #endif /* VIMAGE */
  73. SYSCTL_DECL(_net_inet_ipcomp);
  74. SYSCTL_INT(_net_inet_ipcomp, OID_AUTO, ipcomp_enable,
  75. CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipcomp_enable), 0, "");
  76. SYSCTL_VNET_PCPUSTAT(_net_inet_ipcomp, IPSECCTL_STATS, stats,
  77. struct ipcompstat, ipcompstat,
  78. "IPCOMP statistics (struct ipcompstat, netipsec/ipcomp_var.h");
  79. static MALLOC_DEFINE(M_IPCOMP, "ipcomp", "IPCOMP");
  80. static int ipcomp_input_cb(struct cryptop *crp);
  81. static int ipcomp_output_cb(struct cryptop *crp);
  82. /*
  83. * RFC 3173 p 2.2. Non-Expansion Policy:
  84. * If the total size of a compressed payload and the IPComp header, as
  85. * defined in section 3, is not smaller than the size of the original
  86. * payload, the IP datagram MUST be sent in the original non-compressed
  87. * form.
  88. *
  89. * When we use IPComp in tunnel mode, for small packets we will receive
  90. * encapsulated IP-IP datagrams without any compression and without IPComp
  91. * header.
  92. */
  93. static int
  94. ipcomp_encapcheck(union sockaddr_union *src, union sockaddr_union *dst)
  95. {
  96. struct secasvar *sav;
  97. sav = key_allocsa_tunnel(src, dst, IPPROTO_IPCOMP);
  98. if (sav == NULL)
  99. return (0);
  100. key_freesav(&sav);
  101. if (src->sa.sa_family == AF_INET)
  102. return (sizeof(struct in_addr) << 4);
  103. else
  104. return (sizeof(struct in6_addr) << 4);
  105. }
  106. static int
  107. ipcomp_nonexp_input(struct mbuf *m, int off, int proto, void *arg __unused)
  108. {
  109. int isr;
  110. NET_EPOCH_ASSERT();
  111. switch (proto) {
  112. #ifdef INET
  113. case IPPROTO_IPV4:
  114. isr = NETISR_IP;
  115. break;
  116. #endif
  117. #ifdef INET6
  118. case IPPROTO_IPV6:
  119. isr = NETISR_IPV6;
  120. break;
  121. #endif
  122. default:
  123. IPCOMPSTAT_INC(ipcomps_nopf);
  124. m_freem(m);
  125. return (IPPROTO_DONE);
  126. }
  127. m_adj(m, off);
  128. IPCOMPSTAT_ADD(ipcomps_ibytes, m->m_pkthdr.len);
  129. IPCOMPSTAT_INC(ipcomps_input);
  130. netisr_dispatch(isr, m);
  131. return (IPPROTO_DONE);
  132. }
  133. /*
  134. * ipcomp_init() is called when an CPI is being set up.
  135. */
  136. static int
  137. ipcomp_init(struct secasvar *sav, struct xformsw *xsp)
  138. {
  139. const struct comp_algo *tcomp;
  140. struct crypto_session_params csp;
  141. /* NB: algorithm really comes in alg_enc and not alg_comp! */
  142. tcomp = comp_algorithm_lookup(sav->alg_enc);
  143. if (tcomp == NULL) {
  144. DPRINTF(("%s: unsupported compression algorithm %d\n", __func__,
  145. sav->alg_comp));
  146. return EINVAL;
  147. }
  148. sav->alg_comp = sav->alg_enc; /* set for doing histogram */
  149. sav->tdb_xform = xsp;
  150. sav->tdb_compalgxform = tcomp;
  151. /* Initialize crypto session */
  152. memset(&csp, 0, sizeof(csp));
  153. csp.csp_mode = CSP_MODE_COMPRESS;
  154. csp.csp_cipher_alg = sav->tdb_compalgxform->type;
  155. return crypto_newsession(&sav->tdb_cryptoid, &csp, V_crypto_support);
  156. }
  157. /*
  158. * ipcomp_cleanup() used when IPCA is deleted
  159. */
  160. static void
  161. ipcomp_cleanup(struct secasvar *sav)
  162. {
  163. crypto_freesession(sav->tdb_cryptoid);
  164. sav->tdb_cryptoid = NULL;
  165. }
  166. /*
  167. * ipcomp_input() gets called to uncompress an input packet
  168. */
  169. static int
  170. ipcomp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
  171. {
  172. struct xform_data *xd;
  173. struct cryptop *crp;
  174. struct ipcomp *ipcomp;
  175. crypto_session_t cryptoid;
  176. caddr_t addr;
  177. int error, hlen = IPCOMP_HLENGTH;
  178. SECASVAR_RLOCK_TRACKER;
  179. /*
  180. * Check that the next header of the IPComp is not IPComp again, before
  181. * doing any real work. Given it is not possible to do double
  182. * compression it means someone is playing tricks on us.
  183. */
  184. error = ENOBUFS;
  185. if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
  186. IPCOMPSTAT_INC(ipcomps_hdrops); /*XXX*/
  187. DPRINTF(("%s: m_pullup failed\n", __func__));
  188. key_freesav(&sav);
  189. return (error);
  190. }
  191. addr = (caddr_t) mtod(m, struct ip *) + skip;
  192. ipcomp = (struct ipcomp *)addr;
  193. if (ipcomp->comp_nxt == IPPROTO_IPCOMP) {
  194. IPCOMPSTAT_INC(ipcomps_pdrops); /* XXX have our own stats? */
  195. DPRINTF(("%s: recursive compression detected\n", __func__));
  196. error = EINVAL;
  197. goto bad;
  198. }
  199. SECASVAR_RLOCK(sav);
  200. cryptoid = sav->tdb_cryptoid;
  201. SECASVAR_RUNLOCK(sav);
  202. /* Get crypto descriptors */
  203. crp = crypto_getreq(cryptoid, M_NOWAIT);
  204. if (crp == NULL) {
  205. DPRINTF(("%s: no crypto descriptors\n", __func__));
  206. IPCOMPSTAT_INC(ipcomps_crypto);
  207. goto bad;
  208. }
  209. /* Get IPsec-specific opaque pointer */
  210. xd = malloc(sizeof(*xd), M_IPCOMP, M_NOWAIT | M_ZERO);
  211. if (xd == NULL) {
  212. DPRINTF(("%s: cannot allocate xform_data\n", __func__));
  213. IPCOMPSTAT_INC(ipcomps_crypto);
  214. crypto_freereq(crp);
  215. goto bad;
  216. }
  217. /* Decompression operation */
  218. crp->crp_op = CRYPTO_OP_DECOMPRESS;
  219. crp->crp_payload_start = skip + hlen;
  220. crp->crp_payload_length = m->m_pkthdr.len - (skip + hlen);
  221. /* Crypto operation descriptor */
  222. crp->crp_flags = CRYPTO_F_CBIFSYNC;
  223. crypto_use_mbuf(crp, m);
  224. crp->crp_callback = ipcomp_input_cb;
  225. crp->crp_opaque = xd;
  226. /* These are passed as-is to the callback */
  227. xd->sav = sav;
  228. xd->protoff = protoff;
  229. xd->skip = skip;
  230. xd->vnet = curvnet;
  231. xd->cryptoid = cryptoid;
  232. SECASVAR_RLOCK(sav);
  233. crp->crp_session = xd->cryptoid = sav->tdb_cryptoid;
  234. SECASVAR_RUNLOCK(sav);
  235. return crypto_dispatch(crp);
  236. bad:
  237. m_freem(m);
  238. key_freesav(&sav);
  239. return (error);
  240. }
  241. /*
  242. * IPComp input callback from the crypto driver.
  243. */
  244. static int
  245. ipcomp_input_cb(struct cryptop *crp)
  246. {
  247. IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  248. struct xform_data *xd;
  249. struct mbuf *m;
  250. struct secasvar *sav;
  251. struct secasindex *saidx;
  252. caddr_t addr;
  253. crypto_session_t cryptoid;
  254. int hlen = IPCOMP_HLENGTH, error, clen;
  255. int skip, protoff;
  256. uint8_t nproto;
  257. m = crp->crp_buf.cb_mbuf;
  258. xd = crp->crp_opaque;
  259. CURVNET_SET(xd->vnet);
  260. sav = xd->sav;
  261. skip = xd->skip;
  262. protoff = xd->protoff;
  263. cryptoid = xd->cryptoid;
  264. saidx = &sav->sah->saidx;
  265. IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET ||
  266. saidx->dst.sa.sa_family == AF_INET6,
  267. ("unexpected protocol family %u", saidx->dst.sa.sa_family));
  268. /* Check for crypto errors */
  269. if (crp->crp_etype) {
  270. if (crp->crp_etype == EAGAIN) {
  271. /* Reset the session ID */
  272. if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
  273. crypto_freesession(cryptoid);
  274. xd->cryptoid = crp->crp_session;
  275. CURVNET_RESTORE();
  276. return (crypto_dispatch(crp));
  277. }
  278. IPCOMPSTAT_INC(ipcomps_noxform);
  279. DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
  280. error = crp->crp_etype;
  281. goto bad;
  282. }
  283. /* Shouldn't happen... */
  284. if (m == NULL) {
  285. IPCOMPSTAT_INC(ipcomps_crypto);
  286. DPRINTF(("%s: null mbuf returned from crypto\n", __func__));
  287. error = EINVAL;
  288. goto bad;
  289. }
  290. IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]);
  291. clen = crp->crp_olen; /* Length of data after processing */
  292. /* Release the crypto descriptors */
  293. free(xd, M_IPCOMP), xd = NULL;
  294. crypto_freereq(crp), crp = NULL;
  295. /* In case it's not done already, adjust the size of the mbuf chain */
  296. m->m_pkthdr.len = clen + hlen + skip;
  297. if (m->m_len < skip + hlen && (m = m_pullup(m, skip + hlen)) == NULL) {
  298. IPCOMPSTAT_INC(ipcomps_hdrops); /*XXX*/
  299. DPRINTF(("%s: m_pullup failed\n", __func__));
  300. error = EINVAL; /*XXX*/
  301. goto bad;
  302. }
  303. /* Keep the next protocol field */
  304. addr = (caddr_t) mtod(m, struct ip *) + skip;
  305. nproto = ((struct ipcomp *) addr)->comp_nxt;
  306. /* Remove the IPCOMP header */
  307. error = m_striphdr(m, skip, hlen);
  308. if (error) {
  309. IPCOMPSTAT_INC(ipcomps_hdrops);
  310. DPRINTF(("%s: bad mbuf chain, IPCA %s/%08lx\n", __func__,
  311. ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  312. (u_long) ntohl(sav->spi)));
  313. goto bad;
  314. }
  315. /* Restore the Next Protocol field */
  316. m_copyback(m, protoff, sizeof (u_int8_t), (u_int8_t *) &nproto);
  317. switch (saidx->dst.sa.sa_family) {
  318. #ifdef INET6
  319. case AF_INET6:
  320. error = ipsec6_common_input_cb(m, sav, skip, protoff);
  321. break;
  322. #endif
  323. #ifdef INET
  324. case AF_INET:
  325. error = ipsec4_common_input_cb(m, sav, skip, protoff);
  326. break;
  327. #endif
  328. default:
  329. panic("%s: Unexpected address family: %d saidx=%p", __func__,
  330. saidx->dst.sa.sa_family, saidx);
  331. }
  332. CURVNET_RESTORE();
  333. return error;
  334. bad:
  335. CURVNET_RESTORE();
  336. if (sav != NULL)
  337. key_freesav(&sav);
  338. if (m != NULL)
  339. m_freem(m);
  340. if (xd != NULL)
  341. free(xd, M_IPCOMP);
  342. if (crp != NULL)
  343. crypto_freereq(crp);
  344. return error;
  345. }
  346. /*
  347. * IPComp output routine, called by ipsec[46]_perform_request()
  348. */
  349. static int
  350. ipcomp_output(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
  351. u_int idx, int skip, int protoff)
  352. {
  353. IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  354. const struct comp_algo *ipcompx;
  355. struct cryptop *crp;
  356. struct xform_data *xd;
  357. crypto_session_t cryptoid;
  358. int error, ralen, maxpacketsize;
  359. SECASVAR_RLOCK_TRACKER;
  360. IPSEC_ASSERT(sav != NULL, ("null SA"));
  361. ipcompx = sav->tdb_compalgxform;
  362. IPSEC_ASSERT(ipcompx != NULL, ("null compression xform"));
  363. /*
  364. * Do not touch the packet in case our payload to compress
  365. * is lower than the minimal threshold of the compression
  366. * alogrithm. We will just send out the data uncompressed.
  367. * See RFC 3173, 2.2. Non-Expansion Policy.
  368. */
  369. if (m->m_pkthdr.len <= ipcompx->minlen) {
  370. IPCOMPSTAT_INC(ipcomps_threshold);
  371. return ipsec_process_done(m, sp, sav, idx);
  372. }
  373. ralen = m->m_pkthdr.len - skip; /* Raw payload length before comp. */
  374. IPCOMPSTAT_INC(ipcomps_output);
  375. /* Check for maximum packet size violations. */
  376. switch (sav->sah->saidx.dst.sa.sa_family) {
  377. #ifdef INET
  378. case AF_INET:
  379. maxpacketsize = IP_MAXPACKET;
  380. break;
  381. #endif /* INET */
  382. #ifdef INET6
  383. case AF_INET6:
  384. maxpacketsize = IPV6_MAXPACKET;
  385. break;
  386. #endif /* INET6 */
  387. default:
  388. IPCOMPSTAT_INC(ipcomps_nopf);
  389. DPRINTF(("%s: unknown/unsupported protocol family %d, "
  390. "IPCA %s/%08lx\n", __func__,
  391. sav->sah->saidx.dst.sa.sa_family,
  392. ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  393. (u_long) ntohl(sav->spi)));
  394. error = EPFNOSUPPORT;
  395. goto bad;
  396. }
  397. if (ralen + skip + IPCOMP_HLENGTH > maxpacketsize) {
  398. IPCOMPSTAT_INC(ipcomps_toobig);
  399. DPRINTF(("%s: packet in IPCA %s/%08lx got too big "
  400. "(len %u, max len %u)\n", __func__,
  401. ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
  402. (u_long) ntohl(sav->spi),
  403. ralen + skip + IPCOMP_HLENGTH, maxpacketsize));
  404. error = EMSGSIZE;
  405. goto bad;
  406. }
  407. /* Update the counters */
  408. IPCOMPSTAT_ADD(ipcomps_obytes, m->m_pkthdr.len - skip);
  409. m = m_unshare(m, M_NOWAIT);
  410. if (m == NULL) {
  411. IPCOMPSTAT_INC(ipcomps_hdrops);
  412. DPRINTF(("%s: cannot clone mbuf chain, IPCA %s/%08lx\n",
  413. __func__, ipsec_address(&sav->sah->saidx.dst, buf,
  414. sizeof(buf)), (u_long) ntohl(sav->spi)));
  415. error = ENOBUFS;
  416. goto bad;
  417. }
  418. /* Ok now, we can pass to the crypto processing. */
  419. SECASVAR_RLOCK(sav);
  420. cryptoid = sav->tdb_cryptoid;
  421. SECASVAR_RUNLOCK(sav);
  422. /* Get crypto descriptors */
  423. crp = crypto_getreq(cryptoid, M_NOWAIT);
  424. if (crp == NULL) {
  425. IPCOMPSTAT_INC(ipcomps_crypto);
  426. DPRINTF(("%s: failed to acquire crypto descriptor\n",__func__));
  427. error = ENOBUFS;
  428. goto bad;
  429. }
  430. /* Compression descriptor */
  431. crp->crp_op = CRYPTO_OP_COMPRESS;
  432. crp->crp_payload_start = skip;
  433. crp->crp_payload_length = ralen;
  434. /* IPsec-specific opaque crypto info */
  435. xd = malloc(sizeof(struct xform_data), M_IPCOMP, M_NOWAIT | M_ZERO);
  436. if (xd == NULL) {
  437. IPCOMPSTAT_INC(ipcomps_crypto);
  438. DPRINTF(("%s: failed to allocate xform_data\n", __func__));
  439. crypto_freereq(crp);
  440. error = ENOBUFS;
  441. goto bad;
  442. }
  443. xd->sp = sp;
  444. xd->sav = sav;
  445. xd->idx = idx;
  446. xd->skip = skip;
  447. xd->protoff = protoff;
  448. xd->vnet = curvnet;
  449. xd->cryptoid = cryptoid;
  450. /* Crypto operation descriptor */
  451. crp->crp_flags = CRYPTO_F_CBIFSYNC;
  452. crypto_use_mbuf(crp, m);
  453. crp->crp_callback = ipcomp_output_cb;
  454. crp->crp_opaque = xd;
  455. return crypto_dispatch(crp);
  456. bad:
  457. if (m)
  458. m_freem(m);
  459. key_freesav(&sav);
  460. key_freesp(&sp);
  461. return (error);
  462. }
  463. /*
  464. * IPComp output callback from the crypto driver.
  465. */
  466. static int
  467. ipcomp_output_cb(struct cryptop *crp)
  468. {
  469. IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
  470. struct xform_data *xd;
  471. struct secpolicy *sp;
  472. struct secasvar *sav;
  473. struct mbuf *m;
  474. crypto_session_t cryptoid;
  475. u_int idx;
  476. int error, skip, protoff;
  477. m = crp->crp_buf.cb_mbuf;
  478. xd = crp->crp_opaque;
  479. CURVNET_SET(xd->vnet);
  480. idx = xd->idx;
  481. sp = xd->sp;
  482. sav = xd->sav;
  483. skip = xd->skip;
  484. protoff = xd->protoff;
  485. cryptoid = xd->cryptoid;
  486. /* Check for crypto errors */
  487. if (crp->crp_etype) {
  488. if (crp->crp_etype == EAGAIN) {
  489. /* Reset the session ID */
  490. if (ipsec_updateid(sav, &crp->crp_session, &cryptoid) != 0)
  491. crypto_freesession(cryptoid);
  492. xd->cryptoid = crp->crp_session;
  493. CURVNET_RESTORE();
  494. return (crypto_dispatch(crp));
  495. }
  496. IPCOMPSTAT_INC(ipcomps_noxform);
  497. DPRINTF(("%s: crypto error %d\n", __func__, crp->crp_etype));
  498. error = crp->crp_etype;
  499. goto bad;
  500. }
  501. /* Shouldn't happen... */
  502. if (m == NULL) {
  503. IPCOMPSTAT_INC(ipcomps_crypto);
  504. DPRINTF(("%s: bogus return buffer from crypto\n", __func__));
  505. error = EINVAL;
  506. goto bad;
  507. }
  508. IPCOMPSTAT_INC(ipcomps_hist[sav->alg_comp]);
  509. if (crp->crp_payload_length > crp->crp_olen) {
  510. struct mbuf *mo;
  511. struct ipcomp *ipcomp;
  512. int roff;
  513. uint8_t prot;
  514. /* Compression helped, inject IPCOMP header. */
  515. mo = m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
  516. if (mo == NULL) {
  517. IPCOMPSTAT_INC(ipcomps_wrap);
  518. DPRINTF(("%s: IPCOMP header inject failed "
  519. "for IPCA %s/%08lx\n",
  520. __func__, ipsec_address(&sav->sah->saidx.dst, buf,
  521. sizeof(buf)), (u_long) ntohl(sav->spi)));
  522. error = ENOBUFS;
  523. goto bad;
  524. }
  525. ipcomp = (struct ipcomp *)(mtod(mo, caddr_t) + roff);
  526. /* Initialize the IPCOMP header */
  527. /* XXX alignment always correct? */
  528. switch (sav->sah->saidx.dst.sa.sa_family) {
  529. #ifdef INET
  530. case AF_INET:
  531. ipcomp->comp_nxt = mtod(m, struct ip *)->ip_p;
  532. break;
  533. #endif /* INET */
  534. #ifdef INET6
  535. case AF_INET6:
  536. ipcomp->comp_nxt = mtod(m, struct ip6_hdr *)->ip6_nxt;
  537. break;
  538. #endif
  539. }
  540. ipcomp->comp_flags = 0;
  541. ipcomp->comp_cpi = htons((u_int16_t) ntohl(sav->spi));
  542. /* Fix Next Protocol in IPv4/IPv6 header */
  543. prot = IPPROTO_IPCOMP;
  544. m_copyback(m, protoff, sizeof(u_int8_t),
  545. (u_char *)&prot);
  546. /* Adjust the length in the IP header */
  547. switch (sav->sah->saidx.dst.sa.sa_family) {
  548. #ifdef INET
  549. case AF_INET:
  550. mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
  551. break;
  552. #endif /* INET */
  553. #ifdef INET6
  554. case AF_INET6:
  555. mtod(m, struct ip6_hdr *)->ip6_plen =
  556. htons(m->m_pkthdr.len) - sizeof(struct ip6_hdr);
  557. break;
  558. #endif /* INET6 */
  559. default:
  560. IPCOMPSTAT_INC(ipcomps_nopf);
  561. DPRINTF(("%s: unknown/unsupported protocol "
  562. "family %d, IPCA %s/%08lx\n", __func__,
  563. sav->sah->saidx.dst.sa.sa_family,
  564. ipsec_address(&sav->sah->saidx.dst, buf,
  565. sizeof(buf)), (u_long) ntohl(sav->spi)));
  566. error = EPFNOSUPPORT;
  567. goto bad;
  568. }
  569. } else {
  570. /* Compression was useless, we have lost time. */
  571. IPCOMPSTAT_INC(ipcomps_uncompr);
  572. DPRINTF(("%s: compressions was useless %d <= %d\n",
  573. __func__, crp->crp_payload_length, crp->crp_olen));
  574. /* XXX remember state to not compress the next couple
  575. * of packets, RFC 3173, 2.2. Non-Expansion Policy */
  576. }
  577. /* Release the crypto descriptor */
  578. free(xd, M_IPCOMP);
  579. crypto_freereq(crp);
  580. /* NB: m is reclaimed by ipsec_process_done. */
  581. error = ipsec_process_done(m, sp, sav, idx);
  582. CURVNET_RESTORE();
  583. return (error);
  584. bad:
  585. if (m)
  586. m_freem(m);
  587. CURVNET_RESTORE();
  588. free(xd, M_IPCOMP);
  589. crypto_freereq(crp);
  590. key_freesav(&sav);
  591. key_freesp(&sp);
  592. return (error);
  593. }
  594. #ifdef INET
  595. static int
  596. ipcomp4_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
  597. void *arg __unused)
  598. {
  599. union sockaddr_union src, dst;
  600. const struct ip *ip;
  601. if (V_ipcomp_enable == 0)
  602. return (0);
  603. if (proto != IPPROTO_IPV4 && proto != IPPROTO_IPV6)
  604. return (0);
  605. bzero(&src, sizeof(src));
  606. bzero(&dst, sizeof(dst));
  607. src.sa.sa_family = dst.sa.sa_family = AF_INET;
  608. src.sin.sin_len = dst.sin.sin_len = sizeof(struct sockaddr_in);
  609. ip = mtod(m, const struct ip *);
  610. src.sin.sin_addr = ip->ip_src;
  611. dst.sin.sin_addr = ip->ip_dst;
  612. return (ipcomp_encapcheck(&src, &dst));
  613. }
  614. static const struct encaptab *ipe4_cookie = NULL;
  615. static const struct encap_config ipv4_encap_cfg = {
  616. .proto = -1,
  617. .min_length = sizeof(struct ip),
  618. .exact_match = sizeof(in_addr_t) << 4,
  619. .check = ipcomp4_nonexp_encapcheck,
  620. .input = ipcomp_nonexp_input
  621. };
  622. #endif
  623. #ifdef INET6
  624. static int
  625. ipcomp6_nonexp_encapcheck(const struct mbuf *m, int off, int proto,
  626. void *arg __unused)
  627. {
  628. union sockaddr_union src, dst;
  629. const struct ip6_hdr *ip6;
  630. if (V_ipcomp_enable == 0)
  631. return (0);
  632. if (proto != IPPROTO_IPV4 && proto != IPPROTO_IPV6)
  633. return (0);
  634. bzero(&src, sizeof(src));
  635. bzero(&dst, sizeof(dst));
  636. src.sa.sa_family = dst.sa.sa_family = AF_INET;
  637. src.sin6.sin6_len = dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
  638. ip6 = mtod(m, const struct ip6_hdr *);
  639. src.sin6.sin6_addr = ip6->ip6_src;
  640. dst.sin6.sin6_addr = ip6->ip6_dst;
  641. if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6.sin6_addr)) {
  642. /* XXX: sa6_recoverscope() */
  643. src.sin6.sin6_scope_id =
  644. ntohs(src.sin6.sin6_addr.s6_addr16[1]);
  645. src.sin6.sin6_addr.s6_addr16[1] = 0;
  646. }
  647. if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6.sin6_addr)) {
  648. /* XXX: sa6_recoverscope() */
  649. dst.sin6.sin6_scope_id =
  650. ntohs(dst.sin6.sin6_addr.s6_addr16[1]);
  651. dst.sin6.sin6_addr.s6_addr16[1] = 0;
  652. }
  653. return (ipcomp_encapcheck(&src, &dst));
  654. }
  655. static const struct encaptab *ipe6_cookie = NULL;
  656. static const struct encap_config ipv6_encap_cfg = {
  657. .proto = -1,
  658. .min_length = sizeof(struct ip6_hdr),
  659. .exact_match = sizeof(struct in6_addr) << 4,
  660. .check = ipcomp6_nonexp_encapcheck,
  661. .input = ipcomp_nonexp_input
  662. };
  663. #endif
  664. static struct xformsw ipcomp_xformsw = {
  665. .xf_type = XF_IPCOMP,
  666. .xf_name = "IPcomp",
  667. .xf_init = ipcomp_init,
  668. .xf_cleanup = ipcomp_cleanup,
  669. .xf_input = ipcomp_input,
  670. .xf_output = ipcomp_output,
  671. };
  672. static void
  673. ipcomp_attach(void)
  674. {
  675. #ifdef INET
  676. ipe4_cookie = ip_encap_attach(&ipv4_encap_cfg, NULL, M_WAITOK);
  677. #endif
  678. #ifdef INET6
  679. ipe6_cookie = ip6_encap_attach(&ipv6_encap_cfg, NULL, M_WAITOK);
  680. #endif
  681. xform_attach(&ipcomp_xformsw);
  682. }
  683. static void
  684. ipcomp_detach(void)
  685. {
  686. #ifdef INET
  687. ip_encap_detach(ipe4_cookie);
  688. #endif
  689. #ifdef INET6
  690. ip6_encap_detach(ipe6_cookie);
  691. #endif
  692. xform_detach(&ipcomp_xformsw);
  693. }
  694. SYSINIT(ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
  695. ipcomp_attach, NULL);
  696. SYSUNINIT(ipcomp_xform_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
  697. ipcomp_detach, NULL);