1*5050Swnj /* udp_usrreq.c 4.8 81/11/23 */ 24784Swnj 34784Swnj #include "../h/param.h" 44887Swnj #include "../h/dir.h" 54887Swnj #include "../h/user.h" 64784Swnj #include "../h/mbuf.h" 7*5050Swnj #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 */ 43*5050Swnj printf("udp_input: "); 444926Swnj m = m0; 454926Swnj if (m->m_len < sizeof (struct udpiphdr) && 464926Swnj m_pullup(m, sizeof (struct udpiphdr)) == 0) { 474926Swnj udpstat.udps_hdrops++; 48*5050Swnj printf("hdrop m_len %d\n", m->m_len); 494926Swnj goto bad; 504926Swnj } 51*5050Swnj ui = mtod(m, struct udpiphdr *); 52*5050Swnj if (ui->ui_len > sizeof (struct ip)) 53*5050Swnj ip_stripoptions((struct ip *)ui, (char *)0); 544926Swnj 554926Swnj /* 564926Swnj * Make mbuf data length reflect udp length. 574926Swnj * If not enough data to reflect udp length, drop. 584926Swnj */ 594955Swnj ulen = ntohs((u_short)ui->ui_ulen); 604926Swnj len = sizeof (struct udpiphdr) + ulen; 61*5050Swnj printf("ulen %d, len %d\n", ulen, len); 624926Swnj if (((struct ip *)ui)->ip_len != len) { 634926Swnj if (len > ((struct ip *)ui)->ip_len) { 64*5050Swnj printf("udp badlen\n"); 654926Swnj udpstat.udps_badlen++; 664926Swnj goto bad; 674926Swnj } 684926Swnj m_adj(m, ((struct ip *)ui)->ip_len - len); 694926Swnj /* (struct ip *)ui->ip_len = len; */ 704926Swnj } 714926Swnj 724926Swnj /* 734926Swnj * Checksum extended udp header and data. 744926Swnj */ 754901Swnj if (udpcksum) { 764926Swnj ui->ui_next = ui->ui_prev = 0; 774926Swnj ui->ui_x1 = 0; 784955Swnj ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen)); 79*5050Swnj if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) { 804926Swnj udpstat.udps_badsum++; 814901Swnj printf("udp cksum %x\n", ui->ui_sum); 824901Swnj m_freem(m); 834901Swnj return; 844901Swnj } 854901Swnj } 864926Swnj 874926Swnj /* 884926Swnj * Convert addresses and ports to host format. 894926Swnj * Locate pcb for datagram. 904926Swnj */ 91*5050Swnj printf("src %x dst %x sport %x dport %x\n", 92*5050Swnj ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport); 934926Swnj inp = in_pcblookup(&udb, 944926Swnj ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 95*5050Swnj if (inp == 0) { 96*5050Swnj printf("pcb not found\n"); 974926Swnj goto bad; 98*5050Swnj } 994926Swnj 1004926Swnj /* 1014926Swnj * Construct sockaddr format source address. 1024926Swnj * Stuff source address and datagram in user buffer. 1034926Swnj */ 1044926Swnj udp_in.sin_port = ui->ui_sport; 1054926Swnj udp_in.sin_addr = ui->ui_src; 106*5050Swnj m->m_len -= sizeof (struct udpiphdr); 107*5050Swnj m->m_off += sizeof (struct udpiphdr); 108*5050Swnj if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0) 1094926Swnj goto bad; 110*5050Swnj sorwakeup(inp->inp_socket); 1114887Swnj return; 1124926Swnj bad: 1134887Swnj m_freem(m); 1144784Swnj } 1154784Swnj 1164887Swnj udp_ctlinput(m) 1174887Swnj struct mbuf *m; 1184887Swnj { 1194887Swnj 120*5050Swnj printf("udp_ctlinput\n"); 1214887Swnj m_freem(m); 1224887Swnj } 1234887Swnj 1244926Swnj /*ARGSUSED*/ 1254955Swnj udp_output(inp, m0) 1264926Swnj struct inpcb *inp; 1274926Swnj struct mbuf *m0; 1284784Swnj { 1294926Swnj register struct mbuf *m; 1304926Swnj register struct udpiphdr *ui; 1314926Swnj register int len = 0; 1324784Swnj 1334926Swnj /* 1344926Swnj * Calculate data length and get a mbuf 1354926Swnj * for udp and ip headers. 1364926Swnj */ 1374926Swnj for (m = m0; m; m = m->m_next) 1384926Swnj len += m->m_len; 139*5050Swnj printf("udp_output len %d: ", len); 1404926Swnj m = m_get(0); 141*5050Swnj if (m == 0) { 142*5050Swnj printf("no mbufs\n"); 1434926Swnj goto bad; 144*5050Swnj } 1454784Swnj 1464926Swnj /* 1474926Swnj * Fill in mbuf with extended udp header 1484926Swnj * and addresses and length put into network format. 1494926Swnj */ 1504926Swnj m->m_off = MMAXOFF - sizeof (struct udpiphdr); 1514926Swnj m->m_len = sizeof (struct udpiphdr); 1524926Swnj m->m_next = m0; 1534926Swnj ui = mtod(m, struct udpiphdr *); 1544926Swnj ui->ui_next = ui->ui_prev = 0; 1554926Swnj ui->ui_x1 = 0; 1564926Swnj ui->ui_pr = IPPROTO_UDP; 157*5050Swnj ui->ui_len = sizeof (struct udpiphdr) + len; 158*5050Swnj ui->ui_src = inp->inp_laddr; 159*5050Swnj ui->ui_dst = inp->inp_faddr; 160*5050Swnj ui->ui_sport = inp->inp_lport; 161*5050Swnj ui->ui_dport = inp->inp_fport; 1624955Swnj ui->ui_ulen = htons((u_short)len); 163*5050Swnj printf("src %x dst %x sport %x dport %x", 164*5050Swnj ui->ui_src.s_addr, ui->ui_dst.s_addr, ui->ui_sport, ui->ui_dport); 1654784Swnj 1664926Swnj /* 1674926Swnj * Stuff checksum and output datagram. 1684926Swnj */ 1694926Swnj ui->ui_sum = 0; 1704926Swnj ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len); 171*5050Swnj printf(" cksum %x\n", ui->ui_sum); 172*5050Swnj ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; 173*5050Swnj ((struct ip *)ui)->ip_ttl = MAXTTL; 1744887Swnj ip_output(m); 1754926Swnj return; 1764926Swnj bad: 1774926Swnj m_freem(m); 1784784Swnj } 1794784Swnj 1804912Swnj /*ARGSUSED*/ 1814887Swnj udp_usrreq(so, req, m, addr) 1824887Swnj struct socket *so; 1834784Swnj int req; 1844784Swnj struct mbuf *m; 1854912Swnj caddr_t addr; 1864784Swnj { 1874887Swnj struct inpcb *inp = sotoinpcb(so); 1884887Swnj int error; 1894784Swnj 190*5050Swnj printf("udp_usrreq %x %s\n", inp, prurequests[req]); 191*5050Swnj if (inp == 0 && req != PRU_ATTACH) { 192*5050Swnj printf("inp == 0 not on ATTACH\n"); 193*5050Swnj return (EINVAL); 194*5050Swnj } 1954784Swnj switch (req) { 1964784Swnj 1974784Swnj case PRU_ATTACH: 1984887Swnj if (inp != 0) 1994887Swnj return (EINVAL); 2004955Swnj error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr); 201*5050Swnj if (error) { 202*5050Swnj printf("in_pcballoc failed %d\n", error); 2034955Swnj return (error); 204*5050Swnj } 2054887Swnj break; 2064784Swnj 2074784Swnj case PRU_DETACH: 2084887Swnj if (inp == 0) 2094887Swnj return (ENOTCONN); 2104912Swnj in_pcbfree(inp); 2114887Swnj break; 2124784Swnj 2134784Swnj case PRU_CONNECT: 2144955Swnj if (inp->inp_faddr.s_addr) 2154887Swnj return (EISCONN); 2164955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 217*5050Swnj if (error) { 218*5050Swnj printf("in_pcbsetpeer failed %d\n", error); 2194887Swnj return (error); 220*5050Swnj } 2214887Swnj soisconnected(so); 2224887Swnj break; 2234784Swnj 2244926Swnj case PRU_ACCEPT: 2254926Swnj return (EOPNOTSUPP); 2264926Swnj 2274784Swnj case PRU_DISCONNECT: 2284955Swnj if (inp->inp_faddr.s_addr == 0) 2294887Swnj return (ENOTCONN); 2304955Swnj inp->inp_faddr.s_addr = 0; 2314887Swnj soisdisconnected(so); 2324784Swnj break; 2334784Swnj 2344912Swnj case PRU_SHUTDOWN: 2354912Swnj socantsendmore(so); 2364912Swnj break; 2374912Swnj 2384784Swnj case PRU_SEND: 2394887Swnj if (addr) { 2404955Swnj if (inp->inp_faddr.s_addr) 2414887Swnj return (EISCONN); 2424955Swnj error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr); 243*5050Swnj if (error) { 244*5050Swnj printf("send setpeer failed %d\n", error); 2454955Swnj return (error); 246*5050Swnj } 2474955Swnj } else { 2484955Swnj if (inp->inp_faddr.s_addr == 0) 2494955Swnj return (ENOTCONN); 2504955Swnj } 251*5050Swnj printf("udp send m %x m_len %d * %c (%o)\n", 252*5050Swnj m, m->m_len, *(mtod(m, caddr_t)), *(mtod(m, caddr_t))); 2534955Swnj udp_output(inp, m); 2544955Swnj if (addr) 2554955Swnj inp->inp_faddr.s_addr = 0; 2564784Swnj break; 2574784Swnj 2584784Swnj case PRU_ABORT: 2594887Swnj in_pcbfree(inp); 2604887Swnj sofree(so); 2614887Swnj soisdisconnected(so); 2624784Swnj break; 2634784Swnj 2644784Swnj case PRU_CONTROL: 2654887Swnj return (EOPNOTSUPP); 2664784Swnj 2674784Swnj default: 2684784Swnj panic("udp_usrreq"); 2694805Swnj } 2704887Swnj return (0); 2714784Swnj } 2724805Swnj 2734955Swnj /*ARGSUSED*/ 2744926Swnj udp_sense(m) 2754926Swnj struct mbuf *m; 2764805Swnj { 2774955Swnj 278*5050Swnj printf("udp_sense\n"); 2794926Swnj return (EOPNOTSUPP); 2804805Swnj } 281