1*5051Swnj /* udp_usrreq.c 4.9 81/11/23 */ 24784Swnj 34784Swnj #include "../h/param.h" 44887Swnj #include "../h/dir.h" 54887Swnj #include "../h/user.h" 64784Swnj #include "../h/mbuf.h" 75050Swnj #define PRUREQUESTS 84805Swnj #include "../h/protosw.h" 94887Swnj #include "../h/socket.h" 104887Swnj #include "../h/socketvar.h" 114805Swnj #include "../net/inet.h" 124887Swnj #include "../net/inet_pcb.h" 134805Swnj #include "../net/inet_systm.h" 144901Swnj #include "../net/ip.h" 154901Swnj #include "../net/ip_var.h" 164887Swnj #include "../net/udp.h" 174887Swnj #include "../net/udp_var.h" 184784Swnj 194926Swnj /* 204926Swnj * UDP protocol implementation. 214926Swnj * Per RFC 768, August, 1980. 224926Swnj */ 234805Swnj udp_init() 244805Swnj { 254805Swnj 264901Swnj udb.inp_next = udb.inp_prev = &udb; 274805Swnj } 284805Swnj 294901Swnj int udpcksum; 304926Swnj struct sockaddr_in udp_in = { AF_INET }; 314901Swnj 324926Swnj udp_input(m0) 334926Swnj struct mbuf *m0; 344784Swnj { 354901Swnj register struct udpiphdr *ui; 364887Swnj register struct inpcb *inp; 374926Swnj register struct mbuf *m; 384926Swnj int len, ulen; 394784Swnj 404926Swnj /* 414926Swnj * Get ip and udp header together in first mbuf. 424926Swnj */ 434926Swnj m = m0; 444926Swnj if (m->m_len < sizeof (struct udpiphdr) && 454926Swnj m_pullup(m, sizeof (struct udpiphdr)) == 0) { 464926Swnj udpstat.udps_hdrops++; 474926Swnj goto bad; 484926Swnj } 495050Swnj ui = mtod(m, struct udpiphdr *); 505050Swnj if (ui->ui_len > sizeof (struct ip)) 515050Swnj ip_stripoptions((struct ip *)ui, (char *)0); 524926Swnj 534926Swnj /* 544926Swnj * Make mbuf data length reflect udp length. 554926Swnj * If not enough data to reflect udp length, drop. 564926Swnj */ 574955Swnj ulen = ntohs((u_short)ui->ui_ulen); 584926Swnj len = sizeof (struct udpiphdr) + ulen; 594926Swnj if (((struct ip *)ui)->ip_len != len) { 604926Swnj if (len > ((struct ip *)ui)->ip_len) { 614926Swnj udpstat.udps_badlen++; 624926Swnj goto bad; 634926Swnj } 644926Swnj m_adj(m, ((struct ip *)ui)->ip_len - len); 654926Swnj /* (struct ip *)ui->ip_len = len; */ 664926Swnj } 674926Swnj 684926Swnj /* 694926Swnj * Checksum extended udp header and data. 704926Swnj */ 714901Swnj if (udpcksum) { 724926Swnj ui->ui_next = ui->ui_prev = 0; 734926Swnj ui->ui_x1 = 0; 744955Swnj ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen)); 755050Swnj if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) { 764926Swnj udpstat.udps_badsum++; 774901Swnj printf("udp cksum %x\n", ui->ui_sum); 784901Swnj m_freem(m); 794901Swnj return; 804901Swnj } 814901Swnj } 824926Swnj 834926Swnj /* 844926Swnj * Convert addresses and ports to host format. 854926Swnj * Locate pcb for datagram. 864926Swnj */ 874926Swnj inp = in_pcblookup(&udb, 884926Swnj ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 89*5051Swnj if (inp == 0) 904926Swnj goto bad; 914926Swnj 924926Swnj /* 934926Swnj * Construct sockaddr format source address. 944926Swnj * Stuff source address and datagram in user buffer. 954926Swnj */ 964926Swnj udp_in.sin_port = ui->ui_sport; 974926Swnj udp_in.sin_addr = ui->ui_src; 985050Swnj m->m_len -= sizeof (struct udpiphdr); 995050Swnj m->m_off += sizeof (struct udpiphdr); 1005050Swnj if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0) 1014926Swnj goto bad; 1025050Swnj sorwakeup(inp->inp_socket); 1034887Swnj return; 1044926Swnj bad: 1054887Swnj m_freem(m); 1064784Swnj } 1074784Swnj 1084887Swnj udp_ctlinput(m) 1094887Swnj struct mbuf *m; 1104887Swnj { 1114887Swnj 1125050Swnj printf("udp_ctlinput\n"); 1134887Swnj m_freem(m); 1144887Swnj } 1154887Swnj 1164926Swnj /*ARGSUSED*/ 1174955Swnj udp_output(inp, m0) 1184926Swnj struct inpcb *inp; 1194926Swnj struct mbuf *m0; 1204784Swnj { 1214926Swnj register struct mbuf *m; 1224926Swnj register struct udpiphdr *ui; 1234926Swnj register int len = 0; 1244784Swnj 1254926Swnj /* 1264926Swnj * Calculate data length and get a mbuf 1274926Swnj * for udp and ip headers. 1284926Swnj */ 1294926Swnj for (m = m0; m; m = m->m_next) 1304926Swnj len += m->m_len; 1314926Swnj m = m_get(0); 132*5051Swnj if (m == 0) 1334926Swnj goto bad; 1344784Swnj 1354926Swnj /* 1364926Swnj * Fill in mbuf with extended udp header 1374926Swnj * and addresses and length put into network format. 1384926Swnj */ 1394926Swnj m->m_off = MMAXOFF - sizeof (struct udpiphdr); 1404926Swnj m->m_len = sizeof (struct udpiphdr); 1414926Swnj m->m_next = m0; 1424926Swnj ui = mtod(m, struct udpiphdr *); 1434926Swnj ui->ui_next = ui->ui_prev = 0; 1444926Swnj ui->ui_x1 = 0; 1454926Swnj ui->ui_pr = IPPROTO_UDP; 1465050Swnj ui->ui_len = sizeof (struct udpiphdr) + len; 1475050Swnj ui->ui_src = inp->inp_laddr; 1485050Swnj ui->ui_dst = inp->inp_faddr; 1495050Swnj ui->ui_sport = inp->inp_lport; 1505050Swnj ui->ui_dport = inp->inp_fport; 1514955Swnj ui->ui_ulen = htons((u_short)len); 1524784Swnj 1534926Swnj /* 1544926Swnj * Stuff checksum and output datagram. 1554926Swnj */ 1564926Swnj ui->ui_sum = 0; 1574926Swnj ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len); 1585050Swnj ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 1595050Swnj ((struct ip *)ui)->ip_ttl = MAXTTL; 1604887Swnj ip_output(m); 1614926Swnj return; 1624926Swnj bad: 1634926Swnj m_freem(m); 1644784Swnj } 1654784Swnj 1664912Swnj /*ARGSUSED*/ 1674887Swnj udp_usrreq(so, req, m, addr) 1684887Swnj struct socket *so; 1694784Swnj int req; 1704784Swnj struct mbuf *m; 1714912Swnj caddr_t addr; 1724784Swnj { 1734887Swnj struct inpcb *inp = sotoinpcb(so); 1744887Swnj int error; 1754784Swnj 176*5051Swnj if (inp == 0 && req != PRU_ATTACH) 1775050Swnj return (EINVAL); 1784784Swnj switch (req) { 1794784Swnj 1804784Swnj case PRU_ATTACH: 1814887Swnj if (inp != 0) 1824887Swnj return (EINVAL); 1834955Swnj error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 184*5051Swnj if (error) 1854955Swnj return (error); 1864887Swnj break; 1874784Swnj 1884784Swnj case PRU_DETACH: 1894887Swnj if (inp == 0) 1904887Swnj return (ENOTCONN); 1914912Swnj in_pcbfree(inp); 1924887Swnj break; 1934784Swnj 1944784Swnj case PRU_CONNECT: 1954955Swnj if (inp->inp_faddr.s_addr) 1964887Swnj return (EISCONN); 1974955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 198*5051Swnj if (error) 1994887Swnj return (error); 2004887Swnj soisconnected(so); 2014887Swnj break; 2024784Swnj 2034926Swnj case PRU_ACCEPT: 2044926Swnj return (EOPNOTSUPP); 2054926Swnj 2064784Swnj case PRU_DISCONNECT: 2074955Swnj if (inp->inp_faddr.s_addr == 0) 2084887Swnj return (ENOTCONN); 2094955Swnj inp->inp_faddr.s_addr = 0; 2104887Swnj soisdisconnected(so); 2114784Swnj break; 2124784Swnj 2134912Swnj case PRU_SHUTDOWN: 2144912Swnj socantsendmore(so); 2154912Swnj break; 2164912Swnj 2174784Swnj case PRU_SEND: 2184887Swnj if (addr) { 2194955Swnj if (inp->inp_faddr.s_addr) 2204887Swnj return (EISCONN); 2214955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 222*5051Swnj if (error) 2234955Swnj return (error); 2244955Swnj } else { 2254955Swnj if (inp->inp_faddr.s_addr == 0) 2264955Swnj return (ENOTCONN); 2274955Swnj } 2284955Swnj udp_output(inp, m); 2294955Swnj if (addr) 2304955Swnj inp->inp_faddr.s_addr = 0; 2314784Swnj break; 2324784Swnj 2334784Swnj case PRU_ABORT: 2344887Swnj in_pcbfree(inp); 2354887Swnj sofree(so); 2364887Swnj soisdisconnected(so); 2374784Swnj break; 2384784Swnj 2394784Swnj case PRU_CONTROL: 2404887Swnj return (EOPNOTSUPP); 2414784Swnj 2424784Swnj default: 2434784Swnj panic("udp_usrreq"); 2444805Swnj } 2454887Swnj return (0); 2464784Swnj } 2474805Swnj 2484955Swnj /*ARGSUSED*/ 2494926Swnj udp_sense(m) 2504926Swnj struct mbuf *m; 2514805Swnj { 2524955Swnj 2535050Swnj printf("udp_sense\n"); 2544926Swnj return (EOPNOTSUPP); 2554805Swnj } 256