udp_usrreq.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:33k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* udp_usrreq.c - UDP protocol routines */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  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. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 03g,12oct01,rae  merge from truestack ver 03k, base 03f (SPR #65887 etc.)
  42. 03f,31aug98,n_s  added udp_hlen validty check to udp_input (). spr #6263.
  43. 03e,05oct97,vin  added fast multicasting.
  44. 03d,31mar97,vin  modified for hash look ups for pcbs(FREEBSD 2.2.1).
  45. 03c,20jan97,vin  replace icmp_error with _icmpErrorHook for scalability, 
  46.  added new udpDoCkSumRcv variable, fixed bugs mentioned
  47.  in Stevens VOLII chapter 23, pg772 & pg774.
  48. 03b,22nov96,vin  added cluster support replaced m_get(..) with mBufClGet(..).
  49. 03a,03mar96,vin  created from BSD4.4 stuff,integrated with 02r of udp_usrreq.c.
  50. */
  51. /*
  52. DESCRIPTION
  53. */
  54. #include "vxWorks.h"
  55. #include "net/mbuf.h"
  56. #include "net/protosw.h"
  57. #include "sys/socket.h"
  58. #include "net/socketvar.h"
  59. #include "errno.h"
  60. #include "net/if.h"
  61. #include "net/route.h"
  62. #include "netinet/in.h"
  63. #include "netinet/in_pcb.h"
  64. #include "netinet/in_systm.h"
  65. #include "netinet/ip.h"
  66. #include "netinet/ip_var.h"
  67. #include "netinet/in_var.h"
  68. #include "netinet/ip_icmp.h"
  69. #include "netinet/udp.h"
  70. #include "netinet/udp_var.h"
  71. #include "net/systm.h"
  72. #include "stdio.h"
  73. #ifdef WV_INSTRUMENTATION
  74. #ifdef INCLUDE_WVNET
  75. #include "wvNetLib.h"
  76. #endif
  77. #endif
  78. #ifdef VIRTUAL_STACK
  79. #include "netinet/vsLib.h"
  80. #endif
  81. /*
  82.  * UDP protocol implementation.
  83.  * Per RFC 768, August, 1980.
  84.  */
  85. #ifndef UDBHASHSIZE
  86. #define UDBHASHSIZE 64
  87. #endif
  88. #ifndef VIRTUAL_STACK
  89. #ifndef COMPAT_42
  90. int udpcksum  = 1; /* turn on send checksum by default */
  91. int udpDoCkSumRcv = 1; /* turn on recv checksum by default */
  92. #else
  93. int udpcksum  = 0; /* XXX */
  94. int udpDoCkSumRcv = 0;
  95. #endif
  96. /* externs */
  97. extern VOIDFUNCPTR _icmpErrorHook;
  98. /* globals */
  99. struct  inpcbhead udb;          /* from udp_var.h */
  100. struct  inpcbinfo udbinfo;
  101. struct  udpstat udpstat; /* global udp statistics structure */
  102. struct  sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
  103. struct inpcb * udp_last_inpcb = NULL; /* last PCB cache for fast look up */
  104. int udp_ttl = UDP_TTL;
  105. u_long udp_sendspace = 9216; /* really max datagram size */
  106. u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
  107. /* 40 1K datagrams */
  108. u_short udp_pcbhashsize = UDBHASHSIZE;  /* size of hash table */
  109. #endif    /* VIRTUAL_STACK */
  110. /* locals */
  111. #ifdef WV_INSTRUMENTATION
  112. #ifdef INCLUDE_WVNET
  113.     /* Set common fields of event identifiers for this module. */
  114. LOCAL UCHAR wvNetModuleId = WV_NET_UDPREQ_MODULE; /* Value for udp_usrreq.c */
  115. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  116. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  117. #endif    /* INCLUDE_WVNET */
  118. #endif
  119. /* forward declarations */
  120. static void udp_detach (struct inpcb *);
  121. static void udp_notify (struct inpcb *, int);
  122. static struct mbuf *udp_saveopt (caddr_t, int, int);
  123. void
  124. udp_init()
  125. {
  126. #ifdef WV_INSTRUMENTATION
  127. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  128.     WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 43, 16,
  129.                      WV_NETEVENT_UDPINIT_START)
  130. #endif  /* INCLUDE_WVNET */
  131. #endif
  132. LIST_INIT(&udb);
  133. udbinfo.listhead = &udb;
  134. #ifdef VIRTUAL_STACK
  135.         udp_in.sin_len     = sizeof(udp_in);
  136.         udp_in.sin_family  = AF_INET;
  137.         udp_last_inpcb     = NULL;
  138.         udp_ttl            = UDP_TTL;
  139.         udp_sendspace      = 9216;
  140.         udp_recvspace      = 40 * (1024 + sizeof (struct sockaddr_in));
  141.         udp_pcbhashsize    = UDBHASHSIZE;
  142. #ifndef COMPAT_42
  143.         udpcksum     = 1; /* turn on send checksum by default */
  144.         udpDoCkSumRcv    = 1; /* turn on recv checksum by default */
  145. #else
  146.         udpcksum     = 0; /* XXX */
  147.         udpDoCkSumRcv    = 0;
  148. #endif    /* COMPAT_42 */
  149. #endif    /* VIRTUAL_STACK */
  150. udbinfo.hashbase = hashinit(udp_pcbhashsize, MT_PCB, &udbinfo.hashmask);
  151. }
  152. void
  153. udp_input(m, iphlen)
  154. register struct mbuf *m;
  155. int iphlen;
  156. {
  157. register struct ip *ip;
  158. register struct udphdr *uh;
  159. register struct inpcb *inp;
  160. struct mbuf *opts = 0;
  161. int len;
  162. struct ip save_ip;
  163. #ifdef WV_INSTRUMENTATION
  164. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  165.     WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_NOTICE, 21, 10,
  166.                     WV_NETEVENT_UDPIN_START, WV_NET_RECV)
  167. #endif  /* INCLUDE_WVNET */
  168. #endif
  169. udpstat.udps_ipackets++;
  170. /*
  171.  * Strip IP options, if any; should skip this,
  172.  * make available to user, and use on returned packets,
  173.  * but we don't yet have a way to check the checksum
  174.  * with options still present.
  175.  */
  176. if (iphlen > sizeof (struct ip)) {
  177. ip_stripoptions(m, (struct mbuf *)0);
  178. iphlen = sizeof(struct ip);
  179. }
  180. /*
  181.  * Get IP and UDP header together in first mbuf.
  182.  */
  183. ip = mtod(m, struct ip *);
  184. if (m->m_len < iphlen + sizeof(struct udphdr)) {
  185. if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
  186. udpstat.udps_hdrops++;
  187. #ifdef WV_INSTRUMENTATION
  188. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  189.             WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_WARNING, 14, 4,
  190.                             WV_NETEVENT_UDPIN_SHORTPKTHDR, WV_NET_RECV)
  191. #endif  /* INCLUDE_WVNET */
  192. #endif
  193. return;
  194. }
  195. ip = mtod(m, struct ip *);
  196. }
  197. uh = (struct udphdr *)((caddr_t)ip + iphlen);
  198. /*
  199.  * Make mbuf data length reflect UDP length.
  200.  * If not enough data to reflect UDP length, drop.
  201.  */
  202. len = ntohs((u_short)uh->uh_ulen);
  203. if (len < sizeof (struct udphdr))
  204.     {
  205.     udpstat.udps_badlen++;
  206.     goto bad;
  207.     }
  208. if (ip->ip_len != len) {
  209. if (len > ip->ip_len) {
  210. #ifdef WV_INSTRUMENTATION
  211. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  212.             WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_WARNING, 15, 5,
  213.                             WV_NETEVENT_UDPIN_BADLEN, WV_NET_RECV)
  214. #endif  /* INCLUDE_WVNET */
  215. #endif
  216. udpstat.udps_badlen++;
  217. goto bad;
  218. }
  219. m_adj(m, len - ip->ip_len);
  220. /* ip->ip_len = len; */
  221. }
  222. /*
  223.  * Save a copy of the IP header in case we want restore it
  224.  * for sending an ICMP error message in response.
  225.  */
  226. save_ip = *ip;
  227. /*
  228.  * Checksum extended UDP header and data.
  229.  */
  230. if (udpDoCkSumRcv && uh->uh_sum) {
  231. ((struct ipovly *)ip)->ih_next = 0;
  232. ((struct ipovly *)ip)->ih_prev = 0;
  233. ((struct ipovly *)ip)->ih_x1 = 0;
  234. ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
  235. if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip)))) {
  236. #ifdef WV_INSTRUMENTATION
  237. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  238.             WV_NET_EVENT_0 (NET_CORE_EVENT, WV_NET_WARNING, 16, 6,
  239.                             WV_NETEVENT_UDPIN_BADSUM, WV_NET_RECV)
  240. #endif  /* INCLUDE_WVNET */
  241. #endif
  242. udpstat.udps_badsum++;
  243. m_freem(m);
  244. return;
  245. }
  246. }
  247.         if(IN_MULTICAST(ntohl(ip->ip_dst.s_addr)))
  248.             {
  249.             IN_MULTI *  pInMulti;
  250.             M_BLK_ID pInPcbMblk;
  251.             IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, pInMulti);
  252.             /* give the packet to all pcbs registered */
  253.             if (pInMulti != NULL)
  254.                 {
  255. struct socket *last;
  256. /*
  257.  * Construct sockaddr format source address.
  258.  */
  259. udp_in.sin_port = uh->uh_sport;
  260. udp_in.sin_addr = ip->ip_src;
  261. m->m_len -= sizeof (struct udpiphdr);
  262. m->m_data += sizeof (struct udpiphdr);
  263. /*
  264.  * give the datagrams to all the pcbs 
  265.  * 
  266.  */
  267. last = NULL;
  268. for (pInPcbMblk = pInMulti->pInPcbMblk; pInPcbMblk != NULL;
  269.                      pInPcbMblk = pInPcbMblk->mBlkHdr.mNext)
  270.                     {
  271.                     inp = mtod (pInPcbMblk, struct inpcb *);
  272.                     if (inp->inp_lport != uh->uh_dport)
  273.                         continue;
  274.                     if (inp->inp_laddr.s_addr != INADDR_ANY)
  275.                         if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
  276.                             continue;
  277.                     if (inp->inp_faddr.s_addr != INADDR_ANY)
  278.                         if (inp->inp_faddr.s_addr != ip->ip_src.s_addr ||
  279.                             inp->inp_fport != uh->uh_sport)
  280.                             continue;
  281.                     if (last != NULL)
  282.                         {
  283.                         struct mbuf *n;
  284.                         if ((n = m_copy(m, 0, M_COPYALL)) != NULL)
  285.                             {
  286. #ifdef WV_INSTRUMENTATION
  287. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  288.                 WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18,
  289.                                        uh->uh_sport, uh->uh_dport,
  290.                                        WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV,
  291.                                        ip->ip_src.s_addr, uh->uh_sport,
  292.                                        last->so_fd, uh->uh_dport)
  293. #endif  /* INCLUDE_WVNET */
  294. #endif
  295.                             if (sbappendaddr(&last->so_rcv,
  296.                                              (struct sockaddr *)&udp_in,
  297.                                              n, (struct mbuf *)0) == 0)
  298.                                 {
  299. #ifdef WV_INSTRUMENTATION
  300. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  301.                 WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7,
  302.                                        uh->uh_sport, uh->uh_dport,
  303.                                        WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV,
  304.                                        last->so_fd)
  305. #endif  /* INCLUDE_WVNET */
  306. #endif
  307.                                 m_freem(n);
  308.                                 udpstat.udps_fullsock++;
  309.                                 }
  310.                             else
  311.                                 sorwakeup(last);
  312.                             }
  313.                         }
  314.                     last = inp->inp_socket;
  315.                     /*
  316.                      * Don't look for additional matches if this one does
  317.                      * not have either the SO_REUSEPORT or SO_REUSEADDR
  318.                      * socket options set.  This heuristic avoids searching
  319.                      * through all pcbs in the common case of a non-shared
  320.                      * port.  It assumes that an application will never
  321.                      * clear these options after setting them.
  322.                      */
  323.                     if ((last->so_options & (SO_REUSEPORT|SO_REUSEADDR)) == 0)
  324.                         break;
  325.                     }
  326. if (last == NULL)
  327.                     {
  328.                     /*
  329.                      * No matching pcb found; discard datagram.
  330.                      * (No need to send an ICMP Port Unreachable
  331.                      * for a broadcast or multicast datgram.)
  332.                      */
  333. #ifdef WV_INSTRUMENTATION
  334. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  335.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8,
  336.                                    uh->uh_sport, uh->uh_dport,
  337.                                    WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV,
  338.                                    ip->ip_src.s_addr, uh->uh_sport,
  339.                                    ip->ip_dst.s_addr, uh->uh_dport)
  340. #endif  /* INCLUDE_WVNET */
  341. #endif
  342.                     udpstat.udps_noportbcast++;
  343.                     goto bad;
  344.                     }
  345. #ifdef WV_INSTRUMENTATION
  346. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  347.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18,
  348.                                    uh->uh_sport, uh->uh_dport,
  349.                                    WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV,
  350.                                    ip->ip_src.s_addr, uh->uh_sport,
  351.                                    last->so_fd, uh->uh_dport)
  352. #endif  /* INCLUDE_WVNET */
  353. #endif
  354. if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in,
  355.                                  m, (struct mbuf *)0) == 0)
  356.                     {
  357. #ifdef WV_INSTRUMENTATION
  358. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  359.             WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7,
  360.                                    uh->uh_sport, uh->uh_dport,
  361.                                    WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV,
  362.                                    last->so_fd)
  363. #endif  /* INCLUDE_WVNET */
  364. #endif
  365.                     udpstat.udps_fullsock++;
  366.                     goto bad;
  367.                     }
  368. sorwakeup(last);
  369. return;
  370.                 }
  371.             }
  372.         
  373. if (in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
  374. struct socket *last;
  375. /*
  376.  * Deliver a multicast or broadcast datagram to *all* sockets
  377.  * for which the local and remote addresses and ports match
  378.  * those of the incoming datagram.  This allows more than
  379.  * one process to receive multi/broadcasts on the same port.
  380.  * (This really ought to be done for unicast datagrams as
  381.  * well, but that would cause problems with existing
  382.  * applications that open both address-specific sockets and
  383.  * a wildcard socket listening to the same port -- they would
  384.  * end up receiving duplicates of every unicast datagram.
  385.  * Those applications open the multiple sockets to overcome an
  386.  * inadequacy of the UDP socket interface, but for backwards
  387.  * compatibility we avoid the problem here rather than
  388.  * fixing the interface.  Maybe 4.5BSD will remedy this?)
  389.  */
  390. /*
  391.  * Construct sockaddr format source address.
  392.  */
  393. udp_in.sin_port = uh->uh_sport;
  394. udp_in.sin_addr = ip->ip_src;
  395. m->m_len -= sizeof (struct udpiphdr);
  396. m->m_data += sizeof (struct udpiphdr);
  397. /*
  398.  * Locate pcb(s) for datagram.
  399.  * (Algorithm copied from raw_intr().)
  400.  */
  401. last = NULL;
  402. for (inp = udb.lh_first; inp != NULL;
  403.                      inp = inp->inp_list.le_next) {
  404. if (inp->inp_lport != uh->uh_dport)
  405. continue;
  406. if (inp->inp_laddr.s_addr != INADDR_ANY) {
  407. if (inp->inp_laddr.s_addr !=
  408.     ip->ip_dst.s_addr)
  409. continue;
  410. }
  411. if (inp->inp_faddr.s_addr != INADDR_ANY) {
  412. if (inp->inp_faddr.s_addr !=
  413.     ip->ip_src.s_addr ||
  414.     inp->inp_fport != uh->uh_sport)
  415. continue;
  416. }
  417. if (last != NULL) {
  418. struct mbuf *n;
  419. if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
  420. #ifdef WV_INSTRUMENTATION
  421. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  422.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18,
  423.                                    uh->uh_sport, uh->uh_dport,
  424.                                    WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV,
  425.                                    ip->ip_src.s_addr, uh->uh_sport,
  426.                                    last->so_fd, uh->uh_dport)
  427. #endif  /* INCLUDE_WVNET */
  428. #endif
  429. if (sbappendaddr(&last->so_rcv,
  430. (struct sockaddr *)&udp_in,
  431. n, (struct mbuf *)0) == 0) {
  432. m_freem(n);
  433. #ifdef WV_INSTRUMENTATION
  434. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  435.             WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7,
  436.                                    uh->uh_sport, uh->uh_dport,
  437.                                    WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV,
  438.                                    last->so_fd)
  439. #endif  /* INCLUDE_WVNET */
  440. #endif
  441. udpstat.udps_fullsock++;
  442. } else
  443. sorwakeup(last);
  444. }
  445. }
  446. last = inp->inp_socket;
  447. /*
  448.  * Don't look for additional matches if this one does
  449.  * not have either the SO_REUSEPORT or SO_REUSEADDR
  450.  * socket options set.  This heuristic avoids searching
  451.  * through all pcbs in the common case of a non-shared
  452.  * port.  It * assumes that an application will never
  453.  * clear these options after setting them.
  454.  */
  455. if ((last->so_options & (SO_REUSEPORT|SO_REUSEADDR))
  456.                             == 0)
  457. break;
  458. }
  459. if (last == NULL) {
  460. /*
  461.  * No matching pcb found; discard datagram.
  462.  * (No need to send an ICMP Port Unreachable
  463.  * for a broadcast or multicast datgram.)
  464.  */
  465. #ifdef WV_INSTRUMENTATION
  466. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  467.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8,
  468.                                    uh->uh_sport, uh->uh_dport,
  469.                                    WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV,
  470.                                    ip->ip_src.s_addr, uh->uh_sport,
  471.                                    ip->ip_dst.s_addr, uh->uh_dport)
  472. #endif  /* INCLUDE_WVNET */
  473. #endif
  474. udpstat.udps_noportbcast++;
  475. goto bad;
  476. }
  477. #ifdef WV_INSTRUMENTATION
  478. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  479.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18,
  480.                                    uh->uh_sport, uh->uh_dport,
  481.                                    WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV,
  482.                                    ip->ip_src.s_addr, uh->uh_sport,
  483.                                    last->so_fd, uh->uh_dport)
  484. #endif  /* INCLUDE_WVNET */
  485. #endif
  486. if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in,
  487.      m, (struct mbuf *)0) == 0) {
  488. #ifdef WV_INSTRUMENTATION
  489. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  490.             WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7,
  491.                                    uh->uh_sport, uh->uh_dport,
  492.                                    WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV,
  493.                                    last->so_fd)
  494. #endif  /* INCLUDE_WVNET */
  495. #endif
  496. udpstat.udps_fullsock++;
  497. goto bad;
  498. }
  499. sorwakeup(last);
  500. return;
  501. }
  502. /*
  503.  * Locate pcb for datagram. use the cached pcb if it matches.
  504.  */
  505. inp = udp_last_inpcb;
  506.         if ((inp != NULL) &&
  507.             (inp->inp_lport == uh->uh_dport) &&
  508.     (inp->inp_fport == uh->uh_sport) &&
  509.     (inp->inp_faddr.s_addr == ip->ip_src.s_addr) &&
  510.             (inp->inp_laddr.s_addr == ip->ip_dst.s_addr))
  511.             {
  512.             goto pcbMatchFound;
  513.             }
  514.         else
  515.             {
  516. #ifdef WV_INSTRUMENTATION
  517. #ifdef INCLUDE_WVNET    /* WV_NET_VERBOSE event */
  518.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_VERBOSE, 44, 17,
  519.                                    uh->uh_sport, uh->uh_dport,
  520.                                    WV_NETEVENT_UDPIN_CACHEMISS, WV_NET_RECV,
  521.                                    ip->ip_src.s_addr, uh->uh_sport,
  522.                                    ip->ip_dst.s_addr, uh->uh_dport)
  523. #endif  /* INCLUDE_WVNET */
  524. #endif
  525.             udpstat.udpps_pcbcachemiss++;
  526.             /*
  527.              * Locate pcb for datagram.
  528.              */
  529.             inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport,
  530.                                        ip->ip_dst, uh->uh_dport, 1);
  531.             if (inp == NULL)
  532.                 { /* look up for the wildcard match, hash look up failed */
  533.                 udpstat.udpps_pcbhashmiss++;
  534.                 udpstat.udps_noport++;
  535. #ifdef WV_INSTRUMENTATION
  536. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  537.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8,
  538.                                    uh->uh_sport, uh->uh_dport,
  539.                                    WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV,
  540.                                    ip->ip_src.s_addr, uh->uh_sport,
  541.                                    ip->ip_dst.s_addr, uh->uh_dport)
  542. #endif  /* INCLUDE_WVNET */
  543. #endif
  544.                 if (m->m_flags & (M_BCAST | M_MCAST))
  545.                     {
  546.                     udpstat.udps_noportbcast++;
  547.                     goto bad;
  548.                     }
  549. #ifdef WV_INSTRUMENTATION
  550. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  551.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 19, 9,
  552.                                    uh->uh_sport, uh->uh_dport,
  553.                                    WV_NETEVENT_UDPIN_NOPORT, WV_NET_RECV,
  554.                                    ip->ip_src.s_addr, uh->uh_sport,
  555.                                    ip->ip_dst.s_addr, uh->uh_dport)
  556. #endif  /* INCLUDE_WVNET */
  557. #endif
  558.                 *ip = save_ip;
  559.                 /* bug fix mentioned in Stevens VolII page774,(vinai) */
  560.                 /* ip->ip_len += iphlen; */
  561.                 if (_icmpErrorHook != NULL)
  562.                     (*_icmpErrorHook) (m, ICMP_UNREACH, ICMP_UNREACH_PORT, 
  563.                                        0, 0);
  564.                 return;
  565.                 }
  566.             }
  567.         udp_last_inpcb = inp;
  568.         
  569. pcbMatchFound:
  570. #ifdef WV_INSTRUMENTATION
  571. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  572.             WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18,
  573.                                    uh->uh_sport, uh->uh_dport,
  574.                                    WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV,
  575.                                    ip->ip_src.s_addr, uh->uh_sport,
  576.                                    inp->inp_socket->so_fd, uh->uh_dport)
  577. #endif  /* INCLUDE_WVNET */
  578. #endif
  579. /*
  580.  * Construct sockaddr format source address.
  581.  * Stuff source address and datagram in user buffer.
  582.  */
  583. udp_in.sin_port = uh->uh_sport;
  584. udp_in.sin_addr = ip->ip_src;
  585. if (inp->inp_flags & INP_CONTROLOPTS) {
  586. struct mbuf **mp = &opts;
  587. if (inp->inp_flags & INP_RECVDSTADDR) {
  588. *mp = udp_saveopt((caddr_t) &ip->ip_dst,
  589.     sizeof(struct in_addr), IP_RECVDSTADDR);
  590. if (*mp)
  591. mp = &(*mp)->m_next;
  592. }
  593. #ifdef notyet
  594. /* options were tossed above */
  595. if (inp->inp_flags & INP_RECVOPTS) {
  596. *mp = udp_saveopt((caddr_t) opts_deleted_above,
  597.     sizeof(struct in_addr), IP_RECVOPTS);
  598. if (*mp)
  599. mp = &(*mp)->m_next;
  600. }
  601. /* ip_srcroute doesn't do what we want here, need to fix */
  602. if (inp->inp_flags & INP_RECVRETOPTS) {
  603. *mp = udp_saveopt((caddr_t) ip_srcroute(),
  604.     sizeof(struct in_addr), IP_RECVRETOPTS);
  605. if (*mp)
  606. mp = &(*mp)->m_next;
  607. }
  608. #endif
  609. }
  610. iphlen += sizeof(struct udphdr);
  611. m->m_len -= iphlen;
  612. m->m_pkthdr.len -= iphlen;
  613. m->m_data += iphlen;
  614. if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
  615.     m, opts) == 0) {
  616. #ifdef WV_INSTRUMENTATION
  617. #ifdef INCLUDE_WVNET    /* WV_NET_WARNING event */
  618.             WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7,
  619.                                    uh->uh_sport, uh->uh_dport,
  620.                                    WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV,
  621.                                    inp->inp_socket->so_fd)
  622. #endif  /* INCLUDE_WVNET */
  623. #endif
  624. udpstat.udps_fullsock++;
  625. goto bad;
  626. }
  627. sorwakeup(inp->inp_socket);
  628. return;
  629. bad:
  630. m_freem(m);
  631. if (opts)
  632. m_freem(opts);
  633. }
  634. /*
  635.  * Create a "control" mbuf containing the specified data
  636.  * with the specified type for presentation with a datagram.
  637.  */
  638. struct mbuf *
  639. udp_saveopt(p, size, type)
  640. caddr_t p;
  641. register int size;
  642. int type;
  643. {
  644. register struct cmsghdr *cp;
  645. struct mbuf *m;
  646. if ((m = mBufClGet(M_DONTWAIT, MT_CONTROL, CL_SIZE_128, TRUE)) == NULL)
  647. return ((struct mbuf *) NULL);
  648. cp = (struct cmsghdr *) mtod(m, struct cmsghdr *);
  649. bcopy(p, CMSG_DATA(cp), size);
  650. size += sizeof(*cp);
  651. m->m_len = size;
  652. cp->cmsg_len = size;
  653. cp->cmsg_level = IPPROTO_IP;
  654. cp->cmsg_type = type;
  655. return (m);
  656. }
  657. /*
  658.  * Notify a udp user of an asynchronous error;
  659.  * just wake up so that he can collect error status.
  660.  */
  661. static void
  662. udp_notify(inp, error)
  663. register struct inpcb *inp;
  664. int error;
  665. {
  666. #ifdef WV_INSTRUMENTATION
  667. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  668.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 48, 12,
  669.                      WV_NETEVENT_UDPNOTIFY_START,
  670.                      inp->inp_socket->so_fd, error)
  671. #endif  /* INCLUDE_WVNET */
  672. #endif
  673. inp->inp_socket->so_error = error;
  674. sorwakeup(inp->inp_socket);
  675. sowwakeup(inp->inp_socket);
  676. }
  677. void
  678. udp_ctlinput(cmd, sa, ip)
  679. int cmd;
  680. struct sockaddr *sa;
  681. register struct ip *ip;
  682. {
  683. register struct udphdr *uh;
  684. extern struct in_addr zeroin_addr;
  685. extern u_char inetctlerrmap[];
  686. #ifdef WV_INSTRUMENTATION
  687. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  688.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 49, 13,
  689.                      WV_NETEVENT_UDPCTLIN_START, cmd)
  690. #endif  /* INCLUDE_WVNET */
  691. #endif
  692. if (!PRC_IS_REDIRECT(cmd) &&
  693.     ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0))
  694. return;
  695. if (ip) {
  696. uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
  697. in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
  698. cmd, udp_notify);
  699. } else
  700. in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
  701. }
  702. int
  703. udp_output(inp, m, addr, control)
  704. register struct inpcb *inp;
  705. register struct mbuf *m;
  706. struct mbuf *addr, *control;
  707. {
  708.         struct rtentry *rt;
  709. register struct udpiphdr *ui;
  710. register int len = m->m_pkthdr.len;
  711. struct in_addr laddr;
  712. int s = 0, error = 0;
  713. if (control)
  714. m_freem(control); /* XXX */
  715. if (addr) {
  716. laddr = inp->inp_laddr;
  717. if (inp->inp_faddr.s_addr != INADDR_ANY) {
  718. error = EISCONN;
  719. goto release;
  720. }
  721. /*
  722.  * Must block input while temporarily connected.
  723.  */
  724. s = splnet();
  725. error = in_pcbconnect(inp, addr);
  726. if (error) {
  727. splx(s);
  728. goto release;
  729. }
  730. } else {
  731. if (inp->inp_faddr.s_addr == INADDR_ANY) {
  732. error = ENOTCONN;
  733. goto release;
  734. }
  735. }
  736. /*
  737.  * Calculate data length and get a mbuf
  738.  * for UDP and IP headers.
  739.  */
  740. M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
  741. if (m == 0) {
  742. error = ENOBUFS;
  743. if (addr)
  744.     {
  745.                     in_pcbdisconnect(inp);
  746.     splx (s);
  747.     }
  748. goto release;
  749. }
  750. /*
  751.  * Fill in mbuf with extended UDP header
  752.  * and addresses and length put into network format.
  753.  */
  754. ui = mtod(m, struct udpiphdr *);
  755. ui->ui_next = ui->ui_prev = 0;
  756. ui->ui_x1 = 0;
  757. ui->ui_pr = IPPROTO_UDP;
  758. ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
  759. ui->ui_src = inp->inp_laddr;
  760. ui->ui_dst = inp->inp_faddr;
  761. ui->ui_sport = inp->inp_lport;
  762. ui->ui_dport = inp->inp_fport;
  763. ui->ui_ulen = ui->ui_len;
  764. /*
  765.  * Stuff checksum and output datagram.
  766.  */
  767. ui->ui_sum = 0;
  768. if (udpcksum) {
  769.     if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
  770. ui->ui_sum = 0xffff;
  771. }
  772. ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
  773. ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */
  774. ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */
  775. udpstat.udps_opackets++;
  776.         /*
  777.          * Prevent fragmentation to continue (or trigger) path MTU discovery
  778.          * if the required routing entry and path MTU estimate are available
  779.          * and path MTU discovery is enabled for this socket. Since UDP
  780.          * produces a single datagram for each send operation, the application
  781.          * which enables path MTU discovery must send datagrams equal to
  782.          * the current MTU estimate or the process will not complete.
  783.          */
  784.         rt = inp->inp_route.ro_rt;
  785.         if (rt && (rt->rt_flags & RTF_UP) && !(rt->rt_rmx.rmx_locks & RTV_MTU))
  786.             {
  787.             if (inp->inp_socket->so_options & SO_USEPATHMTU)
  788.                 ( (struct ip *)ui)->ip_off |= IP_DF;
  789.             }
  790. error = ip_output(m, inp->inp_options, &inp->inp_route,
  791.     inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
  792.     inp->inp_moptions);
  793. #ifdef WV_INSTRUMENTATION
  794. #ifdef INCLUDE_WVNET    /* WV_NET_NOTICE event */
  795.     WV_NET_PORTOUT_EVENT_4 (NET_CORE_EVENT, WV_NET_NOTICE, 22, 11,
  796.                             inp->inp_lport, inp->inp_fport,
  797.                             WV_NETEVENT_UDPOUT_FINISH, WV_NET_SEND,
  798.                             inp->inp_socket->so_fd, error,
  799.                             inp->inp_lport, inp->inp_fport)
  800. #endif  /* INCLUDE_WVNET */
  801. #endif
  802. if (addr) {
  803. in_pcbdisconnect(inp);
  804. inp->inp_laddr = laddr;
  805. splx(s);
  806. }
  807. return (error);
  808. release:
  809. #ifdef WV_INSTRUMENTATION
  810. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  811.     WV_NET_EVENT_2 (NET_CORE_EVENT, WV_NET_ERROR, 41, 2,
  812.                     WV_NETEVENT_UDPOUT_FAIL, WV_NET_SEND,
  813.                     inp->inp_socket->so_fd, error)
  814. #endif  /* INCLUDE_WVNET */
  815. #endif
  816. m_freem(m);
  817. return (error);
  818. }
  819. /*ARGSUSED*/
  820. int
  821. udp_usrreq(so, req, m, addr, control)
  822. struct socket *so;
  823. int req;
  824. struct mbuf *m, *addr, *control;
  825. {
  826. struct inpcb *inp = sotoinpcb(so);
  827. int error = 0;
  828. int s;
  829. #ifdef WV_INSTRUMENTATION
  830. #ifdef INCLUDE_WVNET    /* WV_NET_INFO event */
  831.     WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 50, 14,
  832.                      WV_NETEVENT_UDPREQ_START, so->so_fd, req)
  833. #endif  /* INCLUDE_WVNET */
  834. #endif
  835. if (req == PRU_CONTROL)
  836. return (in_control(so, (u_long)m, (caddr_t)addr,
  837. (struct ifnet *)control));
  838. if (inp == NULL && req != PRU_ATTACH) {
  839. #ifdef WV_INSTRUMENTATION
  840. #ifdef INCLUDE_WVNET    /* WV_NET_ERROR event */
  841.         WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_ERROR, 42, 3,
  842.                         WV_NETEVENT_UDPREQ_NOPCB, so->so_fd, req)
  843. #endif  /* INCLUDE_WVNET */
  844. #endif
  845. error = EINVAL;
  846. goto release;
  847. }
  848. /*
  849.  * Note: need to block udp_input while changing
  850.  * the udp pcb queue and/or pcb addresses.
  851.  */
  852. switch (req) {
  853. case PRU_ATTACH:
  854. if (inp != NULL) {
  855. error = EINVAL;
  856. break;
  857. }
  858. s = splnet();
  859. error = in_pcballoc(so, &udbinfo);
  860. splx(s);
  861. if (error)
  862. break;
  863. error = soreserve(so, udp_sendspace, udp_recvspace);
  864. if (error)
  865. break;
  866. ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl;
  867. break;
  868. case PRU_DETACH:
  869. udp_detach(inp);
  870. break;
  871. case PRU_BIND:
  872. s = splnet();
  873. error = in_pcbbind(inp, addr);
  874. splx(s);
  875. break;
  876. case PRU_LISTEN:
  877. error = EOPNOTSUPP;
  878. break;
  879. case PRU_CONNECT:
  880. if (inp->inp_faddr.s_addr != INADDR_ANY) {
  881. error = EISCONN;
  882. break;
  883. }
  884. s = splnet();
  885. error = in_pcbconnect(inp, addr);
  886. splx(s);
  887. if (error == 0)
  888. soisconnected(so);
  889. break;
  890. case PRU_CONNECT2:
  891. error = EOPNOTSUPP;
  892. break;
  893. case PRU_ACCEPT:
  894. error = EOPNOTSUPP;
  895. break;
  896. case PRU_DISCONNECT:
  897. if (inp->inp_faddr.s_addr == INADDR_ANY) {
  898. error = ENOTCONN;
  899. break;
  900. }
  901. s = splnet();
  902. in_pcbdisconnect(inp);
  903. inp->inp_laddr.s_addr = INADDR_ANY;
  904. splx(s);
  905. so->so_state &= ~SS_ISCONNECTED; /* XXX */
  906. break;
  907. case PRU_SHUTDOWN:
  908. socantsendmore(so);
  909. break;
  910. case PRU_SEND:
  911. return (udp_output(inp, m, addr, control));
  912. case PRU_ABORT:
  913. soisdisconnected(so);
  914. udp_detach(inp);
  915. break;
  916. case PRU_SOCKADDR:
  917. in_setsockaddr(inp, addr);
  918. break;
  919. case PRU_PEERADDR:
  920. in_setpeeraddr(inp, addr);
  921. break;
  922. case PRU_SENSE:
  923. /*
  924.  * stat: don't bother with a blocksize.
  925.  */
  926. return (0);
  927. case PRU_SENDOOB:
  928. case PRU_FASTTIMO:
  929. case PRU_SLOWTIMO:
  930. case PRU_PROTORCV:
  931. case PRU_PROTOSEND:
  932. error =  EOPNOTSUPP;
  933. break;
  934. case PRU_RCVD:
  935. case PRU_RCVOOB:
  936. return (EOPNOTSUPP); /* do not free mbuf's */
  937. default:
  938. #ifdef WV_INSTRUMENTATION
  939. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  940.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 32, 1,
  941.                              WV_NETEVENT_UDPREQ_PANIC, so->so_fd, req)
  942. #endif  /* INCLUDE_WVNET */
  943. #endif
  944. panic("udp_usrreq");
  945. }
  946. release:
  947. if (control) {
  948. printf("udp control data unexpectedly retainedn");
  949. m_freem(control);
  950. }
  951. if (m)
  952. m_freem(m);
  953. return (error);
  954. }
  955. static void
  956. udp_detach(inp)
  957. struct inpcb *inp;
  958. {
  959. int s = splnet();
  960. if (inp == udp_last_inpcb)
  961.             udp_last_inpcb = NULL;
  962. in_pcbdetach(inp);
  963. splx(s);
  964. }
  965. #ifdef SYSCTL_SUPPORT
  966. /*
  967.  * Sysctl for udp variables.
  968.  */
  969. udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
  970. int *name;
  971. u_int namelen;
  972. void *oldp;
  973. size_t *oldlenp;
  974. void *newp;
  975. size_t newlen;
  976. {
  977. /*
  978.  * XXX - This event cannot currently occur: the udp_sysctl() routine
  979.  *       is only called by the Unix sysctl command which is not supported
  980.  *       by VxWorks
  981. #ifdef WV_INSTRUMENTATION
  982. #ifdef INCLUDE_WVNET    /@ WV_NET_INFO event @/
  983.     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_INFO, 51, 15,
  984.                      WV_NETEVENT_UDPCTRL_START, name[0])
  985. #endif  /@ INCLUDE_WVNET @/
  986. #endif
  987.  * XXX - end of unused event
  988.  */
  989. /* All sysctl names at this level are terminal. */
  990. if (namelen != 1)
  991. return (ENOTDIR);
  992. switch (name[0]) {
  993. case UDPCTL_CHECKSUM:
  994. return (sysctl_int(oldp, oldlenp, newp, newlen, &udpcksum));
  995. default:
  996. return (ENOPROTOOPT);
  997. }
  998. /* NOTREACHED */
  999. }
  1000. #endif /* SYSCTL_SUPPORT */