1*5220Swnj /* udp_usrreq.c 4.15 81/12/09 */ 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" 105094Swnj #include "../net/in.h" 115094Swnj #include "../net/in_pcb.h" 125094Swnj #include "../net/in_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 255094Swnj COUNT(UDP_INIT); 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 405094Swnj COUNT(UDP_INPUT); 414926Swnj /* 424926Swnj * Get ip and udp header together in first mbuf. 434926Swnj */ 444926Swnj m = m0; 454926Swnj if (m->m_len < sizeof (struct udpiphdr) && 464926Swnj m_pullup(m, sizeof (struct udpiphdr)) == 0) { 474926Swnj udpstat.udps_hdrops++; 484926Swnj goto bad; 494926Swnj } 505050Swnj ui = mtod(m, struct udpiphdr *); 515050Swnj if (ui->ui_len > sizeof (struct ip)) 52*5220Swnj ip_stripoptions((struct ip *)ui, (struct mbuf *)0); 534926Swnj 544926Swnj /* 554926Swnj * Make mbuf data length reflect udp length. 564926Swnj * If not enough data to reflect udp length, drop. 574926Swnj */ 584955Swnj ulen = ntohs((u_short)ui->ui_ulen); 59*5220Swnj len = sizeof (struct udphdr) + ulen; 60*5220Swnj printf("len %d, ulen %d, ((struct ip *)ui)->ip_len %d\n", 61*5220Swnj len, ulen, ((struct ip *)ui)->ip_len); 624926Swnj if (((struct ip *)ui)->ip_len != len) { 634926Swnj if (len > ((struct ip *)ui)->ip_len) { 644926Swnj udpstat.udps_badlen++; 654926Swnj goto bad; 664926Swnj } 674926Swnj m_adj(m, ((struct ip *)ui)->ip_len - len); 684926Swnj /* (struct ip *)ui->ip_len = len; */ 694926Swnj } 704926Swnj 714926Swnj /* 724926Swnj * Checksum extended udp header and data. 734926Swnj */ 744901Swnj if (udpcksum) { 754926Swnj ui->ui_next = ui->ui_prev = 0; 764926Swnj ui->ui_x1 = 0; 77*5220Swnj ui->ui_len = htons((u_short)(sizeof (struct udphdr) + ulen)); 78*5220Swnj if (ui->ui_sum = in_cksum(m, len)) { 794926Swnj udpstat.udps_badsum++; 804901Swnj printf("udp cksum %x\n", ui->ui_sum); 814901Swnj m_freem(m); 824901Swnj return; 834901Swnj } 844901Swnj } 854926Swnj 864926Swnj /* 874926Swnj * Locate pcb for datagram. 884926Swnj */ 894926Swnj inp = in_pcblookup(&udb, 904926Swnj ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 915051Swnj if (inp == 0) 924926Swnj goto bad; 934926Swnj 944926Swnj /* 954926Swnj * Construct sockaddr format source address. 964926Swnj * Stuff source address and datagram in user buffer. 974926Swnj */ 984926Swnj udp_in.sin_port = ui->ui_sport; 994926Swnj udp_in.sin_addr = ui->ui_src; 1005050Swnj m->m_len -= sizeof (struct udpiphdr); 1015050Swnj m->m_off += sizeof (struct udpiphdr); 102*5220Swnj printf("sbappendaddr called with m %x m->m_len %d m->m_off %d\n", 103*5220Swnj m, m->m_len, m->m_off); 104*5220Swnj printf("*mtod(m, char *) %x\n", *mtod(m, char *)); 1055050Swnj if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0) 1064926Swnj goto bad; 1075050Swnj sorwakeup(inp->inp_socket); 1084887Swnj return; 1094926Swnj bad: 1104887Swnj m_freem(m); 1114784Swnj } 1124784Swnj 1134887Swnj udp_ctlinput(m) 1144887Swnj struct mbuf *m; 1154887Swnj { 1164887Swnj 1175094Swnj COUNT(UDP_CTLINPUT); 1185050Swnj printf("udp_ctlinput\n"); 1194887Swnj m_freem(m); 1204887Swnj } 1214887Swnj 1224926Swnj /*ARGSUSED*/ 1234955Swnj udp_output(inp, m0) 1244926Swnj struct inpcb *inp; 1254926Swnj struct mbuf *m0; 1264784Swnj { 1274926Swnj register struct mbuf *m; 1284926Swnj register struct udpiphdr *ui; 1294926Swnj register int len = 0; 1304784Swnj 1315094Swnj COUNT(UDP_OUTPUT); 1324926Swnj /* 1334926Swnj * Calculate data length and get a mbuf 1344926Swnj * for udp and ip headers. 1354926Swnj */ 1364926Swnj for (m = m0; m; m = m->m_next) 1374926Swnj len += m->m_len; 1384926Swnj m = m_get(0); 1395051Swnj if (m == 0) 1404926Swnj goto bad; 1414784Swnj 1424926Swnj /* 1434926Swnj * Fill in mbuf with extended udp header 1444926Swnj * and addresses and length put into network format. 1454926Swnj */ 1464926Swnj m->m_off = MMAXOFF - sizeof (struct udpiphdr); 1474926Swnj m->m_len = sizeof (struct udpiphdr); 1484926Swnj m->m_next = m0; 1494926Swnj ui = mtod(m, struct udpiphdr *); 1504926Swnj ui->ui_next = ui->ui_prev = 0; 1514926Swnj ui->ui_x1 = 0; 1524926Swnj ui->ui_pr = IPPROTO_UDP; 1535050Swnj ui->ui_len = sizeof (struct udpiphdr) + len; 1545050Swnj ui->ui_src = inp->inp_laddr; 1555050Swnj ui->ui_dst = inp->inp_faddr; 1565050Swnj ui->ui_sport = inp->inp_lport; 1575050Swnj ui->ui_dport = inp->inp_fport; 1584955Swnj ui->ui_ulen = htons((u_short)len); 1594784Swnj 1604926Swnj /* 1614926Swnj * Stuff checksum and output datagram. 1624926Swnj */ 1634926Swnj ui->ui_sum = 0; 1645094Swnj ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len); 1655050Swnj ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 1665050Swnj ((struct ip *)ui)->ip_ttl = MAXTTL; 1675115Swnj (void) ip_output(m, (struct mbuf *)0); 1684926Swnj return; 1694926Swnj bad: 1704926Swnj m_freem(m); 1714784Swnj } 1724784Swnj 1734912Swnj /*ARGSUSED*/ 1744887Swnj udp_usrreq(so, req, m, addr) 1754887Swnj struct socket *so; 1764784Swnj int req; 1774784Swnj struct mbuf *m; 1784912Swnj caddr_t addr; 1794784Swnj { 1804887Swnj struct inpcb *inp = sotoinpcb(so); 1814887Swnj int error; 1824784Swnj 1835094Swnj COUNT(UDP_USRREQ); 1845051Swnj if (inp == 0 && req != PRU_ATTACH) 1855050Swnj return (EINVAL); 186*5220Swnj printf("udp_usrreq %d\n", req); 1874784Swnj switch (req) { 1884784Swnj 1894784Swnj case PRU_ATTACH: 1904887Swnj if (inp != 0) 1914887Swnj return (EINVAL); 1925166Swnj error = in_pcbattach(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 1935051Swnj if (error) 1944955Swnj return (error); 1954887Swnj break; 1964784Swnj 1974784Swnj case PRU_DETACH: 1984887Swnj if (inp == 0) 1994887Swnj return (ENOTCONN); 2005166Swnj in_pcbdetach(inp); 2014887Swnj break; 2024784Swnj 2034784Swnj case PRU_CONNECT: 2044955Swnj if (inp->inp_faddr.s_addr) 2054887Swnj return (EISCONN); 2065166Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 2075051Swnj if (error) 2084887Swnj return (error); 2094887Swnj soisconnected(so); 2104887Swnj break; 2114784Swnj 2124926Swnj case PRU_ACCEPT: 2134926Swnj return (EOPNOTSUPP); 2144926Swnj 2154784Swnj case PRU_DISCONNECT: 2164955Swnj if (inp->inp_faddr.s_addr == 0) 2174887Swnj return (ENOTCONN); 2185166Swnj in_pcbdisconnect(inp); 2194887Swnj soisdisconnected(so); 2204784Swnj break; 2214784Swnj 2224912Swnj case PRU_SHUTDOWN: 2234912Swnj socantsendmore(so); 2244912Swnj break; 2254912Swnj 2264784Swnj case PRU_SEND: 2274887Swnj if (addr) { 228*5220Swnj if (inp->inp_faddr.s_addr) { 229*5220Swnj printf("EISCONN\n"); 2304887Swnj return (EISCONN); 231*5220Swnj } 2325166Swnj error = in_pcbconnect(inp, (struct sockaddr_in *)addr); 233*5220Swnj if (error) { 234*5220Swnj printf("pcbconnect error %d\n", error); 2354955Swnj return (error); 236*5220Swnj } 2374955Swnj } else { 2384955Swnj if (inp->inp_faddr.s_addr == 0) 2394955Swnj return (ENOTCONN); 2404955Swnj } 241*5220Swnj printf("to udp_output\n"); 2424955Swnj udp_output(inp, m); 2434955Swnj if (addr) 2445166Swnj in_pcbdisconnect(inp); 2454784Swnj break; 2464784Swnj 2474784Swnj case PRU_ABORT: 2485166Swnj in_pcbdetach(inp); 2494887Swnj sofree(so); 2504887Swnj soisdisconnected(so); 2514784Swnj break; 2524784Swnj 2534784Swnj case PRU_CONTROL: 2544887Swnj return (EOPNOTSUPP); 2554784Swnj 2564784Swnj default: 2574784Swnj panic("udp_usrreq"); 2584805Swnj } 2594887Swnj return (0); 2604784Swnj } 261