RAW_IP.C
上传用户:tjbfgc
上传日期:2013-03-31
资源大小:140k
文件大小:9k
源码类别:

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1982, 1986, 1988, 1993
  3.  * The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  * This product includes software developed by the University of
  16.  * California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
  34.  */
  35. #include <sys/param.h>
  36. #include <sys/malloc.h>
  37. #include <sys/mbuf.h>
  38. #include <sys/socket.h>
  39. #include <sys/protosw.h>
  40. #include <sys/socketvar.h>
  41. #include <sys/errno.h>
  42. #include <sys/systm.h>
  43. #include <net/if.h>
  44. #include <net/route.h>
  45. #include <netinet/in.h>
  46. #include <netinet/in_systm.h>
  47. #include <netinet/ip.h>
  48. #include <netinet/ip_var.h>
  49. #include <netinet/ip_mroute.h>
  50. #include <netinet/in_pcb.h>
  51. struct inpcb rawinpcb;
  52. /*
  53.  * Nominal space allocated to a raw ip socket.
  54.  */
  55. #define RIPSNDQ 8192
  56. #define RIPRCVQ 8192
  57. /*
  58.  * Raw interface to IP protocol.
  59.  */
  60. /*
  61.  * Initialize raw connection block q.
  62.  */
  63. void
  64. rip_init()
  65. {
  66. rawinpcb.inp_next = rawinpcb.inp_prev = &rawinpcb;
  67. }
  68. struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
  69. /*
  70.  * Setup generic address and protocol structures
  71.  * for raw_input routine, then pass them along with
  72.  * mbuf chain.
  73.  */
  74. void
  75. rip_input(m)
  76. struct mbuf *m;
  77. {
  78. register struct ip *ip = mtod(m, struct ip *);
  79. register struct inpcb *inp;
  80. struct socket *last = 0;
  81. ripsrc.sin_addr = ip->ip_src;
  82. for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) {
  83. if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
  84. continue;
  85. if (inp->inp_laddr.s_addr &&
  86.     inp->inp_laddr.s_addr == ip->ip_dst.s_addr)
  87. continue;
  88. if (inp->inp_faddr.s_addr &&
  89.     inp->inp_faddr.s_addr == ip->ip_src.s_addr)
  90. continue;
  91. if (last) {
  92. struct mbuf *n;
  93. if (n = m_copy(m, 0, (int)M_COPYALL)) {
  94. if (sbappendaddr(&last->so_rcv, &ripsrc,
  95.     n, (struct mbuf *)0) == 0)
  96. /* should notify about lost packet */
  97. m_freem(n);
  98. else
  99. sorwakeup(last);
  100. }
  101. }
  102. last = inp->inp_socket;
  103. }
  104. if (last) {
  105. if (sbappendaddr(&last->so_rcv, &ripsrc,
  106.     m, (struct mbuf *)0) == 0)
  107. m_freem(m);
  108. else
  109. sorwakeup(last);
  110. } else {
  111. m_freem(m);
  112. ipstat.ips_noproto++;
  113. ipstat.ips_delivered--;
  114. }
  115. }
  116. /*
  117.  * Generate IP header and pass packet to ip_output.
  118.  * Tack on options user may have setup with control call.
  119.  */
  120. int
  121. rip_output(m, so, dst)
  122. register struct mbuf *m;
  123. struct socket *so;
  124. u_long dst;
  125. {
  126. register struct ip *ip;
  127. register struct inpcb *inp = sotoinpcb(so);
  128. struct mbuf *opts;
  129. int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
  130. /*
  131.  * If the user handed us a complete IP packet, use it.
  132.  * Otherwise, allocate an mbuf for a header and fill it in.
  133.  */
  134. if ((inp->inp_flags & INP_HDRINCL) == 0) {
  135. M_PREPEND(m, sizeof(struct ip), M_WAIT);
  136. ip = mtod(m, struct ip *);
  137. ip->ip_tos = 0;
  138. ip->ip_off = 0;
  139. ip->ip_p = inp->inp_ip.ip_p;
  140. ip->ip_len = m->m_pkthdr.len;
  141. ip->ip_src = inp->inp_laddr;
  142. ip->ip_dst.s_addr = dst;
  143. ip->ip_ttl = MAXTTL;
  144. opts = inp->inp_options;
  145. } else {
  146. ip = mtod(m, struct ip *);
  147. if (ip->ip_id == 0)
  148. ip->ip_id = htons(ip_id++);
  149. opts = NULL;
  150. /* XXX prevent ip_output from overwriting header fields */
  151. flags |= IP_RAWOUTPUT;
  152. ipstat.ips_rawout++;
  153. }
  154. return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions));
  155. }
  156. /*
  157.  * Raw IP socket option processing.
  158.  */
  159. int
  160. rip_ctloutput(op, so, level, optname, m)
  161. int op;
  162. struct socket *so;
  163. int level, optname;
  164. struct mbuf **m;
  165. {
  166. register struct inpcb *inp = sotoinpcb(so);
  167. register int error;
  168. if (level != IPPROTO_IP)
  169. return (EINVAL);
  170. switch (optname) {
  171. case IP_HDRINCL:
  172. if (op == PRCO_SETOPT || op == PRCO_GETOPT) {
  173. if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
  174. return (EINVAL);
  175. if (op == PRCO_SETOPT) {
  176. if (*mtod(*m, int *))
  177. inp->inp_flags |= INP_HDRINCL;
  178. else
  179. inp->inp_flags &= ~INP_HDRINCL;
  180. (void)m_free(*m);
  181. } else {
  182. (*m)->m_len = sizeof (int);
  183. *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
  184. }
  185. return (0);
  186. }
  187. break;
  188. case DVMRP_INIT:
  189. case DVMRP_DONE:
  190. case DVMRP_ADD_VIF:
  191. case DVMRP_DEL_VIF:
  192. case DVMRP_ADD_LGRP:
  193. case DVMRP_DEL_LGRP:
  194. case DVMRP_ADD_MRT:
  195. case DVMRP_DEL_MRT:
  196. #ifdef MROUTING
  197. if (op == PRCO_SETOPT) {
  198. error = ip_mrouter_cmd(optname, so, *m);
  199. if (*m)
  200. (void)m_free(*m);
  201. } else
  202. error = EINVAL;
  203. return (error);
  204. #else
  205. if (op == PRCO_SETOPT && *m)
  206. (void)m_free(*m);
  207. return (EOPNOTSUPP);
  208. #endif
  209. }
  210. return (ip_ctloutput(op, so, level, optname, m));
  211. }
  212. u_long rip_sendspace = RIPSNDQ;
  213. u_long rip_recvspace = RIPRCVQ;
  214. /*ARGSUSED*/
  215. int
  216. rip_usrreq(so, req, m, nam, control)
  217. register struct socket *so;
  218. int req;
  219. struct mbuf *m, *nam, *control;
  220. {
  221. register int error = 0;
  222. register struct inpcb *inp = sotoinpcb(so);
  223. #ifdef MROUTING
  224. extern struct socket *ip_mrouter;
  225. #endif
  226. switch (req) {
  227. case PRU_ATTACH:
  228. if (inp)
  229. panic("rip_attach");
  230. if ((so->so_state & SS_PRIV) == 0) {
  231. error = EACCES;
  232. break;
  233. }
  234. if ((error = soreserve(so, rip_sendspace, rip_recvspace)) ||
  235.     (error = in_pcballoc(so, &rawinpcb)))
  236. break;
  237. inp = (struct inpcb *)so->so_pcb;
  238. inp->inp_ip.ip_p = (int)nam;
  239. break;
  240. case PRU_DISCONNECT:
  241. if ((so->so_state & SS_ISCONNECTED) == 0) {
  242. error = ENOTCONN;
  243. break;
  244. }
  245. /* FALLTHROUGH */
  246. case PRU_ABORT:
  247. soisdisconnected(so);
  248. /* FALLTHROUGH */
  249. case PRU_DETACH:
  250. if (inp == 0)
  251. panic("rip_detach");
  252. #ifdef MROUTING
  253. if (so == ip_mrouter)
  254. ip_mrouter_done();
  255. #endif
  256. in_pcbdetach(inp);
  257. break;
  258. case PRU_BIND:
  259.     {
  260. struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  261. if (nam->m_len != sizeof(*addr)) {
  262. error = EINVAL;
  263. break;
  264. }
  265. if ((ifnet == 0) ||
  266.     ((addr->sin_family != AF_INET) &&
  267.      (addr->sin_family != AF_IMPLINK)) ||
  268.     (addr->sin_addr.s_addr &&
  269.      ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
  270. error = EADDRNOTAVAIL;
  271. break;
  272. }
  273. inp->inp_laddr = addr->sin_addr;
  274. break;
  275.     }
  276. case PRU_CONNECT:
  277.     {
  278. struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  279. if (nam->m_len != sizeof(*addr)) {
  280. error = EINVAL;
  281. break;
  282. }
  283. if (ifnet == 0) {
  284. error = EADDRNOTAVAIL;
  285. break;
  286. }
  287. if ((addr->sin_family != AF_INET) &&
  288.      (addr->sin_family != AF_IMPLINK)) {
  289. error = EAFNOSUPPORT;
  290. break;
  291. }
  292. inp->inp_faddr = addr->sin_addr;
  293. soisconnected(so);
  294. break;
  295.     }
  296. case PRU_CONNECT2:
  297. error = EOPNOTSUPP;
  298. break;
  299. /*
  300.  * Mark the connection as being incapable of further input.
  301.  */
  302. case PRU_SHUTDOWN:
  303. socantsendmore(so);
  304. break;
  305. /*
  306.  * Ship a packet out.  The appropriate raw output
  307.  * routine handles any massaging necessary.
  308.  */
  309. case PRU_SEND:
  310.     {
  311. register u_long dst;
  312. if (so->so_state & SS_ISCONNECTED) {
  313. if (nam) {
  314. error = EISCONN;
  315. break;
  316. }
  317. dst = inp->inp_faddr.s_addr;
  318. } else {
  319. if (nam == NULL) {
  320. error = ENOTCONN;
  321. break;
  322. }
  323. dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
  324. }
  325. error = rip_output(m, so, dst);
  326. m = NULL;
  327. break;
  328.     }
  329. case PRU_SENSE:
  330. /*
  331.  * stat: don't bother with a blocksize.
  332.  */
  333. return (0);
  334. /*
  335.  * Not supported.
  336.  */
  337. case PRU_RCVOOB:
  338. case PRU_RCVD:
  339. case PRU_LISTEN:
  340. case PRU_ACCEPT:
  341. case PRU_SENDOOB:
  342. error = EOPNOTSUPP;
  343. break;
  344. case PRU_SOCKADDR:
  345. in_setsockaddr(inp, nam);
  346. break;
  347. case PRU_PEERADDR:
  348. in_setpeeraddr(inp, nam);
  349. break;
  350. default:
  351. panic("rip_usrreq");
  352. }
  353. if (m != NULL)
  354. m_freem(m);
  355. return (error);
  356. }