123199Smckusick /* 244596Skarels * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California. 332789Sbostic * All rights reserved. 423199Smckusick * 544642Sbostic * %sccs.include.redist.c% 632789Sbostic * 7*56531Sbostic * @(#)udp_usrreq.c 7.26 (Berkeley) 10/11/92 823199Smckusick */ 94784Swnj 10*56531Sbostic #include <sys/param.h> 11*56531Sbostic #include <sys/malloc.h> 12*56531Sbostic #include <sys/mbuf.h> 13*56531Sbostic #include <sys/protosw.h> 14*56531Sbostic #include <sys/socket.h> 15*56531Sbostic #include <sys/socketvar.h> 16*56531Sbostic #include <sys/errno.h> 17*56531Sbostic #include <sys/stat.h> 1810897Ssam 19*56531Sbostic #include <net/if.h> 20*56531Sbostic #include <net/route.h> 2110897Ssam 22*56531Sbostic #include <netinet/in.h> 23*56531Sbostic #include <netinet/in_systm.h> 24*56531Sbostic #include <netinet/ip.h> 25*56531Sbostic #include <netinet/in_pcb.h> 26*56531Sbostic #include <netinet/ip_var.h> 27*56531Sbostic #include <netinet/ip_icmp.h> 28*56531Sbostic #include <netinet/udp.h> 29*56531Sbostic #include <netinet/udp_var.h> 304784Swnj 3144596Skarels struct inpcb *udp_last_inpcb = &udb; 3244596Skarels 334926Swnj /* 344926Swnj * UDP protocol implementation. 354926Swnj * Per RFC 768, August, 1980. 364926Swnj */ 374805Swnj udp_init() 384805Swnj { 394805Swnj 404901Swnj udb.inp_next = udb.inp_prev = &udb; 414805Swnj } 424805Swnj 4326118Skarels #ifndef COMPAT_42 4419519Skarels int udpcksum = 1; 4526118Skarels #else 4626118Skarels int udpcksum = 0; /* XXX */ 4726118Skarels #endif 4831398Skarels int udp_ttl = UDP_TTL; 4926118Skarels 5037324Skarels struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; 514901Swnj 5235794Skarels udp_input(m, iphlen) 5335794Skarels register struct mbuf *m; 5435794Skarels int iphlen; 554784Swnj { 5640688Skarels register struct ip *ip; 5740688Skarels register struct udphdr *uh; 584887Swnj register struct inpcb *inp; 5944596Skarels struct mbuf *opts = 0; 607844Sroot int len; 6140688Skarels struct ip save_ip; 624784Swnj 6344596Skarels udpstat.udps_ipackets++; 6444828Skarels 6544828Skarels /* 6644828Skarels * Strip IP options, if any; should skip this, 6744828Skarels * make available to user, and use on returned packets, 6844828Skarels * but we don't yet have a way to check the checksum 6944828Skarels * with options still present. 7044828Skarels */ 7144828Skarels if (iphlen > sizeof (struct ip)) { 7240688Skarels ip_stripoptions(m, (struct mbuf *)0); 7344828Skarels iphlen = sizeof(struct ip); 7444828Skarels } 7544828Skarels 764926Swnj /* 775246Sroot * Get IP and UDP header together in first mbuf. 784926Swnj */ 7940688Skarels ip = mtod(m, struct ip *); 8040688Skarels if (m->m_len < iphlen + sizeof(struct udphdr)) { 8140688Skarels if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) { 8235288Skarels udpstat.udps_hdrops++; 8335288Skarels return; 8435288Skarels } 8540688Skarels ip = mtod(m, struct ip *); 8635288Skarels } 8740688Skarels uh = (struct udphdr *)((caddr_t)ip + iphlen); 884926Swnj 894926Swnj /* 905246Sroot * Make mbuf data length reflect UDP length. 915246Sroot * If not enough data to reflect UDP length, drop. 924926Swnj */ 9340688Skarels len = ntohs((u_short)uh->uh_ulen); 9440688Skarels if (ip->ip_len != len) { 9540688Skarels if (len > ip->ip_len) { 964926Swnj udpstat.udps_badlen++; 974926Swnj goto bad; 984926Swnj } 9940688Skarels m_adj(m, len - ip->ip_len); 10040688Skarels /* ip->ip_len = len; */ 1014926Swnj } 10224823Skarels /* 10340688Skarels * Save a copy of the IP header in case we want restore it 10440688Skarels * for sending an ICMP error message in response. 10524823Skarels */ 10640688Skarels save_ip = *ip; 1074926Swnj 1084926Swnj /* 1095246Sroot * Checksum extended UDP header and data. 1104926Swnj */ 11140688Skarels if (udpcksum && uh->uh_sum) { 11240688Skarels ((struct ipovly *)ip)->ih_next = 0; 11340688Skarels ((struct ipovly *)ip)->ih_prev = 0; 11440688Skarels ((struct ipovly *)ip)->ih_x1 = 0; 11540688Skarels ((struct ipovly *)ip)->ih_len = uh->uh_ulen; 11640688Skarels if (uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) { 1174926Swnj udpstat.udps_badsum++; 1184901Swnj m_freem(m); 1194901Swnj return; 1204901Swnj } 1214901Swnj } 1224926Swnj 12354716Ssklower #ifdef MULTICAST 12454716Ssklower if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)) || 12554716Ssklower in_broadcast(ip->ip_dst)) { 12654716Ssklower struct socket *last; 12754716Ssklower /* 12854716Ssklower * Deliver a multicast or broadcast datagram to *all* sockets 12954716Ssklower * for which the local and remote addresses and ports match 13054716Ssklower * those of the incoming datagram. This allows more than 13154716Ssklower * one process to receive multi/broadcasts on the same port. 13254716Ssklower * (This really ought to be done for unicast datagrams as 13354716Ssklower * well, but that would cause problems with existing 13454716Ssklower * applications that open both address-specific sockets and 13554716Ssklower * a wildcard socket listening to the same port -- they would 13654716Ssklower * end up receiving duplicates of every unicast datagram. 13754716Ssklower * Those applications open the multiple sockets to overcome an 13854716Ssklower * inadequacy of the UDP socket interface, but for backwards 13954716Ssklower * compatibility we avoid the problem here rather than 14054716Ssklower * fixing the interface. Maybe 4.4BSD will remedy this?) 14154716Ssklower */ 14254716Ssklower 14354716Ssklower /* 14454716Ssklower * Construct sockaddr format source address. 14554716Ssklower */ 14654716Ssklower udp_in.sin_port = uh->uh_sport; 14754716Ssklower udp_in.sin_addr = ip->ip_src; 14854716Ssklower m->m_len -= sizeof (struct udpiphdr); 14954716Ssklower m->m_data += sizeof (struct udpiphdr); 15054716Ssklower /* 15154716Ssklower * Locate pcb(s) for datagram. 15254716Ssklower * (Algorithm copied from raw_intr().) 15354716Ssklower */ 15454716Ssklower last = NULL; 15554716Ssklower for (inp = udb.inp_next; inp != &udb; inp = inp->inp_next) { 15654716Ssklower if (inp->inp_lport != uh->uh_dport) 15754716Ssklower continue; 15854716Ssklower if (inp->inp_laddr.s_addr != INADDR_ANY) { 15954716Ssklower if (inp->inp_laddr.s_addr != 16054716Ssklower ip->ip_dst.s_addr) 16154716Ssklower continue; 16254716Ssklower } 16354716Ssklower if (inp->inp_faddr.s_addr != INADDR_ANY) { 16454716Ssklower if (inp->inp_faddr.s_addr != 16554716Ssklower ip->ip_src.s_addr || 16654716Ssklower inp->inp_fport != uh->uh_sport) 16754716Ssklower continue; 16854716Ssklower } 16954716Ssklower 17054716Ssklower if (last != NULL) { 17154716Ssklower struct mbuf *n; 17254716Ssklower 17354716Ssklower if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { 17454716Ssklower if (sbappendaddr(&last->so_rcv, 17554716Ssklower (struct sockaddr *)&udp_in, 17654716Ssklower n, (struct mbuf *)0) == 0) 17754716Ssklower m_freem(n); 17854716Ssklower else 17954716Ssklower sorwakeup(last); 18054716Ssklower } 18154716Ssklower } 18254716Ssklower last = inp->inp_socket; 18354716Ssklower /* 18454716Ssklower * Don't look for additional matches if this one 18555348Ssklower * does not have the SO_REUSEPORT socket option set. 18654716Ssklower * This heuristic avoids searching through all pcbs 18754716Ssklower * in the common case of a non-shared port. It 18854716Ssklower * assumes that an application will never clear 18955348Ssklower * the SO_REUSEPORT option after setting it. 19054716Ssklower */ 19155348Ssklower if ((last->so_options & SO_REUSEPORT) == 0) 19254716Ssklower break; 19354716Ssklower } 19454716Ssklower 19554716Ssklower if (last == NULL) { 19654716Ssklower /* 19754716Ssklower * No matching pcb found; discard datagram. 19854716Ssklower * (No need to send an ICMP Port Unreachable 19954716Ssklower * for a broadcast or multicast datgram.) 20054716Ssklower */ 20154716Ssklower goto bad; 20254716Ssklower } 20354716Ssklower if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in, 20454716Ssklower m, (struct mbuf *)0) == 0) 20554716Ssklower goto bad; 20654716Ssklower sorwakeup(last); 20754716Ssklower return; 20854716Ssklower } 20954716Ssklower #endif 2104926Swnj /* 2117844Sroot * Locate pcb for datagram. 2124926Swnj */ 21344596Skarels inp = udp_last_inpcb; 21444596Skarels if (inp->inp_lport != uh->uh_dport || 21544596Skarels inp->inp_fport != uh->uh_sport || 21644596Skarels inp->inp_faddr.s_addr != ip->ip_src.s_addr || 21744596Skarels inp->inp_laddr.s_addr != ip->ip_dst.s_addr) { 21844596Skarels inp = in_pcblookup(&udb, ip->ip_src, uh->uh_sport, 21944596Skarels ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD); 22044596Skarels if (inp) 22144596Skarels udp_last_inpcb = inp; 22244596Skarels udpstat.udpps_pcbcachemiss++; 22344596Skarels } 2246584Ssam if (inp == 0) { 22510144Ssam /* don't send ICMP response for broadcast packet */ 22640688Skarels udpstat.udps_noport++; 22754716Ssklower #ifndef MULTICAST 22854716Ssklower /* XXX why don't we do this with MULTICAST? */ 22954716Ssklower if (m->m_flags & (M_BCAST | M_MCAST)) { 23044596Skarels udpstat.udps_noportbcast++; 2316584Ssam goto bad; 23244596Skarels } 23354716Ssklower #endif 23440688Skarels *ip = save_ip; 23544828Skarels ip->ip_len += iphlen; 23635794Skarels icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT); 2376584Ssam return; 2386584Ssam } 2396584Ssam 2404926Swnj /* 2414926Swnj * Construct sockaddr format source address. 2424926Swnj * Stuff source address and datagram in user buffer. 2434926Swnj */ 24440688Skarels udp_in.sin_port = uh->uh_sport; 24540688Skarels udp_in.sin_addr = ip->ip_src; 24644596Skarels if (inp->inp_flags & INP_CONTROLOPTS) { 24744596Skarels struct mbuf **mp = &opts; 24844596Skarels struct mbuf *udp_saveopt(); 24944596Skarels 25044596Skarels if (inp->inp_flags & INP_RECVDSTADDR) { 25144596Skarels *mp = udp_saveopt((caddr_t) &ip->ip_dst, 25244596Skarels sizeof(struct in_addr), IP_RECVDSTADDR); 25344596Skarels if (*mp) 25444596Skarels mp = &(*mp)->m_next; 25544596Skarels } 25644596Skarels #ifdef notyet 25744596Skarels /* options were tossed above */ 25844596Skarels if (inp->inp_flags & INP_RECVOPTS) { 25944596Skarels *mp = udp_saveopt((caddr_t) opts_deleted_above, 26044596Skarels sizeof(struct in_addr), IP_RECVOPTS); 26144596Skarels if (*mp) 26244596Skarels mp = &(*mp)->m_next; 26344596Skarels } 26444596Skarels /* ip_srcroute doesn't do what we want here, need to fix */ 26544596Skarels if (inp->inp_flags & INP_RECVRETOPTS) { 26644596Skarels *mp = udp_saveopt((caddr_t) ip_srcroute(), 26744596Skarels sizeof(struct in_addr), IP_RECVRETOPTS); 26844596Skarels if (*mp) 26944596Skarels mp = &(*mp)->m_next; 27044596Skarels } 27144596Skarels #endif 27244596Skarels } 27340688Skarels iphlen += sizeof(struct udphdr); 27440688Skarels m->m_len -= iphlen; 27540688Skarels m->m_pkthdr.len -= iphlen; 27640688Skarels m->m_data += iphlen; 27712767Ssam if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, 27844596Skarels m, opts) == 0) { 27944596Skarels udpstat.udps_fullsock++; 2804926Swnj goto bad; 28144596Skarels } 2825050Swnj sorwakeup(inp->inp_socket); 2834887Swnj return; 2844926Swnj bad: 2854887Swnj m_freem(m); 28644596Skarels if (opts) 28744596Skarels m_freem(opts); 2884784Swnj } 2894784Swnj 29026426Skarels /* 29144596Skarels * Create a "control" mbuf containing the specified data 29244596Skarels * with the specified type for presentation with a datagram. 29344596Skarels */ 29444596Skarels struct mbuf * 29544596Skarels udp_saveopt(p, size, type) 29644596Skarels caddr_t p; 29744596Skarels register int size; 29844596Skarels int type; 29944596Skarels { 30044596Skarels register struct cmsghdr *cp; 30144596Skarels struct mbuf *m; 30244596Skarels 30344596Skarels if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL) 30444596Skarels return ((struct mbuf *) NULL); 30544596Skarels cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); 30645645Ssklower bcopy(p, (caddr_t)(cp + 1), size); 30744596Skarels size += sizeof(*cp); 30844596Skarels m->m_len = size; 30944596Skarels cp->cmsg_len = size; 31044596Skarels cp->cmsg_level = IPPROTO_IP; 31144596Skarels cp->cmsg_type = type; 31244596Skarels return (m); 31344596Skarels } 31444596Skarels 31544596Skarels /* 31626426Skarels * Notify a udp user of an asynchronous error; 31726426Skarels * just wake up so that he can collect error status. 31826426Skarels */ 31944596Skarels udp_notify(inp, errno) 32026426Skarels register struct inpcb *inp; 32152949Storek int errno; 32226426Skarels { 32326426Skarels 32444596Skarels inp->inp_socket->so_error = errno; 32526426Skarels sorwakeup(inp->inp_socket); 32626426Skarels sowwakeup(inp->inp_socket); 32726426Skarels } 32826426Skarels 32940688Skarels udp_ctlinput(cmd, sa, ip) 3306591Ssam int cmd; 33124823Skarels struct sockaddr *sa; 33240688Skarels register struct ip *ip; 3336591Ssam { 33440688Skarels register struct udphdr *uh; 33540688Skarels extern struct in_addr zeroin_addr; 3366591Ssam extern u_char inetctlerrmap[]; 3376591Ssam 33840688Skarels if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0) 3396591Ssam return; 34040688Skarels if (ip) { 34140688Skarels uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 34240688Skarels in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport, 34340688Skarels cmd, udp_notify); 34440688Skarels } else 34540688Skarels in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify); 3466591Ssam } 3476591Ssam 34842184Skarels udp_output(inp, m, addr, control) 34926060Skarels register struct inpcb *inp; 35035794Skarels register struct mbuf *m; 35142184Skarels struct mbuf *addr, *control; 3524784Swnj { 3534926Swnj register struct udpiphdr *ui; 35435794Skarels register int len = m->m_pkthdr.len; 35542184Skarels struct in_addr laddr; 35642184Skarels int s, error = 0; 3574784Swnj 35842184Skarels if (control) 35942184Skarels m_freem(control); /* XXX */ 36042184Skarels 36142184Skarels if (addr) { 36242184Skarels laddr = inp->inp_laddr; 36342184Skarels if (inp->inp_faddr.s_addr != INADDR_ANY) { 36442184Skarels error = EISCONN; 36542184Skarels goto release; 36642184Skarels } 36742184Skarels /* 36842184Skarels * Must block input while temporarily connected. 36942184Skarels */ 37042184Skarels s = splnet(); 37142184Skarels error = in_pcbconnect(inp, addr); 37242184Skarels if (error) { 37342184Skarels splx(s); 37442184Skarels goto release; 37542184Skarels } 37642184Skarels } else { 37742184Skarels if (inp->inp_faddr.s_addr == INADDR_ANY) { 37842184Skarels error = ENOTCONN; 37942184Skarels goto release; 38042184Skarels } 38142184Skarels } 3824926Swnj /* 3834926Swnj * Calculate data length and get a mbuf 3845246Sroot * for UDP and IP headers. 3854926Swnj */ 38650715Smckusick M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); 38750715Smckusick if (m == 0) { 38850715Smckusick error = ENOBUFS; 38950715Smckusick goto release; 39050715Smckusick } 3914784Swnj 3924926Swnj /* 3935246Sroot * Fill in mbuf with extended UDP header 3944926Swnj * and addresses and length put into network format. 3954926Swnj */ 3964926Swnj ui = mtod(m, struct udpiphdr *); 3974926Swnj ui->ui_next = ui->ui_prev = 0; 3984926Swnj ui->ui_x1 = 0; 3994926Swnj ui->ui_pr = IPPROTO_UDP; 40015226Ssam ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); 4015050Swnj ui->ui_src = inp->inp_laddr; 4025050Swnj ui->ui_dst = inp->inp_faddr; 4035050Swnj ui->ui_sport = inp->inp_lport; 4045050Swnj ui->ui_dport = inp->inp_fport; 40515226Ssam ui->ui_ulen = ui->ui_len; 4064784Swnj 4074926Swnj /* 4084926Swnj * Stuff checksum and output datagram. 4094926Swnj */ 4104926Swnj ui->ui_sum = 0; 41119519Skarels if (udpcksum) { 41219519Skarels if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) 41333715Skarels ui->ui_sum = 0xffff; 41421112Skarels } 4155050Swnj ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 41644596Skarels ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ 41744596Skarels ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ 41840688Skarels udpstat.udps_opackets++; 41942184Skarels error = ip_output(m, inp->inp_options, &inp->inp_route, 42054716Ssklower inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST) 42154716Ssklower #ifdef MULTICAST 42254716Ssklower , inp->inp_moptions 42354716Ssklower #endif 42454716Ssklower ); 42542184Skarels 42642184Skarels if (addr) { 42742184Skarels in_pcbdisconnect(inp); 42842184Skarels inp->inp_laddr = laddr; 42942184Skarels splx(s); 43042184Skarels } 43142184Skarels return (error); 43242184Skarels 43342184Skarels release: 43442184Skarels m_freem(m); 43542184Skarels return (error); 4364784Swnj } 4374784Swnj 43838354Smckusick u_long udp_sendspace = 9216; /* really max datagram size */ 43938354Smckusick u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in)); 44038354Smckusick /* 40 1K datagrams */ 44118368Skarels 4428602Sroot /*ARGSUSED*/ 44342184Skarels udp_usrreq(so, req, m, addr, control) 4444887Swnj struct socket *so; 4454784Swnj int req; 44642184Skarels struct mbuf *m, *addr, *control; 4474784Swnj { 4484887Swnj struct inpcb *inp = sotoinpcb(so); 4496507Ssam int error = 0; 45044596Skarels int s; 4514784Swnj 45218368Skarels if (req == PRU_CONTROL) 45342184Skarels return (in_control(so, (int)m, (caddr_t)addr, 45440688Skarels (struct ifnet *)control)); 45511080Ssam if (inp == NULL && req != PRU_ATTACH) { 45611080Ssam error = EINVAL; 45711080Ssam goto release; 45811080Ssam } 45944596Skarels /* 46044968Skarels * Note: need to block udp_input while changing 46144968Skarels * the udp pcb queue and/or pcb addresses. 46244596Skarels */ 4634784Swnj switch (req) { 4644784Swnj 4654784Swnj case PRU_ATTACH: 46611080Ssam if (inp != NULL) { 46711080Ssam error = EINVAL; 46811080Ssam break; 46911080Ssam } 47044596Skarels s = splnet(); 4718273Sroot error = in_pcballoc(so, &udb); 47244596Skarels splx(s); 4738273Sroot if (error) 4748273Sroot break; 47518368Skarels error = soreserve(so, udp_sendspace, udp_recvspace); 4768273Sroot if (error) 4778273Sroot break; 47844596Skarels ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = udp_ttl; 4794887Swnj break; 4804784Swnj 4814784Swnj case PRU_DETACH: 48244968Skarels udp_detach(inp); 4834887Swnj break; 4844784Swnj 4858273Sroot case PRU_BIND: 48644968Skarels s = splnet(); 48742184Skarels error = in_pcbbind(inp, addr); 48844968Skarels splx(s); 4898273Sroot break; 4908273Sroot 4918273Sroot case PRU_LISTEN: 4928273Sroot error = EOPNOTSUPP; 4938273Sroot break; 4948273Sroot 4954784Swnj case PRU_CONNECT: 49611080Ssam if (inp->inp_faddr.s_addr != INADDR_ANY) { 49711080Ssam error = EISCONN; 49811080Ssam break; 49911080Ssam } 50044968Skarels s = splnet(); 50142184Skarels error = in_pcbconnect(inp, addr); 50244968Skarels splx(s); 5036507Ssam if (error == 0) 5046507Ssam soisconnected(so); 5054887Swnj break; 5064784Swnj 50713118Ssam case PRU_CONNECT2: 50813118Ssam error = EOPNOTSUPP; 50913118Ssam break; 51013118Ssam 5114926Swnj case PRU_ACCEPT: 51211080Ssam error = EOPNOTSUPP; 51311080Ssam break; 5144926Swnj 5154784Swnj case PRU_DISCONNECT: 51611080Ssam if (inp->inp_faddr.s_addr == INADDR_ANY) { 51711080Ssam error = ENOTCONN; 51811080Ssam break; 51911080Ssam } 52044968Skarels s = splnet(); 5215166Swnj in_pcbdisconnect(inp); 52240688Skarels inp->inp_laddr.s_addr = INADDR_ANY; 52344968Skarels splx(s); 52426404Skarels so->so_state &= ~SS_ISCONNECTED; /* XXX */ 5254784Swnj break; 5264784Swnj 5274912Swnj case PRU_SHUTDOWN: 5284912Swnj socantsendmore(so); 5294912Swnj break; 5304912Swnj 53142184Skarels case PRU_SEND: 53244596Skarels return (udp_output(inp, m, addr, control)); 5334784Swnj 5344784Swnj case PRU_ABORT: 53531750Skarels soisdisconnected(so); 53644968Skarels udp_detach(inp); 5374784Swnj break; 5384784Swnj 5396511Ssam case PRU_SOCKADDR: 54042184Skarels in_setsockaddr(inp, addr); 5416511Ssam break; 5426511Ssam 54314124Ssam case PRU_PEERADDR: 54442184Skarels in_setpeeraddr(inp, addr); 54514124Ssam break; 54614124Ssam 54716988Skarels case PRU_SENSE: 54816988Skarels /* 54916988Skarels * stat: don't bother with a blocksize. 55016988Skarels */ 55116988Skarels return (0); 55216988Skarels 55312205Ssam case PRU_SENDOOB: 55412205Ssam case PRU_FASTTIMO: 55512205Ssam case PRU_SLOWTIMO: 55612205Ssam case PRU_PROTORCV: 55712205Ssam case PRU_PROTOSEND: 55812205Ssam error = EOPNOTSUPP; 55912205Ssam break; 56013118Ssam 56116799Skarels case PRU_RCVD: 56216799Skarels case PRU_RCVOOB: 56316799Skarels return (EOPNOTSUPP); /* do not free mbuf's */ 56416799Skarels 56513118Ssam default: 56613118Ssam panic("udp_usrreq"); 5674805Swnj } 56844596Skarels 56911080Ssam release: 57042184Skarels if (control) { 57142184Skarels printf("udp control data unexpectedly retained\n"); 57242184Skarels m_freem(control); 57342184Skarels } 57442184Skarels if (m) 57511080Ssam m_freem(m); 5766507Ssam return (error); 5774784Swnj } 57844968Skarels 57944968Skarels udp_detach(inp) 58044968Skarels struct inpcb *inp; 58144968Skarels { 58244968Skarels int s = splnet(); 58344968Skarels 58444968Skarels if (inp == udp_last_inpcb) 58544968Skarels udp_last_inpcb = &udb; 58644968Skarels in_pcbdetach(inp); 58744968Skarels splx(s); 58844968Skarels } 589