The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/udp_usrreq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
    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  *      @(#)udp_usrreq.c        8.6 (Berkeley) 5/23/95
   34  * $FreeBSD: src/sys/netinet/udp_usrreq.c,v 1.30.2.4 1999/09/05 08:18:49 peter Exp $
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/queue.h>
   39 #include <sys/systm.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mbuf.h>
   42 #include <sys/protosw.h>
   43 #include <sys/socket.h>
   44 #include <sys/socketvar.h>
   45 #include <sys/errno.h>
   46 #include <sys/stat.h>
   47 #include <sys/kernel.h>
   48 #include <sys/sysctl.h>
   49 #include <sys/syslog.h>
   50 
   51 #include <net/if.h>
   52 #include <net/route.h>
   53 
   54 #include <netinet/in.h>
   55 #include <netinet/in_systm.h>
   56 #include <netinet/ip.h>
   57 #include <netinet/in_pcb.h>
   58 #include <netinet/in_var.h>
   59 #include <netinet/ip_var.h>
   60 #include <netinet/ip_icmp.h>
   61 #include <netinet/udp.h>
   62 #include <netinet/udp_var.h>
   63 
   64 /*
   65  * UDP protocol implementation.
   66  * Per RFC 768, August, 1980.
   67  */
   68 #ifndef COMPAT_42
   69 static int      udpcksum = 1;
   70 #else
   71 static int      udpcksum = 0;           /* XXX */
   72 #endif
   73 SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
   74                 &udpcksum, 0, "");
   75 
   76 static int log_in_vain = 0;
   77 SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, 
   78         &log_in_vain, 0, "");
   79 
   80 static struct   inpcbhead udb;          /* from udp_var.h */
   81 static struct   inpcbinfo udbinfo;
   82 
   83 #ifndef UDBHASHSIZE
   84 #define UDBHASHSIZE 64
   85 #endif
   86 
   87 static struct   udpstat udpstat;        /* from udp_var.h */
   88 SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
   89         &udpstat, udpstat, "");
   90 
   91 static struct   sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
   92 
   93 static  void udp_detach __P((struct inpcb *));
   94 static  int udp_output __P((struct inpcb *, struct mbuf *, struct mbuf *,
   95                             struct mbuf *));
   96 static  void udp_notify __P((struct inpcb *, int));
   97 
   98 void
   99 udp_init()
  100 {
  101         LIST_INIT(&udb);
  102         udbinfo.listhead = &udb;
  103         udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
  104 }
  105 
  106 void
  107 udp_input(m, iphlen)
  108         register struct mbuf *m;
  109         int iphlen;
  110 {
  111         register struct ip *ip;
  112         register struct udphdr *uh;
  113         register struct inpcb *inp;
  114         struct mbuf *opts = 0;
  115         int len;
  116         struct ip save_ip;
  117 
  118         udpstat.udps_ipackets++;
  119 
  120         /*
  121          * Strip IP options, if any; should skip this,
  122          * make available to user, and use on returned packets,
  123          * but we don't yet have a way to check the checksum
  124          * with options still present.
  125          */
  126         if (iphlen > sizeof (struct ip)) {
  127                 ip_stripoptions(m, (struct mbuf *)0);
  128                 iphlen = sizeof(struct ip);
  129         }
  130 
  131         /*
  132          * Get IP and UDP header together in first mbuf.
  133          */
  134         ip = mtod(m, struct ip *);
  135         if (m->m_len < iphlen + sizeof(struct udphdr)) {
  136                 if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
  137                         udpstat.udps_hdrops++;
  138                         return;
  139                 }
  140                 ip = mtod(m, struct ip *);
  141         }
  142         uh = (struct udphdr *)((caddr_t)ip + iphlen);
  143 
  144         /*
  145          * Make mbuf data length reflect UDP length.
  146          * If not enough data to reflect UDP length, drop.
  147          */
  148         len = ntohs((u_short)uh->uh_ulen);
  149         if (ip->ip_len != len) {
  150                 if (len > ip->ip_len || len < sizeof(struct udphdr)) {
  151                         udpstat.udps_badlen++;
  152                         goto bad;
  153                 }
  154                 m_adj(m, len - ip->ip_len);
  155                 /* ip->ip_len = len; */
  156         }
  157         /*
  158          * Save a copy of the IP header in case we want restore it
  159          * for sending an ICMP error message in response.
  160          */
  161         save_ip = *ip;
  162 
  163         /*
  164          * Checksum extended UDP header and data.
  165          */
  166         if (uh->uh_sum) {
  167                 ((struct ipovly *)ip)->ih_next = 0;
  168                 ((struct ipovly *)ip)->ih_prev = 0;
  169                 ((struct ipovly *)ip)->ih_x1 = 0;
  170                 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
  171                 uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
  172                 if (uh->uh_sum) {
  173                         udpstat.udps_badsum++;
  174                         m_freem(m);
  175                         return;
  176                 }
  177         }
  178 
  179         if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
  180             in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
  181                 struct inpcb *last;
  182                 /*
  183                  * Deliver a multicast or broadcast datagram to *all* sockets
  184                  * for which the local and remote addresses and ports match
  185                  * those of the incoming datagram.  This allows more than
  186                  * one process to receive multi/broadcasts on the same port.
  187                  * (This really ought to be done for unicast datagrams as
  188                  * well, but that would cause problems with existing
  189                  * applications that open both address-specific sockets and
  190                  * a wildcard socket listening to the same port -- they would
  191                  * end up receiving duplicates of every unicast datagram.
  192                  * Those applications open the multiple sockets to overcome an
  193                  * inadequacy of the UDP socket interface, but for backwards
  194                  * compatibility we avoid the problem here rather than
  195                  * fixing the interface.  Maybe 4.5BSD will remedy this?)
  196                  */
  197 
  198                 /*
  199                  * Construct sockaddr format source address.
  200                  */
  201                 udp_in.sin_port = uh->uh_sport;
  202                 udp_in.sin_addr = ip->ip_src;
  203                 m->m_len -= sizeof (struct udpiphdr);
  204                 m->m_data += sizeof (struct udpiphdr);
  205                 /*
  206                  * Locate pcb(s) for datagram.
  207                  * (Algorithm copied from raw_intr().)
  208                  */
  209                 last = NULL;
  210                 for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
  211                         if (inp->inp_lport != uh->uh_dport)
  212                                 continue;
  213                         if (inp->inp_laddr.s_addr != INADDR_ANY) {
  214                                 if (inp->inp_laddr.s_addr !=
  215                                     ip->ip_dst.s_addr)
  216                                         continue;
  217                         }
  218                         if (inp->inp_faddr.s_addr != INADDR_ANY) {
  219                                 if (inp->inp_faddr.s_addr !=
  220                                     ip->ip_src.s_addr ||
  221                                     inp->inp_fport != uh->uh_sport)
  222                                         continue;
  223                         }
  224 
  225                         if (last != NULL) {
  226                                 struct mbuf *n;
  227 
  228                                 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
  229                                         if (last->inp_flags & INP_CONTROLOPTS
  230                                             || last->inp_socket->so_options & SO_TIMESTAMP)
  231                                                 ip_savecontrol(last, &opts, ip, n);
  232                                         if (sbappendaddr(&last->inp_socket->so_rcv,
  233                                                 (struct sockaddr *)&udp_in,
  234                                                 n, opts) == 0) {
  235                                                 m_freem(n);
  236                                                 if (opts)
  237                                                     m_freem(opts);
  238                                                 udpstat.udps_fullsock++;
  239                                         } else
  240                                                 sorwakeup(last->inp_socket);
  241                                         opts = 0;
  242                                 }
  243                         }
  244                         last = inp;
  245                         /*
  246                          * Don't look for additional matches if this one does
  247                          * not have either the SO_REUSEPORT or SO_REUSEADDR
  248                          * socket options set.  This heuristic avoids searching
  249                          * through all pcbs in the common case of a non-shared
  250                          * port.  It * assumes that an application will never
  251                          * clear these options after setting them.
  252                          */
  253                         if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR) == 0))
  254                                 break;
  255                 }
  256 
  257                 if (last == NULL) {
  258                         /*
  259                          * No matching pcb found; discard datagram.
  260                          * (No need to send an ICMP Port Unreachable
  261                          * for a broadcast or multicast datgram.)
  262                          */
  263                         udpstat.udps_noportbcast++;
  264                         goto bad;
  265                 }
  266                 if (last->inp_flags & INP_CONTROLOPTS
  267                     || last->inp_socket->so_options & SO_TIMESTAMP)
  268                         ip_savecontrol(last, &opts, ip, m);
  269                 if (sbappendaddr(&last->inp_socket->so_rcv,
  270                      (struct sockaddr *)&udp_in,
  271                      m, opts) == 0) {
  272                         udpstat.udps_fullsock++;
  273                         goto bad;
  274                 }
  275                 sorwakeup(last->inp_socket);
  276                 return;
  277         }
  278         /*
  279          * Locate pcb for datagram.
  280          */
  281         inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport,
  282             ip->ip_dst, uh->uh_dport, 1);
  283         if (inp == NULL) {
  284                 if (log_in_vain) {
  285                         char buf[4*sizeof "123"];
  286 
  287                         strcpy(buf, inet_ntoa(ip->ip_dst));
  288                         log(LOG_INFO, "Connection attempt to UDP %s:%d"
  289                             " from %s:%d\n",
  290                                 buf, ntohs(uh->uh_dport),
  291                                 inet_ntoa(ip->ip_src), ntohs(uh->uh_sport));
  292                 }
  293                 udpstat.udps_noport++;
  294                 if (m->m_flags & (M_BCAST | M_MCAST)) {
  295                         udpstat.udps_noportbcast++;
  296                         goto bad;
  297                 }
  298                 *ip = save_ip;
  299                 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
  300                 return;
  301         }
  302 
  303         /*
  304          * Construct sockaddr format source address.
  305          * Stuff source address and datagram in user buffer.
  306          */
  307         udp_in.sin_port = uh->uh_sport;
  308         udp_in.sin_addr = ip->ip_src;
  309         if (inp->inp_flags & INP_CONTROLOPTS
  310             || inp->inp_socket->so_options & SO_TIMESTAMP)
  311                 ip_savecontrol(inp, &opts, ip, m);
  312         iphlen += sizeof(struct udphdr);
  313         m->m_len -= iphlen;
  314         m->m_pkthdr.len -= iphlen;
  315         m->m_data += iphlen;
  316         if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
  317             m, opts) == 0) {
  318                 udpstat.udps_fullsock++;
  319                 goto bad;
  320         }
  321         sorwakeup(inp->inp_socket);
  322         return;
  323 bad:
  324         m_freem(m);
  325         if (opts)
  326                 m_freem(opts);
  327 }
  328 
  329 /*
  330  * Notify a udp user of an asynchronous error;
  331  * just wake up so that he can collect error status.
  332  */
  333 static void
  334 udp_notify(inp, errno)
  335         register struct inpcb *inp;
  336         int errno;
  337 {
  338         inp->inp_socket->so_error = errno;
  339         sorwakeup(inp->inp_socket);
  340         sowwakeup(inp->inp_socket);
  341 }
  342 
  343 void
  344 udp_ctlinput(cmd, sa, vip)
  345         int cmd;
  346         struct sockaddr *sa;
  347         void *vip;
  348 {
  349         register struct ip *ip = vip;
  350         register struct udphdr *uh;
  351 
  352         if (!PRC_IS_REDIRECT(cmd) &&
  353             ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0))
  354                 return;
  355         if (ip) {
  356                 uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
  357                 in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
  358                         cmd, udp_notify);
  359         } else
  360                 in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
  361 }
  362 
  363 static int
  364 udp_output(inp, m, addr, control)
  365         register struct inpcb *inp;
  366         register struct mbuf *m;
  367         struct mbuf *addr, *control;
  368 {
  369         register struct udpiphdr *ui;
  370         register int len = m->m_pkthdr.len;
  371         struct in_addr laddr;
  372         int s = 0, error = 0;
  373 
  374         if (control)
  375                 m_freem(control);               /* XXX */
  376 
  377         if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
  378                 error = EMSGSIZE;
  379                 goto release;
  380         }
  381 
  382         if (addr) {
  383                 laddr = inp->inp_laddr;
  384                 if (inp->inp_faddr.s_addr != INADDR_ANY) {
  385                         error = EISCONN;
  386                         goto release;
  387                 }
  388                 /*
  389                  * Must block input while temporarily connected.
  390                  */
  391                 s = splnet();
  392                 error = in_pcbconnect(inp, addr);
  393                 if (error) {
  394                         splx(s);
  395                         goto release;
  396                 }
  397         } else {
  398                 if (inp->inp_faddr.s_addr == INADDR_ANY) {
  399                         error = ENOTCONN;
  400                         goto release;
  401                 }
  402         }
  403         /*
  404          * Calculate data length and get a mbuf
  405          * for UDP and IP headers.
  406          */
  407         M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
  408         if (m == 0) {
  409                 error = ENOBUFS;
  410                 if (addr)
  411                         splx(s);
  412                 goto release;
  413         }
  414 
  415         /*
  416          * Fill in mbuf with extended UDP header
  417          * and addresses and length put into network format.
  418          */
  419         ui = mtod(m, struct udpiphdr *);
  420         ui->ui_next = ui->ui_prev = 0;
  421         ui->ui_x1 = 0;
  422         ui->ui_pr = IPPROTO_UDP;
  423         ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
  424         ui->ui_src = inp->inp_laddr;
  425         ui->ui_dst = inp->inp_faddr;
  426         ui->ui_sport = inp->inp_lport;
  427         ui->ui_dport = inp->inp_fport;
  428         ui->ui_ulen = ui->ui_len;
  429 
  430         /*
  431          * Stuff checksum and output datagram.
  432          */
  433         ui->ui_sum = 0;
  434         if (udpcksum) {
  435             if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
  436                 ui->ui_sum = 0xffff;
  437         }
  438         ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
  439         ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl;    /* XXX */
  440         ((struct ip *)ui)->ip_tos = inp->inp_ip_tos;    /* XXX */
  441         udpstat.udps_opackets++;
  442         error = ip_output(m, inp->inp_options, &inp->inp_route,
  443             inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
  444             inp->inp_moptions);
  445 
  446         if (addr) {
  447                 in_pcbdisconnect(inp);
  448                 inp->inp_laddr = laddr;
  449                 splx(s);
  450         }
  451         return (error);
  452 
  453 release:
  454         m_freem(m);
  455         return (error);
  456 }
  457 
  458 static u_long   udp_sendspace = 9216;           /* really max datagram size */
  459                                         /* 40 1K datagrams */
  460 SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
  461         &udp_sendspace, 0, "");
  462 
  463 static u_long   udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
  464 SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
  465         &udp_recvspace, 0, "");
  466 
  467 /*ARGSUSED*/
  468 int
  469 udp_usrreq(so, req, m, addr, control)
  470         struct socket *so;
  471         int req;
  472         struct mbuf *m, *addr, *control;
  473 {
  474         struct inpcb *inp = sotoinpcb(so);
  475         int error = 0;
  476         int s;
  477 
  478         if (req == PRU_CONTROL)
  479                 return (in_control(so, (u_long)m, (caddr_t)addr,
  480                         (struct ifnet *)control));
  481         if (inp == NULL && req != PRU_ATTACH) {
  482                 error = EINVAL;
  483                 goto release;
  484         }
  485         /*
  486          * Note: need to block udp_input while changing
  487          * the udp pcb queue and/or pcb addresses.
  488          */
  489         switch (req) {
  490 
  491         case PRU_ATTACH:
  492                 if (inp != NULL) {
  493                         error = EINVAL;
  494                         break;
  495                 }
  496                 s = splnet();
  497                 error = in_pcballoc(so, &udbinfo);
  498                 splx(s);
  499                 if (error)
  500                         break;
  501                 error = soreserve(so, udp_sendspace, udp_recvspace);
  502                 if (error)
  503                         break;
  504                 ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
  505                 break;
  506 
  507         case PRU_DETACH:
  508                 udp_detach(inp);
  509                 break;
  510 
  511         case PRU_BIND:
  512                 s = splnet();
  513                 error = in_pcbbind(inp, addr);
  514                 splx(s);
  515                 break;
  516 
  517         case PRU_LISTEN:
  518                 error = EOPNOTSUPP;
  519                 break;
  520 
  521         case PRU_CONNECT:
  522                 if (inp->inp_faddr.s_addr != INADDR_ANY) {
  523                         error = EISCONN;
  524                         break;
  525                 }
  526                 s = splnet();
  527                 error = in_pcbconnect(inp, addr);
  528                 splx(s);
  529                 if (error == 0)
  530                         soisconnected(so);
  531                 break;
  532 
  533         case PRU_CONNECT2:
  534                 error = EOPNOTSUPP;
  535                 break;
  536 
  537         case PRU_ACCEPT:
  538                 error = EOPNOTSUPP;
  539                 break;
  540 
  541         case PRU_DISCONNECT:
  542                 if (inp->inp_faddr.s_addr == INADDR_ANY) {
  543                         error = ENOTCONN;
  544                         break;
  545                 }
  546                 s = splnet();
  547                 in_pcbdisconnect(inp);
  548                 inp->inp_laddr.s_addr = INADDR_ANY;
  549                 splx(s);
  550                 so->so_state &= ~SS_ISCONNECTED;                /* XXX */
  551                 break;
  552 
  553         case PRU_SHUTDOWN:
  554                 socantsendmore(so);
  555                 break;
  556 
  557         case PRU_SEND:
  558                 return (udp_output(inp, m, addr, control));
  559 
  560         case PRU_ABORT:
  561                 soisdisconnected(so);
  562                 udp_detach(inp);
  563                 break;
  564 
  565         case PRU_SOCKADDR:
  566                 in_setsockaddr(inp, addr);
  567                 break;
  568 
  569         case PRU_PEERADDR:
  570                 in_setpeeraddr(inp, addr);
  571                 break;
  572 
  573         case PRU_SENSE:
  574                 /*
  575                  * stat: don't bother with a blocksize.
  576                  */
  577                 return (0);
  578 
  579         case PRU_SENDOOB:
  580         case PRU_FASTTIMO:
  581         case PRU_SLOWTIMO:
  582         case PRU_PROTORCV:
  583         case PRU_PROTOSEND:
  584                 error =  EOPNOTSUPP;
  585                 break;
  586 
  587         case PRU_RCVD:
  588         case PRU_RCVOOB:
  589                 return (EOPNOTSUPP);    /* do not free mbuf's */
  590 
  591         default:
  592                 panic("udp_usrreq");
  593         }
  594 
  595 release:
  596         if (control) {
  597                 printf("udp control data unexpectedly retained\n");
  598                 m_freem(control);
  599         }
  600         if (m)
  601                 m_freem(m);
  602         return (error);
  603 }
  604 
  605 static void
  606 udp_detach(inp)
  607         struct inpcb *inp;
  608 {
  609         int s = splnet();
  610 
  611         in_pcbdetach(inp);
  612         splx(s);
  613 }

Cache object: 60b91b6ecc370535742fdd7820f7fa4d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.