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

网络编程

开发平台:

C/C++

  1. /*
  2.  * Copyright (c) 1982, 1986, 1988, 1990, 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.  * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
  34.  */
  35. #include <sys/param.h>
  36. #include <sys/malloc.h>
  37. #include <sys/mbuf.h>
  38. #include <sys/errno.h>
  39. #include <sys/protosw.h>
  40. #include <sys/socket.h>
  41. #include <sys/socketvar.h>
  42. #include <net/if.h>
  43. #include <net/route.h>
  44. #include <netinet/in.h>
  45. #include <netinet/in_systm.h>
  46. #include <netinet/ip.h>
  47. #include <netinet/in_pcb.h>
  48. #include <netinet/in_var.h>
  49. #include <netinet/ip_var.h>
  50. #ifdef vax
  51. #include <machine/mtpr.h>
  52. #endif
  53. static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
  54. static void ip_mloopback
  55. __P((struct ifnet *, struct mbuf *, struct sockaddr_in *));
  56. /*
  57.  * IP output.  The packet in mbuf chain m contains a skeletal IP
  58.  * header (with len, off, ttl, proto, tos, src, dst).
  59.  * The mbuf chain containing the packet will be freed.
  60.  * The mbuf opt, if present, will not be freed.
  61.  */
  62. int
  63. ip_output(m0, opt, ro, flags, imo)
  64. struct mbuf *m0;
  65. struct mbuf *opt;
  66. struct route *ro;
  67. int flags;
  68. struct ip_moptions *imo;
  69. {
  70. register struct ip *ip, *mhip;
  71. register struct ifnet *ifp;
  72. register struct mbuf *m = m0;
  73. register int hlen = sizeof (struct ip);
  74. int len, off, error = 0;
  75. struct route iproute;
  76. struct sockaddr_in *dst;
  77. struct in_ifaddr *ia;
  78. #ifdef DIAGNOSTIC
  79. if ((m->m_flags & M_PKTHDR) == 0)
  80. panic("ip_output no HDR");
  81. #endif
  82. if (opt) {
  83. m = ip_insertoptions(m, opt, &len);
  84. hlen = len;
  85. }
  86. ip = mtod(m, struct ip *);
  87. /*
  88.  * Fill in IP header.
  89.  */
  90. if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
  91. ip->ip_v = IPVERSION;
  92. ip->ip_off &= IP_DF;
  93. ip->ip_id = htons(ip_id++);
  94. ip->ip_hl = hlen >> 2;
  95. ipstat.ips_localout++;
  96. } else {
  97. hlen = ip->ip_hl << 2;
  98. }
  99. /*
  100.  * Route packet.
  101.  */
  102. if (ro == 0) {
  103. ro = &iproute;
  104. bzero((caddr_t)ro, sizeof (*ro));
  105. }
  106. dst = (struct sockaddr_in *)&ro->ro_dst;
  107. /*
  108.  * If there is a cached route,
  109.  * check that it is to the same destination
  110.  * and is still up.  If not, free it and try again.
  111.  */
  112. if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
  113.    dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
  114. RTFREE(ro->ro_rt);
  115. ro->ro_rt = (struct rtentry *)0;
  116. }
  117. if (ro->ro_rt == 0) {
  118. dst->sin_family = AF_INET;
  119. dst->sin_len = sizeof(*dst);
  120. dst->sin_addr = ip->ip_dst;
  121. }
  122. /*
  123.  * If routing to interface only,
  124.  * short circuit routing lookup.
  125.  */
  126. #define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
  127. #define sintosa(sin) ((struct sockaddr *)(sin))
  128. if (flags & IP_ROUTETOIF) {
  129. if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
  130.     (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
  131. ipstat.ips_noroute++;
  132. error = ENETUNREACH;
  133. goto bad;
  134. }
  135. ifp = ia->ia_ifp;
  136. ip->ip_ttl = 1;
  137. } else {
  138. if (ro->ro_rt == 0)
  139. rtalloc(ro);
  140. if (ro->ro_rt == 0) {
  141. ipstat.ips_noroute++;
  142. error = EHOSTUNREACH;
  143. goto bad;
  144. }
  145. ia = ifatoia(ro->ro_rt->rt_ifa);
  146. ifp = ro->ro_rt->rt_ifp;
  147. ro->ro_rt->rt_use++;
  148. if (ro->ro_rt->rt_flags & RTF_GATEWAY)
  149. dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
  150. }
  151. if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
  152. struct in_multi *inm;
  153. extern struct ifnet loif;
  154. m->m_flags |= M_MCAST;
  155. /*
  156.  * IP destination address is multicast.  Make sure "dst"
  157.  * still points to the address in "ro".  (It may have been
  158.  * changed to point to a gateway address, above.)
  159.  */
  160. dst = (struct sockaddr_in *)&ro->ro_dst;
  161. /*
  162.  * See if the caller provided any multicast options
  163.  */
  164. if (imo != NULL) {
  165. ip->ip_ttl = imo->imo_multicast_ttl;
  166. if (imo->imo_multicast_ifp != NULL)
  167. ifp = imo->imo_multicast_ifp;
  168. } else
  169. ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
  170. /*
  171.  * Confirm that the outgoing interface supports multicast.
  172.  */
  173. if ((ifp->if_flags & IFF_MULTICAST) == 0) {
  174. ipstat.ips_noroute++;
  175. error = ENETUNREACH;
  176. goto bad;
  177. }
  178. /*
  179.  * If source address not specified yet, use address
  180.  * of outgoing interface.
  181.  */
  182. if (ip->ip_src.s_addr == INADDR_ANY) {
  183. register struct in_ifaddr *ia;
  184. for (ia = in_ifaddr; ia; ia = ia->ia_next)
  185. if (ia->ia_ifp == ifp) {
  186. ip->ip_src = IA_SIN(ia)->sin_addr;
  187. break;
  188. }
  189. }
  190. IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
  191. if (inm != NULL &&
  192.    (imo == NULL || imo->imo_multicast_loop)) {
  193. /*
  194.  * If we belong to the destination multicast group
  195.  * on the outgoing interface, and the caller did not
  196.  * forbid loopback, loop back a copy.
  197.  */
  198. ip_mloopback(ifp, m, dst);
  199. }
  200. #ifdef MROUTING
  201. else {
  202. /*
  203.  * If we are acting as a multicast router, perform
  204.  * multicast forwarding as if the packet had just
  205.  * arrived on the interface to which we are about
  206.  * to send.  The multicast forwarding function
  207.  * recursively calls this function, using the
  208.  * IP_FORWARDING flag to prevent infinite recursion.
  209.  *
  210.  * Multicasts that are looped back by ip_mloopback(),
  211.  * above, will be forwarded by the ip_input() routine,
  212.  * if necessary.
  213.  */
  214. extern struct socket *ip_mrouter;
  215. if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
  216. if (ip_mforward(m, ifp) != 0) {
  217. m_freem(m);
  218. goto done;
  219. }
  220. }
  221. }
  222. #endif
  223. /*
  224.  * Multicasts with a time-to-live of zero may be looped-
  225.  * back, above, but must not be transmitted on a network.
  226.  * Also, multicasts addressed to the loopback interface
  227.  * are not sent -- the above call to ip_mloopback() will
  228.  * loop back a copy if this host actually belongs to the
  229.  * destination group on the loopback interface.
  230.  */
  231. if (ip->ip_ttl == 0 || ifp == &loif) {
  232. m_freem(m);
  233. goto done;
  234. }
  235. goto sendit;
  236. }
  237. #ifndef notdef
  238. /*
  239.  * If source address not specified yet, use address
  240.  * of outgoing interface.
  241.  */
  242. if (ip->ip_src.s_addr == INADDR_ANY)
  243. ip->ip_src = IA_SIN(ia)->sin_addr;
  244. #endif
  245. /*
  246.  * Look for broadcast address and
  247.  * and verify user is allowed to send
  248.  * such a packet.
  249.  */
  250. if (in_broadcast(dst->sin_addr, ifp)) {
  251. if ((ifp->if_flags & IFF_BROADCAST) == 0) {
  252. error = EADDRNOTAVAIL;
  253. goto bad;
  254. }
  255. if ((flags & IP_ALLOWBROADCAST) == 0) {
  256. error = EACCES;
  257. goto bad;
  258. }
  259. /* don't allow broadcast messages to be fragmented */
  260. if ((u_short)ip->ip_len > ifp->if_mtu) {
  261. error = EMSGSIZE;
  262. goto bad;
  263. }
  264. m->m_flags |= M_BCAST;
  265. } else
  266. m->m_flags &= ~M_BCAST;
  267. sendit:
  268. /*
  269.  * If small enough for interface, can just send directly.
  270.  */
  271. if ((u_short)ip->ip_len <= ifp->if_mtu) {
  272. ip->ip_len = htons((u_short)ip->ip_len);
  273. ip->ip_off = htons((u_short)ip->ip_off);
  274. ip->ip_sum = 0;
  275. ip->ip_sum = in_cksum(m, hlen);
  276. error = (*ifp->if_output)(ifp, m,
  277. (struct sockaddr *)dst, ro->ro_rt);
  278. goto done;
  279. }
  280. /*
  281.  * Too large for interface; fragment if possible.
  282.  * Must be able to put at least 8 bytes per fragment.
  283.  */
  284. if (ip->ip_off & IP_DF) {
  285. error = EMSGSIZE;
  286. ipstat.ips_cantfrag++;
  287. goto bad;
  288. }
  289. len = (ifp->if_mtu - hlen) &~ 7;
  290. if (len < 8) {
  291. error = EMSGSIZE;
  292. goto bad;
  293. }
  294.     {
  295. int mhlen, firstlen = len;
  296. struct mbuf **mnext = &m->m_nextpkt;
  297. /*
  298.  * Loop through length of segment after first fragment,
  299.  * make new header and copy data of each part and link onto chain.
  300.  */
  301. m0 = m;
  302. mhlen = sizeof (struct ip);
  303. for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
  304. MGETHDR(m, M_DONTWAIT, MT_HEADER);
  305. if (m == 0) {
  306. error = ENOBUFS;
  307. ipstat.ips_odropped++;
  308. goto sendorfree;
  309. }
  310. m->m_data += max_linkhdr;
  311. mhip = mtod(m, struct ip *);
  312. *mhip = *ip;
  313. if (hlen > sizeof (struct ip)) {
  314. mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
  315. mhip->ip_hl = mhlen >> 2;
  316. }
  317. m->m_len = mhlen;
  318. mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
  319. if (ip->ip_off & IP_MF)
  320. mhip->ip_off |= IP_MF;
  321. if (off + len >= (u_short)ip->ip_len)
  322. len = (u_short)ip->ip_len - off;
  323. else
  324. mhip->ip_off |= IP_MF;
  325. mhip->ip_len = htons((u_short)(len + mhlen));
  326. m->m_next = m_copy(m0, off, len);
  327. if (m->m_next == 0) {
  328. (void) m_free(m);
  329. error = ENOBUFS; /* ??? */
  330. ipstat.ips_odropped++;
  331. goto sendorfree;
  332. }
  333. m->m_pkthdr.len = mhlen + len;
  334. m->m_pkthdr.rcvif = (struct ifnet *)0;
  335. mhip->ip_off = htons((u_short)mhip->ip_off);
  336. mhip->ip_sum = 0;
  337. mhip->ip_sum = in_cksum(m, mhlen);
  338. *mnext = m;
  339. mnext = &m->m_nextpkt;
  340. ipstat.ips_ofragments++;
  341. }
  342. /*
  343.  * Update first fragment by trimming what's been copied out
  344.  * and updating header, then send each fragment (in order).
  345.  */
  346. m = m0;
  347. m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
  348. m->m_pkthdr.len = hlen + firstlen;
  349. ip->ip_len = htons((u_short)m->m_pkthdr.len);
  350. ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
  351. ip->ip_sum = 0;
  352. ip->ip_sum = in_cksum(m, hlen);
  353. sendorfree:
  354. for (m = m0; m; m = m0) {
  355. m0 = m->m_nextpkt;
  356. m->m_nextpkt = 0;
  357. if (error == 0)
  358. error = (*ifp->if_output)(ifp, m,
  359.     (struct sockaddr *)dst, ro->ro_rt);
  360. else
  361. m_freem(m);
  362. }
  363. if (error == 0)
  364. ipstat.ips_fragmented++;
  365.     }
  366. done:
  367. if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
  368. RTFREE(ro->ro_rt);
  369. return (error);
  370. bad:
  371. m_freem(m0);
  372. goto done;
  373. }
  374. /*
  375.  * Insert IP options into preformed packet.
  376.  * Adjust IP destination as required for IP source routing,
  377.  * as indicated by a non-zero in_addr at the start of the options.
  378.  */
  379. static struct mbuf *
  380. ip_insertoptions(m, opt, phlen)
  381. register struct mbuf *m;
  382. struct mbuf *opt;
  383. int *phlen;
  384. {
  385. register struct ipoption *p = mtod(opt, struct ipoption *);
  386. struct mbuf *n;
  387. register struct ip *ip = mtod(m, struct ip *);
  388. unsigned optlen;
  389. optlen = opt->m_len - sizeof(p->ipopt_dst);
  390. if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
  391. return (m); /* XXX should fail */
  392. if (p->ipopt_dst.s_addr)
  393. ip->ip_dst = p->ipopt_dst;
  394. if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
  395. MGETHDR(n, M_DONTWAIT, MT_HEADER);
  396. if (n == 0)
  397. return (m);
  398. n->m_pkthdr.len = m->m_pkthdr.len + optlen;
  399. m->m_len -= sizeof(struct ip);
  400. m->m_data += sizeof(struct ip);
  401. n->m_next = m;
  402. m = n;
  403. m->m_len = optlen + sizeof(struct ip);
  404. m->m_data += max_linkhdr;
  405. bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
  406. } else {
  407. m->m_data -= optlen;
  408. m->m_len += optlen;
  409. m->m_pkthdr.len += optlen;
  410. ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
  411. }
  412. ip = mtod(m, struct ip *);
  413. bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
  414. *phlen = sizeof(struct ip) + optlen;
  415. ip->ip_len += optlen;
  416. return (m);
  417. }
  418. /*
  419.  * Copy options from ip to jp,
  420.  * omitting those not copied during fragmentation.
  421.  */
  422. int
  423. ip_optcopy(ip, jp)
  424. struct ip *ip, *jp;
  425. {
  426. register u_char *cp, *dp;
  427. int opt, optlen, cnt;
  428. cp = (u_char *)(ip + 1);
  429. dp = (u_char *)(jp + 1);
  430. cnt = (ip->ip_hl << 2) - sizeof (struct ip);
  431. for (; cnt > 0; cnt -= optlen, cp += optlen) {
  432. opt = cp[0];
  433. if (opt == IPOPT_EOL)
  434. break;
  435. if (opt == IPOPT_NOP) {
  436. /* Preserve for IP mcast tunnel's LSRR alignment. */
  437. *dp++ = IPOPT_NOP;
  438. optlen = 1;
  439. continue;
  440. } else
  441. optlen = cp[IPOPT_OLEN];
  442. /* bogus lengths should have been caught by ip_dooptions */
  443. if (optlen > cnt)
  444. optlen = cnt;
  445. if (IPOPT_COPIED(opt)) {
  446. bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
  447. dp += optlen;
  448. }
  449. }
  450. for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
  451. *dp++ = IPOPT_EOL;
  452. return (optlen);
  453. }
  454. /*
  455.  * IP socket option processing.
  456.  */
  457. int
  458. ip_ctloutput(op, so, level, optname, mp)
  459. int op;
  460. struct socket *so;
  461. int level, optname;
  462. struct mbuf **mp;
  463. {
  464. register struct inpcb *inp = sotoinpcb(so);
  465. register struct mbuf *m = *mp;
  466. register int optval;
  467. int error = 0;
  468. if (level != IPPROTO_IP) {
  469. error = EINVAL;
  470. if (op == PRCO_SETOPT && *mp)
  471. (void) m_free(*mp);
  472. } else switch (op) {
  473. case PRCO_SETOPT:
  474. switch (optname) {
  475. case IP_OPTIONS:
  476. #ifdef notyet
  477. case IP_RETOPTS:
  478. return (ip_pcbopts(optname, &inp->inp_options, m));
  479. #else
  480. return (ip_pcbopts(&inp->inp_options, m));
  481. #endif
  482. case IP_TOS:
  483. case IP_TTL:
  484. case IP_RECVOPTS:
  485. case IP_RECVRETOPTS:
  486. case IP_RECVDSTADDR:
  487. if (m->m_len != sizeof(int))
  488. error = EINVAL;
  489. else {
  490. optval = *mtod(m, int *);
  491. switch (optname) {
  492. case IP_TOS:
  493. inp->inp_ip.ip_tos = optval;
  494. break;
  495. case IP_TTL:
  496. inp->inp_ip.ip_ttl = optval;
  497. break;
  498. #define OPTSET(bit) 
  499. if (optval) 
  500. inp->inp_flags |= bit; 
  501. else 
  502. inp->inp_flags &= ~bit;
  503. case IP_RECVOPTS:
  504. OPTSET(INP_RECVOPTS);
  505. break;
  506. case IP_RECVRETOPTS:
  507. OPTSET(INP_RECVRETOPTS);
  508. break;
  509. case IP_RECVDSTADDR:
  510. OPTSET(INP_RECVDSTADDR);
  511. break;
  512. }
  513. }
  514. break;
  515. #undef OPTSET
  516. case IP_MULTICAST_IF:
  517. case IP_MULTICAST_TTL:
  518. case IP_MULTICAST_LOOP:
  519. case IP_ADD_MEMBERSHIP:
  520. case IP_DROP_MEMBERSHIP:
  521. error = ip_setmoptions(optname, &inp->inp_moptions, m);
  522. break;
  523. default:
  524. error = ENOPROTOOPT;
  525. break;
  526. }
  527. if (m)
  528. (void)m_free(m);
  529. break;
  530. case PRCO_GETOPT:
  531. switch (optname) {
  532. case IP_OPTIONS:
  533. case IP_RETOPTS:
  534. *mp = m = m_get(M_WAIT, MT_SOOPTS);
  535. if (inp->inp_options) {
  536. m->m_len = inp->inp_options->m_len;
  537. bcopy(mtod(inp->inp_options, caddr_t),
  538.     mtod(m, caddr_t), (unsigned)m->m_len);
  539. } else
  540. m->m_len = 0;
  541. break;
  542. case IP_TOS:
  543. case IP_TTL:
  544. case IP_RECVOPTS:
  545. case IP_RECVRETOPTS:
  546. case IP_RECVDSTADDR:
  547. *mp = m = m_get(M_WAIT, MT_SOOPTS);
  548. m->m_len = sizeof(int);
  549. switch (optname) {
  550. case IP_TOS:
  551. optval = inp->inp_ip.ip_tos;
  552. break;
  553. case IP_TTL:
  554. optval = inp->inp_ip.ip_ttl;
  555. break;
  556. #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0)
  557. case IP_RECVOPTS:
  558. optval = OPTBIT(INP_RECVOPTS);
  559. break;
  560. case IP_RECVRETOPTS:
  561. optval = OPTBIT(INP_RECVRETOPTS);
  562. break;
  563. case IP_RECVDSTADDR:
  564. optval = OPTBIT(INP_RECVDSTADDR);
  565. break;
  566. }
  567. *mtod(m, int *) = optval;
  568. break;
  569. case IP_MULTICAST_IF:
  570. case IP_MULTICAST_TTL:
  571. case IP_MULTICAST_LOOP:
  572. case IP_ADD_MEMBERSHIP:
  573. case IP_DROP_MEMBERSHIP:
  574. error = ip_getmoptions(optname, inp->inp_moptions, mp);
  575. break;
  576. default:
  577. error = ENOPROTOOPT;
  578. break;
  579. }
  580. break;
  581. }
  582. return (error);
  583. }
  584. /*
  585.  * Set up IP options in pcb for insertion in output packets.
  586.  * Store in mbuf with pointer in pcbopt, adding pseudo-option
  587.  * with destination address if source routed.
  588.  */
  589. int
  590. #ifdef notyet
  591. ip_pcbopts(optname, pcbopt, m)
  592. int optname;
  593. #else
  594. ip_pcbopts(pcbopt, m)
  595. #endif
  596. struct mbuf **pcbopt;
  597. register struct mbuf *m;
  598. {
  599. register cnt, optlen;
  600. register u_char *cp;
  601. u_char opt;
  602. /* turn off any old options */
  603. if (*pcbopt)
  604. (void)m_free(*pcbopt);
  605. *pcbopt = 0;
  606. if (m == (struct mbuf *)0 || m->m_len == 0) {
  607. /*
  608.  * Only turning off any previous options.
  609.  */
  610. if (m)
  611. (void)m_free(m);
  612. return (0);
  613. }
  614. #ifndef vax
  615. if (m->m_len % sizeof(long))
  616. goto bad;
  617. #endif
  618. /*
  619.  * IP first-hop destination address will be stored before
  620.  * actual options; move other options back
  621.  * and clear it when none present.
  622.  */
  623. if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
  624. goto bad;
  625. cnt = m->m_len;
  626. m->m_len += sizeof(struct in_addr);
  627. cp = mtod(m, u_char *) + sizeof(struct in_addr);
  628. ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
  629. bzero(mtod(m, caddr_t), sizeof(struct in_addr));
  630. for (; cnt > 0; cnt -= optlen, cp += optlen) {
  631. opt = cp[IPOPT_OPTVAL];
  632. if (opt == IPOPT_EOL)
  633. break;
  634. if (opt == IPOPT_NOP)
  635. optlen = 1;
  636. else {
  637. optlen = cp[IPOPT_OLEN];
  638. if (optlen <= IPOPT_OLEN || optlen > cnt)
  639. goto bad;
  640. }
  641. switch (opt) {
  642. default:
  643. break;
  644. case IPOPT_LSRR:
  645. case IPOPT_SSRR:
  646. /*
  647.  * user process specifies route as:
  648.  * ->A->B->C->D
  649.  * D must be our final destination (but we can't
  650.  * check that since we may not have connected yet).
  651.  * A is first hop destination, which doesn't appear in
  652.  * actual IP option, but is stored before the options.
  653.  */
  654. if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
  655. goto bad;
  656. m->m_len -= sizeof(struct in_addr);
  657. cnt -= sizeof(struct in_addr);
  658. optlen -= sizeof(struct in_addr);
  659. cp[IPOPT_OLEN] = optlen;
  660. /*
  661.  * Move first hop before start of options.
  662.  */
  663. bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
  664.     sizeof(struct in_addr));
  665. /*
  666.  * Then copy rest of options back
  667.  * to close up the deleted entry.
  668.  */
  669. ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
  670.     sizeof(struct in_addr)),
  671.     (caddr_t)&cp[IPOPT_OFFSET+1],
  672.     (unsigned)cnt + sizeof(struct in_addr));
  673. break;
  674. }
  675. }
  676. if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
  677. goto bad;
  678. *pcbopt = m;
  679. return (0);
  680. bad:
  681. (void)m_free(m);
  682. return (EINVAL);
  683. }
  684. /*
  685.  * Set the IP multicast options in response to user setsockopt().
  686.  */
  687. int
  688. ip_setmoptions(optname, imop, m)
  689. int optname;
  690. struct ip_moptions **imop;
  691. struct mbuf *m;
  692. {
  693. register int error = 0;
  694. u_char loop;
  695. register int i;
  696. struct in_addr addr;
  697. register struct ip_mreq *mreq;
  698. register struct ifnet *ifp;
  699. register struct ip_moptions *imo = *imop;
  700. struct route ro;
  701. register struct sockaddr_in *dst;
  702. if (imo == NULL) {
  703. /*
  704.  * No multicast option buffer attached to the pcb;
  705.  * allocate one and initialize to default values.
  706.  */
  707. imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,
  708.     M_WAITOK);
  709. if (imo == NULL)
  710. return (ENOBUFS);
  711. *imop = imo;
  712. imo->imo_multicast_ifp = NULL;
  713. imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
  714. imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
  715. imo->imo_num_memberships = 0;
  716. }
  717. switch (optname) {
  718. case IP_MULTICAST_IF:
  719. /*
  720.  * Select the interface for outgoing multicast packets.
  721.  */
  722. if (m == NULL || m->m_len != sizeof(struct in_addr)) {
  723. error = EINVAL;
  724. break;
  725. }
  726. addr = *(mtod(m, struct in_addr *));
  727. /*
  728.  * INADDR_ANY is used to remove a previous selection.
  729.  * When no interface is selected, a default one is
  730.  * chosen every time a multicast packet is sent.
  731.  */
  732. if (addr.s_addr == INADDR_ANY) {
  733. imo->imo_multicast_ifp = NULL;
  734. break;
  735. }
  736. /*
  737.  * The selected interface is identified by its local
  738.  * IP address.  Find the interface and confirm that
  739.  * it supports multicasting.
  740.  */
  741. INADDR_TO_IFP(addr, ifp);
  742. if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
  743. error = EADDRNOTAVAIL;
  744. break;
  745. }
  746. imo->imo_multicast_ifp = ifp;
  747. break;
  748. case IP_MULTICAST_TTL:
  749. /*
  750.  * Set the IP time-to-live for outgoing multicast packets.
  751.  */
  752. if (m == NULL || m->m_len != 1) {
  753. error = EINVAL;
  754. break;
  755. }
  756. imo->imo_multicast_ttl = *(mtod(m, u_char *));
  757. break;
  758. case IP_MULTICAST_LOOP:
  759. /*
  760.  * Set the loopback flag for outgoing multicast packets.
  761.  * Must be zero or one.
  762.  */
  763. if (m == NULL || m->m_len != 1 ||
  764.    (loop = *(mtod(m, u_char *))) > 1) {
  765. error = EINVAL;
  766. break;
  767. }
  768. imo->imo_multicast_loop = loop;
  769. break;
  770. case IP_ADD_MEMBERSHIP:
  771. /*
  772.  * Add a multicast group membership.
  773.  * Group must be a valid IP multicast address.
  774.  */
  775. if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
  776. error = EINVAL;
  777. break;
  778. }
  779. mreq = mtod(m, struct ip_mreq *);
  780. if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
  781. error = EINVAL;
  782. break;
  783. }
  784. /*
  785.  * If no interface address was provided, use the interface of
  786.  * the route to the given multicast address.
  787.  */
  788. if (mreq->imr_interface.s_addr == INADDR_ANY) {
  789. ro.ro_rt = NULL;
  790. dst = (struct sockaddr_in *)&ro.ro_dst;
  791. dst->sin_len = sizeof(*dst);
  792. dst->sin_family = AF_INET;
  793. dst->sin_addr = mreq->imr_multiaddr;
  794. rtalloc(&ro);
  795. if (ro.ro_rt == NULL) {
  796. error = EADDRNOTAVAIL;
  797. break;
  798. }
  799. ifp = ro.ro_rt->rt_ifp;
  800. rtfree(ro.ro_rt);
  801. }
  802. else {
  803. INADDR_TO_IFP(mreq->imr_interface, ifp);
  804. }
  805. /*
  806.  * See if we found an interface, and confirm that it
  807.  * supports multicast.
  808.  */
  809. if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
  810. error = EADDRNOTAVAIL;
  811. break;
  812. }
  813. /*
  814.  * See if the membership already exists or if all the
  815.  * membership slots are full.
  816.  */
  817. for (i = 0; i < imo->imo_num_memberships; ++i) {
  818. if (imo->imo_membership[i]->inm_ifp == ifp &&
  819.     imo->imo_membership[i]->inm_addr.s_addr
  820. == mreq->imr_multiaddr.s_addr)
  821. break;
  822. }
  823. if (i < imo->imo_num_memberships) {
  824. error = EADDRINUSE;
  825. break;
  826. }
  827. if (i == IP_MAX_MEMBERSHIPS) {
  828. error = ETOOMANYREFS;
  829. break;
  830. }
  831. /*
  832.  * Everything looks good; add a new record to the multicast
  833.  * address list for the given interface.
  834.  */
  835. if ((imo->imo_membership[i] =
  836.     in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
  837. error = ENOBUFS;
  838. break;
  839. }
  840. ++imo->imo_num_memberships;
  841. break;
  842. case IP_DROP_MEMBERSHIP:
  843. /*
  844.  * Drop a multicast group membership.
  845.  * Group must be a valid IP multicast address.
  846.  */
  847. if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
  848. error = EINVAL;
  849. break;
  850. }
  851. mreq = mtod(m, struct ip_mreq *);
  852. if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
  853. error = EINVAL;
  854. break;
  855. }
  856. /*
  857.  * If an interface address was specified, get a pointer
  858.  * to its ifnet structure.
  859.  */
  860. if (mreq->imr_interface.s_addr == INADDR_ANY)
  861. ifp = NULL;
  862. else {
  863. INADDR_TO_IFP(mreq->imr_interface, ifp);
  864. if (ifp == NULL) {
  865. error = EADDRNOTAVAIL;
  866. break;
  867. }
  868. }
  869. /*
  870.  * Find the membership in the membership array.
  871.  */
  872. for (i = 0; i < imo->imo_num_memberships; ++i) {
  873. if ((ifp == NULL ||
  874.      imo->imo_membership[i]->inm_ifp == ifp) &&
  875.      imo->imo_membership[i]->inm_addr.s_addr ==
  876.      mreq->imr_multiaddr.s_addr)
  877. break;
  878. }
  879. if (i == imo->imo_num_memberships) {
  880. error = EADDRNOTAVAIL;
  881. break;
  882. }
  883. /*
  884.  * Give up the multicast address record to which the
  885.  * membership points.
  886.  */
  887. in_delmulti(imo->imo_membership[i]);
  888. /*
  889.  * Remove the gap in the membership array.
  890.  */
  891. for (++i; i < imo->imo_num_memberships; ++i)
  892. imo->imo_membership[i-1] = imo->imo_membership[i];
  893. --imo->imo_num_memberships;
  894. break;
  895. default:
  896. error = EOPNOTSUPP;
  897. break;
  898. }
  899. /*
  900.  * If all options have default values, no need to keep the mbuf.
  901.  */
  902. if (imo->imo_multicast_ifp == NULL &&
  903.     imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
  904.     imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
  905.     imo->imo_num_memberships == 0) {
  906. free(*imop, M_IPMOPTS);
  907. *imop = NULL;
  908. }
  909. return (error);
  910. }
  911. /*
  912.  * Return the IP multicast options in response to user getsockopt().
  913.  */
  914. int
  915. ip_getmoptions(optname, imo, mp)
  916. int optname;
  917. register struct ip_moptions *imo;
  918. register struct mbuf **mp;
  919. {
  920. u_char *ttl;
  921. u_char *loop;
  922. struct in_addr *addr;
  923. struct in_ifaddr *ia;
  924. *mp = m_get(M_WAIT, MT_SOOPTS);
  925. switch (optname) {
  926. case IP_MULTICAST_IF:
  927. addr = mtod(*mp, struct in_addr *);
  928. (*mp)->m_len = sizeof(struct in_addr);
  929. if (imo == NULL || imo->imo_multicast_ifp == NULL)
  930. addr->s_addr = INADDR_ANY;
  931. else {
  932. IFP_TO_IA(imo->imo_multicast_ifp, ia);
  933. addr->s_addr = (ia == NULL) ? INADDR_ANY
  934. : IA_SIN(ia)->sin_addr.s_addr;
  935. }
  936. return (0);
  937. case IP_MULTICAST_TTL:
  938. ttl = mtod(*mp, u_char *);
  939. (*mp)->m_len = 1;
  940. *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
  941.      : imo->imo_multicast_ttl;
  942. return (0);
  943. case IP_MULTICAST_LOOP:
  944. loop = mtod(*mp, u_char *);
  945. (*mp)->m_len = 1;
  946. *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
  947.       : imo->imo_multicast_loop;
  948. return (0);
  949. default:
  950. return (EOPNOTSUPP);
  951. }
  952. }
  953. /*
  954.  * Discard the IP multicast options.
  955.  */
  956. void
  957. ip_freemoptions(imo)
  958. register struct ip_moptions *imo;
  959. {
  960. register int i;
  961. if (imo != NULL) {
  962. for (i = 0; i < imo->imo_num_memberships; ++i)
  963. in_delmulti(imo->imo_membership[i]);
  964. free(imo, M_IPMOPTS);
  965. }
  966. }
  967. /*
  968.  * Routine called from ip_output() to loop back a copy of an IP multicast
  969.  * packet to the input queue of a specified interface.  Note that this
  970.  * calls the output routine of the loopback "driver", but with an interface
  971.  * pointer that might NOT be &loif -- easier than replicating that code here.
  972.  */
  973. static void
  974. ip_mloopback(ifp, m, dst)
  975. struct ifnet *ifp;
  976. register struct mbuf *m;
  977. register struct sockaddr_in *dst;
  978. {
  979. register struct ip *ip;
  980. struct mbuf *copym;
  981. copym = m_copy(m, 0, M_COPYALL);
  982. if (copym != NULL) {
  983. /*
  984.  * We don't bother to fragment if the IP length is greater
  985.  * than the interface's MTU.  Can this possibly matter?
  986.  */
  987. ip = mtod(copym, struct ip *);
  988. ip->ip_len = htons((u_short)ip->ip_len);
  989. ip->ip_off = htons((u_short)ip->ip_off);
  990. ip->ip_sum = 0;
  991. ip->ip_sum = in_cksum(copym, ip->ip_hl << 2);
  992. (void) looutput(ifp, copym, (struct sockaddr *)dst, NULL);
  993. }
  994. }