1*4955Swnj /* udp_usrreq.c 4.7 81/11/20 */ 24784Swnj 34784Swnj #include "../h/param.h" 44887Swnj #include "../h/dir.h" 54887Swnj #include "../h/user.h" 64784Swnj #include "../h/mbuf.h" 74805Swnj #include "../h/protosw.h" 84887Swnj #include "../h/socket.h" 94887Swnj #include "../h/socketvar.h" 104805Swnj #include "../net/inet.h" 114887Swnj #include "../net/inet_pcb.h" 124805Swnj #include "../net/inet_systm.h" 134901Swnj #include "../net/ip.h" 144901Swnj #include "../net/ip_var.h" 154887Swnj #include "../net/udp.h" 164887Swnj #include "../net/udp_var.h" 174784Swnj 184926Swnj /* 194926Swnj * UDP protocol implementation. 204926Swnj * Per RFC 768, August, 1980. 214926Swnj */ 224805Swnj udp_init() 234805Swnj { 244805Swnj 254901Swnj udb.inp_next = udb.inp_prev = &udb; 264805Swnj } 274805Swnj 284901Swnj int udpcksum; 294926Swnj struct sockaddr_in udp_in = { AF_INET }; 304901Swnj 314926Swnj udp_input(m0) 324926Swnj struct mbuf *m0; 334784Swnj { 344901Swnj register struct udpiphdr *ui; 354887Swnj register struct inpcb *inp; 364926Swnj register struct mbuf *m; 374926Swnj int len, ulen; 384784Swnj 394926Swnj /* 404926Swnj * Get ip and udp header together in first mbuf. 414926Swnj */ 424926Swnj m = m0; 434901Swnj ui = mtod(m, struct udpiphdr *); 444926Swnj if (ui->ui_len > sizeof (struct ip)) 45*4955Swnj ip_stripoptions((struct ip *)ui, (char *)0); 464926Swnj if (m->m_len < sizeof (struct udpiphdr) && 474926Swnj m_pullup(m, sizeof (struct udpiphdr)) == 0) { 484926Swnj udpstat.udps_hdrops++; 494926Swnj goto bad; 504926Swnj } 514926Swnj 524926Swnj /* 534926Swnj * Make mbuf data length reflect udp length. 544926Swnj * If not enough data to reflect udp length, drop. 554926Swnj */ 56*4955Swnj ulen = ntohs((u_short)ui->ui_ulen); 574926Swnj len = sizeof (struct udpiphdr) + ulen; 584926Swnj if (((struct ip *)ui)->ip_len != len) { 594926Swnj if (len > ((struct ip *)ui)->ip_len) { 604926Swnj udpstat.udps_badlen++; 614926Swnj goto bad; 624926Swnj } 634926Swnj m_adj(m, ((struct ip *)ui)->ip_len - len); 644926Swnj /* (struct ip *)ui->ip_len = len; */ 654926Swnj } 664926Swnj 674926Swnj /* 684926Swnj * Checksum extended udp header and data. 694926Swnj */ 704901Swnj if (udpcksum) { 714926Swnj ui->ui_next = ui->ui_prev = 0; 724926Swnj ui->ui_x1 = 0; 73*4955Swnj ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen)); 744926Swnj if (ui->ui_sum = inet_cksum(m, len)) { 754926Swnj udpstat.udps_badsum++; 764901Swnj printf("udp cksum %x\n", ui->ui_sum); 774901Swnj m_freem(m); 784901Swnj return; 794901Swnj } 804901Swnj } 814926Swnj 824926Swnj /* 834926Swnj * Convert addresses and ports to host format. 844926Swnj * Locate pcb for datagram. 854926Swnj */ 864926Swnj ui->ui_src.s_addr = ntohl(ui->ui_src.s_addr); 874926Swnj ui->ui_dst.s_addr = ntohl(ui->ui_dst.s_addr); 884926Swnj ui->ui_sport = ntohs(ui->ui_sport); 894926Swnj ui->ui_dport = ntohs(ui->ui_dport); 904926Swnj inp = in_pcblookup(&udb, 914926Swnj ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 924887Swnj if (inp == 0) 934926Swnj goto bad; 944926Swnj 954926Swnj /* 964926Swnj * Construct sockaddr format source address. 974926Swnj * Stuff source address and datagram in user buffer. 984926Swnj */ 994926Swnj udp_in.sin_port = ui->ui_sport; 1004926Swnj udp_in.sin_addr = ui->ui_src; 101*4955Swnj if (sbappendaddr(&inp->inp_socket->so_snd, (struct sockaddr *)&udp_in, m) == 0) 1024926Swnj goto bad; 1034887Swnj return; 1044926Swnj bad: 1054887Swnj m_freem(m); 1064784Swnj } 1074784Swnj 1084887Swnj udp_ctlinput(m) 1094887Swnj struct mbuf *m; 1104887Swnj { 1114887Swnj 1124887Swnj m_freem(m); 1134887Swnj } 1144887Swnj 1154926Swnj /*ARGSUSED*/ 116*4955Swnj udp_output(inp, m0) 1174926Swnj struct inpcb *inp; 1184926Swnj struct mbuf *m0; 1194784Swnj { 1204926Swnj register struct mbuf *m; 1214926Swnj register struct udpiphdr *ui; 1224926Swnj register int len = 0; 1234784Swnj 1244926Swnj /* 1254926Swnj * Calculate data length and get a mbuf 1264926Swnj * for udp and ip headers. 1274926Swnj */ 1284926Swnj for (m = m0; m; m = m->m_next) 1294926Swnj len += m->m_len; 1304926Swnj m = m_get(0); 1314926Swnj if (m == 0) 1324926Swnj goto bad; 1334784Swnj 1344926Swnj /* 1354926Swnj * Fill in mbuf with extended udp header 1364926Swnj * and addresses and length put into network format. 1374926Swnj */ 1384926Swnj m->m_off = MMAXOFF - sizeof (struct udpiphdr); 1394926Swnj m->m_len = sizeof (struct udpiphdr); 1404926Swnj m->m_next = m0; 1414926Swnj ui = mtod(m, struct udpiphdr *); 1424926Swnj ui->ui_next = ui->ui_prev = 0; 1434926Swnj ui->ui_x1 = 0; 1444926Swnj ui->ui_pr = IPPROTO_UDP; 145*4955Swnj ui->ui_len = htons((u_short)(sizeof (struct udphdr) + len)); 146*4955Swnj ui->ui_src.s_addr = htonl(inp->inp_laddr.s_addr); 147*4955Swnj ui->ui_dst.s_addr = htonl(inp->inp_faddr.s_addr); 1484926Swnj ui->ui_sport = htons(inp->inp_lport); 1494926Swnj ui->ui_dport = htons(inp->inp_fport); 150*4955Swnj ui->ui_ulen = htons((u_short)len); 1514784Swnj 1524926Swnj /* 1534926Swnj * Stuff checksum and output datagram. 1544926Swnj */ 1554926Swnj ui->ui_sum = 0; 1564926Swnj ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len); 1574887Swnj ip_output(m); 1584926Swnj return; 1594926Swnj bad: 1604926Swnj m_freem(m); 1614784Swnj } 1624784Swnj 1634912Swnj /*ARGSUSED*/ 1644887Swnj udp_usrreq(so, req, m, addr) 1654887Swnj struct socket *so; 1664784Swnj int req; 1674784Swnj struct mbuf *m; 1684912Swnj caddr_t addr; 1694784Swnj { 1704887Swnj struct inpcb *inp = sotoinpcb(so); 1714887Swnj int error; 1724784Swnj 1734784Swnj switch (req) { 1744784Swnj 1754784Swnj case PRU_ATTACH: 1764887Swnj if (inp != 0) 1774887Swnj return (EINVAL); 178*4955Swnj error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 179*4955Swnj if (error) 180*4955Swnj return (error); 1814887Swnj so->so_pcb = (caddr_t)inp; 1824887Swnj break; 1834784Swnj 1844784Swnj case PRU_DETACH: 1854887Swnj if (inp == 0) 1864887Swnj return (ENOTCONN); 1874912Swnj in_pcbfree(inp); 1884887Swnj break; 1894784Swnj 1904784Swnj case PRU_CONNECT: 191*4955Swnj if (inp->inp_faddr.s_addr) 1924887Swnj return (EISCONN); 193*4955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 194*4955Swnj if (error) 1954887Swnj return (error); 1964887Swnj soisconnected(so); 1974887Swnj break; 1984784Swnj 1994926Swnj case PRU_ACCEPT: 2004926Swnj return (EOPNOTSUPP); 2014926Swnj 2024784Swnj case PRU_DISCONNECT: 203*4955Swnj if (inp->inp_faddr.s_addr == 0) 2044887Swnj return (ENOTCONN); 205*4955Swnj inp->inp_faddr.s_addr = 0; 2064887Swnj soisdisconnected(so); 2074784Swnj break; 2084784Swnj 2094912Swnj case PRU_SHUTDOWN: 2104912Swnj socantsendmore(so); 2114912Swnj break; 2124912Swnj 2134784Swnj case PRU_SEND: 2144887Swnj if (addr) { 215*4955Swnj if (inp->inp_faddr.s_addr) 2164887Swnj return (EISCONN); 217*4955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 218*4955Swnj if (error) 219*4955Swnj return (error); 220*4955Swnj } else { 221*4955Swnj if (inp->inp_faddr.s_addr == 0) 222*4955Swnj return (ENOTCONN); 223*4955Swnj } 224*4955Swnj udp_output(inp, m); 225*4955Swnj if (addr) 226*4955Swnj inp->inp_faddr.s_addr = 0; 2274784Swnj break; 2284784Swnj 2294784Swnj case PRU_ABORT: 2304887Swnj in_pcbfree(inp); 2314887Swnj sofree(so); 2324887Swnj soisdisconnected(so); 2334784Swnj break; 2344784Swnj 2354784Swnj case PRU_CONTROL: 2364887Swnj return (EOPNOTSUPP); 2374784Swnj 2384784Swnj default: 2394784Swnj panic("udp_usrreq"); 2404805Swnj } 2414887Swnj return (0); 2424784Swnj } 2434805Swnj 244*4955Swnj /*ARGSUSED*/ 2454926Swnj udp_sense(m) 2464926Swnj struct mbuf *m; 2474805Swnj { 248*4955Swnj 2494926Swnj return (EOPNOTSUPP); 2504805Swnj } 251