PageRenderTime 17ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/openbsd/sys/netinet/raw_ip.c

https://github.com/kame/kame
C | 491 lines | 331 code | 39 blank | 121 comment | 88 complexity | f9c437a67a7102868c4fb9b6855c1892 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. /* $OpenBSD: raw_ip.c,v 1.32 2003/12/21 14:57:19 markus Exp $ */
  2. /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */
  3. /*
  4. * Copyright (c) 1982, 1986, 1988, 1993
  5. * The Regents of the University of California. All rights reserved.
  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. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the University nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
  32. *
  33. * NRL grants permission for redistribution and use in source and binary
  34. * forms, with or without modification, of the software and documentation
  35. * created at NRL provided that the following conditions are met:
  36. *
  37. * 1. Redistributions of source code must retain the above copyright
  38. * notice, this list of conditions and the following disclaimer.
  39. * 2. Redistributions in binary form must reproduce the above copyright
  40. * notice, this list of conditions and the following disclaimer in the
  41. * documentation and/or other materials provided with the distribution.
  42. * 3. All advertising materials mentioning features or use of this software
  43. * must display the following acknowledgements:
  44. * This product includes software developed by the University of
  45. * California, Berkeley and its contributors.
  46. * This product includes software developed at the Information
  47. * Technology Division, US Naval Research Laboratory.
  48. * 4. Neither the name of the NRL nor the names of its contributors
  49. * may be used to endorse or promote products derived from this software
  50. * without specific prior written permission.
  51. *
  52. * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
  53. * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  54. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  55. * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
  56. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  57. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  58. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  59. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  60. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  61. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  62. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  63. *
  64. * The views and conclusions contained in the software and documentation
  65. * are those of the authors and should not be interpreted as representing
  66. * official policies, either expressed or implied, of the US Naval
  67. * Research Laboratory (NRL).
  68. */
  69. #include <sys/param.h>
  70. #include <sys/systm.h>
  71. #include <sys/mbuf.h>
  72. #include <sys/socket.h>
  73. #include <sys/protosw.h>
  74. #include <sys/socketvar.h>
  75. #include <net/if.h>
  76. #include <net/route.h>
  77. #include <netinet/in.h>
  78. #include <netinet/in_systm.h>
  79. #include <netinet/ip.h>
  80. #include <netinet/ip_mroute.h>
  81. #include <netinet/ip_var.h>
  82. #include <netinet/in_pcb.h>
  83. #include <netinet/in_var.h>
  84. #include <netinet/ip_icmp.h>
  85. struct inpcbtable rawcbtable;
  86. /*
  87. * Nominal space allocated to a raw ip socket.
  88. */
  89. #define RIPSNDQ 8192
  90. #define RIPRCVQ 8192
  91. /*
  92. * Raw interface to IP protocol.
  93. */
  94. /*
  95. * Initialize raw connection block q.
  96. */
  97. void
  98. rip_init()
  99. {
  100. in_pcbinit(&rawcbtable, 1);
  101. }
  102. struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
  103. /*
  104. * Setup generic address and protocol structures
  105. * for raw_input routine, then pass them along with
  106. * mbuf chain.
  107. */
  108. void
  109. rip_input(struct mbuf *m, ...)
  110. {
  111. struct ip *ip = mtod(m, struct ip *);
  112. struct inpcb *inp;
  113. struct socket *last = 0;
  114. ripsrc.sin_addr = ip->ip_src;
  115. CIRCLEQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
  116. #ifdef INET6
  117. if (inp->inp_flags & INP_IPV6)
  118. continue;
  119. #endif
  120. if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
  121. continue;
  122. if (inp->inp_laddr.s_addr &&
  123. inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
  124. continue;
  125. if (inp->inp_faddr.s_addr &&
  126. inp->inp_faddr.s_addr != ip->ip_src.s_addr)
  127. continue;
  128. if (last) {
  129. struct mbuf *n;
  130. if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  131. if (sbappendaddr(&last->so_rcv,
  132. sintosa(&ripsrc), n,
  133. (struct mbuf *)0) == 0)
  134. /* should notify about lost packet */
  135. m_freem(n);
  136. else
  137. sorwakeup(last);
  138. }
  139. }
  140. last = inp->inp_socket;
  141. }
  142. if (last) {
  143. if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m,
  144. (struct mbuf *)0) == 0)
  145. m_freem(m);
  146. else
  147. sorwakeup(last);
  148. } else {
  149. if (ip->ip_p != IPPROTO_ICMP)
  150. icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
  151. else
  152. m_freem(m);
  153. ipstat.ips_noproto++;
  154. ipstat.ips_delivered--;
  155. }
  156. }
  157. /*
  158. * Generate IP header and pass packet to ip_output.
  159. * Tack on options user may have setup with control call.
  160. */
  161. int
  162. rip_output(struct mbuf *m, ...)
  163. {
  164. struct socket *so;
  165. u_long dst;
  166. struct ip *ip;
  167. struct inpcb *inp;
  168. int flags;
  169. va_list ap;
  170. va_start(ap, m);
  171. so = va_arg(ap, struct socket *);
  172. dst = va_arg(ap, u_long);
  173. va_end(ap);
  174. inp = sotoinpcb(so);
  175. flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
  176. /*
  177. * If the user handed us a complete IP packet, use it.
  178. * Otherwise, allocate an mbuf for a header and fill it in.
  179. */
  180. if ((inp->inp_flags & INP_HDRINCL) == 0) {
  181. if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
  182. m_freem(m);
  183. return (EMSGSIZE);
  184. }
  185. M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
  186. if (!m)
  187. return (ENOBUFS);
  188. ip = mtod(m, struct ip *);
  189. ip->ip_tos = 0;
  190. ip->ip_off = htons(0);
  191. ip->ip_p = inp->inp_ip.ip_p;
  192. ip->ip_len = htons(m->m_pkthdr.len);
  193. ip->ip_src = inp->inp_laddr;
  194. ip->ip_dst.s_addr = dst;
  195. ip->ip_ttl = MAXTTL;
  196. } else {
  197. if (m->m_pkthdr.len > IP_MAXPACKET) {
  198. m_freem(m);
  199. return (EMSGSIZE);
  200. }
  201. if (m->m_pkthdr.len < sizeof(struct ip)) {
  202. m_freem(m);
  203. return (EINVAL);
  204. }
  205. ip = mtod(m, struct ip *);
  206. /*
  207. * don't allow both user specified and setsockopt options,
  208. * and don't allow packet length sizes that will crash
  209. */
  210. if ((ip->ip_hl != (sizeof (*ip) >> 2) && inp->inp_options) ||
  211. ntohs(ip->ip_len) > m->m_pkthdr.len ||
  212. ntohs(ip->ip_len) < ip->ip_hl << 2) {
  213. m_freem(m);
  214. return (EINVAL);
  215. }
  216. if (ip->ip_id == 0) {
  217. ip->ip_id = htons(ip_randomid());
  218. }
  219. /* XXX prevent ip_output from overwriting header fields */
  220. flags |= IP_RAWOUTPUT;
  221. ipstat.ips_rawout++;
  222. }
  223. #ifdef INET6
  224. /*
  225. * A thought: Even though raw IP shouldn't be able to set IPv6
  226. * multicast options, if it does, the last parameter to
  227. * ip_output should be guarded against v6/v4 problems.
  228. */
  229. #endif
  230. return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
  231. inp->inp_moptions, inp));
  232. }
  233. /*
  234. * Raw IP socket option processing.
  235. */
  236. int
  237. rip_ctloutput(op, so, level, optname, m)
  238. int op;
  239. struct socket *so;
  240. int level, optname;
  241. struct mbuf **m;
  242. {
  243. struct inpcb *inp = sotoinpcb(so);
  244. int error;
  245. if (level != IPPROTO_IP) {
  246. if (op == PRCO_SETOPT && *m)
  247. (void) m_free(*m);
  248. return (EINVAL);
  249. }
  250. switch (optname) {
  251. case IP_HDRINCL:
  252. error = 0;
  253. if (op == PRCO_SETOPT) {
  254. if (*m == 0 || (*m)->m_len < sizeof (int))
  255. error = EINVAL;
  256. else if (*mtod(*m, int *))
  257. inp->inp_flags |= INP_HDRINCL;
  258. else
  259. inp->inp_flags &= ~INP_HDRINCL;
  260. if (*m)
  261. (void)m_free(*m);
  262. } else {
  263. *m = m_get(M_WAIT, M_SOOPTS);
  264. (*m)->m_len = sizeof(int);
  265. *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
  266. }
  267. return (error);
  268. case MRT_INIT:
  269. case MRT_DONE:
  270. case MRT_ADD_VIF:
  271. case MRT_DEL_VIF:
  272. case MRT_ADD_MFC:
  273. case MRT_DEL_MFC:
  274. case MRT_VERSION:
  275. case MRT_ASSERT:
  276. #ifdef MROUTING
  277. switch (op) {
  278. case PRCO_SETOPT:
  279. error = ip_mrouter_set(optname, so, m);
  280. break;
  281. case PRCO_GETOPT:
  282. error = ip_mrouter_get(optname, so, m);
  283. break;
  284. default:
  285. error = EINVAL;
  286. break;
  287. }
  288. return (error);
  289. #else
  290. if (op == PRCO_SETOPT && *m)
  291. m_free(*m);
  292. return (EOPNOTSUPP);
  293. #endif
  294. }
  295. return (ip_ctloutput(op, so, level, optname, m));
  296. }
  297. u_long rip_sendspace = RIPSNDQ;
  298. u_long rip_recvspace = RIPRCVQ;
  299. /*ARGSUSED*/
  300. int
  301. rip_usrreq(so, req, m, nam, control)
  302. struct socket *so;
  303. int req;
  304. struct mbuf *m, *nam, *control;
  305. {
  306. int error = 0;
  307. struct inpcb *inp = sotoinpcb(so);
  308. #ifdef MROUTING
  309. extern struct socket *ip_mrouter;
  310. #endif
  311. if (req == PRU_CONTROL)
  312. return (in_control(so, (u_long)m, (caddr_t)nam,
  313. (struct ifnet *)control));
  314. if (inp == NULL && req != PRU_ATTACH) {
  315. error = EINVAL;
  316. goto release;
  317. }
  318. switch (req) {
  319. case PRU_ATTACH:
  320. if (inp)
  321. panic("rip_attach");
  322. if ((so->so_state & SS_PRIV) == 0) {
  323. error = EACCES;
  324. break;
  325. }
  326. if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
  327. (error = in_pcballoc(so, &rawcbtable)))
  328. break;
  329. inp = (struct inpcb *)so->so_pcb;
  330. inp->inp_ip.ip_p = (long)nam;
  331. break;
  332. case PRU_DISCONNECT:
  333. if ((so->so_state & SS_ISCONNECTED) == 0) {
  334. error = ENOTCONN;
  335. break;
  336. }
  337. /* FALLTHROUGH */
  338. case PRU_ABORT:
  339. soisdisconnected(so);
  340. /* FALLTHROUGH */
  341. case PRU_DETACH:
  342. if (inp == 0)
  343. panic("rip_detach");
  344. #ifdef MROUTING
  345. if (so == ip_mrouter)
  346. ip_mrouter_done();
  347. #endif
  348. in_pcbdetach(inp);
  349. break;
  350. case PRU_BIND:
  351. {
  352. struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  353. if (nam->m_len != sizeof(*addr)) {
  354. error = EINVAL;
  355. break;
  356. }
  357. if ((ifnet.tqh_first == 0) ||
  358. ((addr->sin_family != AF_INET) &&
  359. (addr->sin_family != AF_IMPLINK)) ||
  360. (addr->sin_addr.s_addr &&
  361. ifa_ifwithaddr(sintosa(addr)) == 0)) {
  362. error = EADDRNOTAVAIL;
  363. break;
  364. }
  365. inp->inp_laddr = addr->sin_addr;
  366. break;
  367. }
  368. case PRU_CONNECT:
  369. {
  370. struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  371. if (nam->m_len != sizeof(*addr)) {
  372. error = EINVAL;
  373. break;
  374. }
  375. if (ifnet.tqh_first == 0) {
  376. error = EADDRNOTAVAIL;
  377. break;
  378. }
  379. if ((addr->sin_family != AF_INET) &&
  380. (addr->sin_family != AF_IMPLINK)) {
  381. error = EAFNOSUPPORT;
  382. break;
  383. }
  384. inp->inp_faddr = addr->sin_addr;
  385. soisconnected(so);
  386. break;
  387. }
  388. case PRU_CONNECT2:
  389. error = EOPNOTSUPP;
  390. break;
  391. /*
  392. * Mark the connection as being incapable of further input.
  393. */
  394. case PRU_SHUTDOWN:
  395. socantsendmore(so);
  396. break;
  397. /*
  398. * Ship a packet out. The appropriate raw output
  399. * routine handles any massaging necessary.
  400. */
  401. case PRU_SEND:
  402. {
  403. u_int32_t dst;
  404. if (so->so_state & SS_ISCONNECTED) {
  405. if (nam) {
  406. error = EISCONN;
  407. break;
  408. }
  409. dst = inp->inp_faddr.s_addr;
  410. } else {
  411. if (nam == NULL) {
  412. error = ENOTCONN;
  413. break;
  414. }
  415. dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
  416. }
  417. #ifdef IPSEC
  418. /* XXX Find an IPsec TDB */
  419. #endif
  420. error = rip_output(m, so, dst);
  421. m = NULL;
  422. break;
  423. }
  424. case PRU_SENSE:
  425. /*
  426. * stat: don't bother with a blocksize.
  427. */
  428. return (0);
  429. /*
  430. * Not supported.
  431. */
  432. case PRU_RCVOOB:
  433. case PRU_RCVD:
  434. case PRU_LISTEN:
  435. case PRU_ACCEPT:
  436. case PRU_SENDOOB:
  437. error = EOPNOTSUPP;
  438. break;
  439. case PRU_SOCKADDR:
  440. in_setsockaddr(inp, nam);
  441. break;
  442. case PRU_PEERADDR:
  443. in_setpeeraddr(inp, nam);
  444. break;
  445. default:
  446. panic("rip_usrreq");
  447. }
  448. release:
  449. if (m != NULL)
  450. m_freem(m);
  451. return (error);
  452. }