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

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1982, 1986, 1991, 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.  * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
  34.  */
  35. #include <sys/param.h>
  36. #include <sys/systm.h>
  37. #include <sys/malloc.h>
  38. #include <sys/mbuf.h>
  39. #include <sys/protosw.h>
  40. #include <sys/socket.h>
  41. #include <sys/socketvar.h>
  42. #include <sys/ioctl.h>
  43. #include <sys/errno.h>
  44. #include <sys/time.h>
  45. #include <sys/proc.h>
  46. #include <net/if.h>
  47. #include <net/route.h>
  48. #include <netinet/in.h>
  49. #include <netinet/in_systm.h>
  50. #include <netinet/ip.h>
  51. #include <netinet/in_pcb.h>
  52. #include <netinet/in_var.h>
  53. #include <netinet/ip_var.h>
  54. struct in_addr zeroin_addr;
  55. int
  56. in_pcballoc(so, head)
  57. struct socket *so;
  58. struct inpcb *head;
  59. {
  60. register struct inpcb *inp;
  61. MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_WAITOK);
  62. if (inp == NULL)
  63. return (ENOBUFS);
  64. bzero((caddr_t)inp, sizeof(*inp));
  65. inp->inp_head = head;
  66. inp->inp_socket = so;
  67. insque(inp, head);
  68. so->so_pcb = (caddr_t)inp;
  69. return (0);
  70. }
  71. int
  72. in_pcbbind(inp, nam)
  73. register struct inpcb *inp;
  74. struct mbuf *nam;
  75. {
  76. register struct socket *so = inp->inp_socket;
  77. register struct inpcb *head = inp->inp_head;
  78. register struct sockaddr_in *sin;
  79. struct proc *p = curproc; /* XXX */
  80. u_short lport = 0;
  81. int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
  82. int error;
  83. if (in_ifaddr == 0)
  84. return (EADDRNOTAVAIL);
  85. if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
  86. return (EINVAL);
  87. if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
  88.     ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
  89.      (so->so_options & SO_ACCEPTCONN) == 0))
  90. wild = INPLOOKUP_WILDCARD;
  91. if (nam) {
  92. sin = mtod(nam, struct sockaddr_in *);
  93. if (nam->m_len != sizeof (*sin))
  94. return (EINVAL);
  95. #ifdef notdef
  96. /*
  97.  * We should check the family, but old programs
  98.  * incorrectly fail to initialize it.
  99.  */
  100. if (sin->sin_family != AF_INET)
  101. return (EAFNOSUPPORT);
  102. #endif
  103. lport = sin->sin_port;
  104. if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
  105. /*
  106.  * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
  107.  * allow complete duplication of binding if
  108.  * SO_REUSEPORT is set, or if SO_REUSEADDR is set
  109.  * and a multicast address is bound on both
  110.  * new and duplicated sockets.
  111.  */
  112. if (so->so_options & SO_REUSEADDR)
  113. reuseport = SO_REUSEADDR|SO_REUSEPORT;
  114. } else if (sin->sin_addr.s_addr != INADDR_ANY) {
  115. sin->sin_port = 0; /* yech... */
  116. if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
  117. return (EADDRNOTAVAIL);
  118. }
  119. if (lport) {
  120. struct inpcb *t;
  121. /* GROSS */
  122. if (ntohs(lport) < IPPORT_RESERVED &&
  123.     (error = suser(p->p_ucred, &p->p_acflag)))
  124. return (error);
  125. t = in_pcblookup(head, zeroin_addr, 0,
  126.     sin->sin_addr, lport, wild);
  127. if (t && (reuseport & t->inp_socket->so_options) == 0)
  128. return (EADDRINUSE);
  129. }
  130. inp->inp_laddr = sin->sin_addr;
  131. }
  132. if (lport == 0)
  133. do {
  134. if (head->inp_lport++ < IPPORT_RESERVED ||
  135.     head->inp_lport > IPPORT_USERRESERVED)
  136. head->inp_lport = IPPORT_RESERVED;
  137. lport = htons(head->inp_lport);
  138. } while (in_pcblookup(head,
  139.     zeroin_addr, 0, inp->inp_laddr, lport, wild));
  140. inp->inp_lport = lport;
  141. return (0);
  142. }
  143. /*
  144.  * Connect from a socket to a specified address.
  145.  * Both address and port must be specified in argument sin.
  146.  * If don't have a local address for this socket yet,
  147.  * then pick one.
  148.  */
  149. int
  150. in_pcbconnect(inp, nam)
  151. register struct inpcb *inp;
  152. struct mbuf *nam;
  153. {
  154. struct in_ifaddr *ia;
  155. struct sockaddr_in *ifaddr;
  156. register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
  157. if (nam->m_len != sizeof (*sin))
  158. return (EINVAL);
  159. if (sin->sin_family != AF_INET)
  160. return (EAFNOSUPPORT);
  161. if (sin->sin_port == 0)
  162. return (EADDRNOTAVAIL);
  163. if (in_ifaddr) {
  164. /*
  165.  * If the destination address is INADDR_ANY,
  166.  * use the primary local address.
  167.  * If the supplied address is INADDR_BROADCAST,
  168.  * and the primary interface supports broadcast,
  169.  * choose the broadcast address for that interface.
  170.  */
  171. #define satosin(sa) ((struct sockaddr_in *)(sa))
  172. #define sintosa(sin) ((struct sockaddr *)(sin))
  173. #define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
  174. if (sin->sin_addr.s_addr == INADDR_ANY)
  175.     sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
  176. else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
  177.   (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
  178.     sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
  179. }
  180. if (inp->inp_laddr.s_addr == INADDR_ANY) {
  181. register struct route *ro;
  182. ia = (struct in_ifaddr *)0;
  183. /* 
  184.  * If route is known or can be allocated now,
  185.  * our src addr is taken from the i/f, else punt.
  186.  */
  187. ro = &inp->inp_route;
  188. if (ro->ro_rt &&
  189.     (satosin(&ro->ro_dst)->sin_addr.s_addr !=
  190. sin->sin_addr.s_addr || 
  191.     inp->inp_socket->so_options & SO_DONTROUTE)) {
  192. RTFREE(ro->ro_rt);
  193. ro->ro_rt = (struct rtentry *)0;
  194. }
  195. if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
  196.     (ro->ro_rt == (struct rtentry *)0 ||
  197.     ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
  198. /* No route yet, so try to acquire one */
  199. ro->ro_dst.sa_family = AF_INET;
  200. ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
  201. ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
  202. sin->sin_addr;
  203. rtalloc(ro);
  204. }
  205. /*
  206.  * If we found a route, use the address
  207.  * corresponding to the outgoing interface
  208.  * unless it is the loopback (in case a route
  209.  * to our address on another net goes to loopback).
  210.  */
  211. if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
  212. ia = ifatoia(ro->ro_rt->rt_ifa);
  213. if (ia == 0) {
  214. u_short fport = sin->sin_port;
  215. sin->sin_port = 0;
  216. ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
  217. if (ia == 0)
  218. ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
  219. sin->sin_port = fport;
  220. if (ia == 0)
  221. ia = in_ifaddr;
  222. if (ia == 0)
  223. return (EADDRNOTAVAIL);
  224. }
  225. /*
  226.  * If the destination address is multicast and an outgoing
  227.  * interface has been set as a multicast option, use the
  228.  * address of that interface as our source address.
  229.  */
  230. if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
  231.     inp->inp_moptions != NULL) {
  232. struct ip_moptions *imo;
  233. struct ifnet *ifp;
  234. imo = inp->inp_moptions;
  235. if (imo->imo_multicast_ifp != NULL) {
  236. ifp = imo->imo_multicast_ifp;
  237. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  238. if (ia->ia_ifp == ifp)
  239. break;
  240. if (ia == 0)
  241. return (EADDRNOTAVAIL);
  242. }
  243. }
  244. ifaddr = (struct sockaddr_in *)&ia->ia_addr;
  245. }
  246. if (in_pcblookup(inp->inp_head,
  247.     sin->sin_addr,
  248.     sin->sin_port,
  249.     inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
  250.     inp->inp_lport,
  251.     0))
  252. return (EADDRINUSE);
  253. if (inp->inp_laddr.s_addr == INADDR_ANY) {
  254. if (inp->inp_lport == 0)
  255. (void)in_pcbbind(inp, (struct mbuf *)0);
  256. inp->inp_laddr = ifaddr->sin_addr;
  257. }
  258. inp->inp_faddr = sin->sin_addr;
  259. inp->inp_fport = sin->sin_port;
  260. return (0);
  261. }
  262. int
  263. in_pcbdisconnect(inp)
  264. struct inpcb *inp;
  265. {
  266. inp->inp_faddr.s_addr = INADDR_ANY;
  267. inp->inp_fport = 0;
  268. if (inp->inp_socket->so_state & SS_NOFDREF)
  269. in_pcbdetach(inp);
  270. }
  271. int
  272. in_pcbdetach(inp)
  273. struct inpcb *inp;
  274. {
  275. struct socket *so = inp->inp_socket;
  276. so->so_pcb = 0;
  277. sofree(so);
  278. if (inp->inp_options)
  279. (void)m_free(inp->inp_options);
  280. if (inp->inp_route.ro_rt)
  281. rtfree(inp->inp_route.ro_rt);
  282. ip_freemoptions(inp->inp_moptions);
  283. remque(inp);
  284. FREE(inp, M_PCB);
  285. }
  286. int
  287. in_setsockaddr(inp, nam)
  288. register struct inpcb *inp;
  289. struct mbuf *nam;
  290. {
  291. register struct sockaddr_in *sin;
  292. nam->m_len = sizeof (*sin);
  293. sin = mtod(nam, struct sockaddr_in *);
  294. bzero((caddr_t)sin, sizeof (*sin));
  295. sin->sin_family = AF_INET;
  296. sin->sin_len = sizeof(*sin);
  297. sin->sin_port = inp->inp_lport;
  298. sin->sin_addr = inp->inp_laddr;
  299. }
  300. int
  301. in_setpeeraddr(inp, nam)
  302. struct inpcb *inp;
  303. struct mbuf *nam;
  304. {
  305. register struct sockaddr_in *sin;
  306. nam->m_len = sizeof (*sin);
  307. sin = mtod(nam, struct sockaddr_in *);
  308. bzero((caddr_t)sin, sizeof (*sin));
  309. sin->sin_family = AF_INET;
  310. sin->sin_len = sizeof(*sin);
  311. sin->sin_port = inp->inp_fport;
  312. sin->sin_addr = inp->inp_faddr;
  313. }
  314. /*
  315.  * Pass some notification to all connections of a protocol
  316.  * associated with address dst.  The local address and/or port numbers
  317.  * may be specified to limit the search.  The "usual action" will be
  318.  * taken, depending on the ctlinput cmd.  The caller must filter any
  319.  * cmds that are uninteresting (e.g., no error in the map).
  320.  * Call the protocol specific routine (if any) to report
  321.  * any errors for each matching socket.
  322.  *
  323.  * Must be called at splnet.
  324.  */
  325. int
  326. in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
  327. struct inpcb *head;
  328. struct sockaddr *dst;
  329. u_int fport_arg, lport_arg;
  330. struct in_addr laddr;
  331. int cmd;
  332. void (*notify) __P((struct inpcb *, int));
  333. {
  334. extern u_char inetctlerrmap[];
  335. register struct inpcb *inp, *oinp;
  336. struct in_addr faddr;
  337. u_short fport = fport_arg, lport = lport_arg;
  338. int errno;
  339. if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
  340. return;
  341. faddr = ((struct sockaddr_in *)dst)->sin_addr;
  342. if (faddr.s_addr == INADDR_ANY)
  343. return;
  344. /*
  345.  * Redirects go to all references to the destination,
  346.  * and use in_rtchange to invalidate the route cache.
  347.  * Dead host indications: notify all references to the destination.
  348.  * Otherwise, if we have knowledge of the local port and address,
  349.  * deliver only to that socket.
  350.  */
  351. if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
  352. fport = 0;
  353. lport = 0;
  354. laddr.s_addr = 0;
  355. if (cmd != PRC_HOSTDEAD)
  356. notify = in_rtchange;
  357. }
  358. errno = inetctlerrmap[cmd];
  359. for (inp = head->inp_next; inp != head;) {
  360. if (inp->inp_faddr.s_addr != faddr.s_addr ||
  361.     inp->inp_socket == 0 ||
  362.     (lport && inp->inp_lport != lport) ||
  363.     (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
  364.     (fport && inp->inp_fport != fport)) {
  365. inp = inp->inp_next;
  366. continue;
  367. }
  368. oinp = inp;
  369. inp = inp->inp_next;
  370. if (notify)
  371. (*notify)(oinp, errno);
  372. }
  373. }
  374. /*
  375.  * Check for alternatives when higher level complains
  376.  * about service problems.  For now, invalidate cached
  377.  * routing information.  If the route was created dynamically
  378.  * (by a redirect), time to try a default gateway again.
  379.  */
  380. int
  381. in_losing(inp)
  382. struct inpcb *inp;
  383. {
  384. register struct rtentry *rt;
  385. struct rt_addrinfo info;
  386. if ((rt = inp->inp_route.ro_rt)) {
  387. inp->inp_route.ro_rt = 0;
  388. bzero((caddr_t)&info, sizeof(info));
  389. info.rti_info[RTAX_DST] =
  390. (struct sockaddr *)&inp->inp_route.ro_dst;
  391. info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  392. info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  393. rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
  394. if (rt->rt_flags & RTF_DYNAMIC)
  395. (void) rtrequest(RTM_DELETE, rt_key(rt),
  396. rt->rt_gateway, rt_mask(rt), rt->rt_flags, 
  397. (struct rtentry **)0);
  398. else 
  399. /*
  400.  * A new route can be allocated
  401.  * the next time output is attempted.
  402.  */
  403. rtfree(rt);
  404. }
  405. }
  406. /*
  407.  * After a routing change, flush old routing
  408.  * and allocate a (hopefully) better one.
  409.  */
  410. void
  411. in_rtchange(inp, errno)
  412. register struct inpcb *inp;
  413. int errno;
  414. {
  415. if (inp->inp_route.ro_rt) {
  416. rtfree(inp->inp_route.ro_rt);
  417. inp->inp_route.ro_rt = 0;
  418. /*
  419.  * A new route can be allocated the next time
  420.  * output is attempted.
  421.  */
  422. }
  423. }
  424. struct inpcb *
  425. in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
  426. struct inpcb *head;
  427. struct in_addr faddr, laddr;
  428. u_int fport_arg, lport_arg;
  429. int flags;
  430. {
  431. register struct inpcb *inp, *match = 0;
  432. int matchwild = 3, wildcard;
  433. u_short fport = fport_arg, lport = lport_arg;
  434. for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
  435. if (inp->inp_lport != lport)
  436. continue;
  437. wildcard = 0;
  438. if (inp->inp_laddr.s_addr != INADDR_ANY) {
  439. if (laddr.s_addr == INADDR_ANY)
  440. wildcard++;
  441. else if (inp->inp_laddr.s_addr != laddr.s_addr)
  442. continue;
  443. } else {
  444. if (laddr.s_addr != INADDR_ANY)
  445. wildcard++;
  446. }
  447. if (inp->inp_faddr.s_addr != INADDR_ANY) {
  448. if (faddr.s_addr == INADDR_ANY)
  449. wildcard++;
  450. else if (inp->inp_faddr.s_addr != faddr.s_addr ||
  451.     inp->inp_fport != fport)
  452. continue;
  453. } else {
  454. if (faddr.s_addr != INADDR_ANY)
  455. wildcard++;
  456. }
  457. if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
  458. continue;
  459. if (wildcard < matchwild) {
  460. match = inp;
  461. matchwild = wildcard;
  462. if (matchwild == 0)
  463. break;
  464. }
  465. }
  466. return (match);
  467. }