1*4926Swnj /* udp_usrreq.c 4.6 81/11/18 */ 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_host.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 19*4926Swnj /* 20*4926Swnj * UDP protocol implementation. 21*4926Swnj * Per RFC 768, August, 1980. 22*4926Swnj */ 234805Swnj udp_init() 244805Swnj { 254805Swnj 264901Swnj udb.inp_next = udb.inp_prev = &udb; 274805Swnj } 284805Swnj 294901Swnj int udpcksum; 30*4926Swnj struct sockaddr_in udp_in = { AF_INET }; 314901Swnj 32*4926Swnj udp_input(m0) 33*4926Swnj struct mbuf *m0; 344784Swnj { 354901Swnj register struct udpiphdr *ui; 364887Swnj register struct inpcb *inp; 37*4926Swnj register struct mbuf *m; 38*4926Swnj int len, ulen; 394784Swnj 40*4926Swnj /* 41*4926Swnj * Get ip and udp header together in first mbuf. 42*4926Swnj */ 43*4926Swnj m = m0; 444901Swnj ui = mtod(m, struct udpiphdr *); 45*4926Swnj if (ui->ui_len > sizeof (struct ip)) 464901Swnj ip_stripoptions((struct ip *)ui); 47*4926Swnj if (m->m_len < sizeof (struct udpiphdr) && 48*4926Swnj m_pullup(m, sizeof (struct udpiphdr)) == 0) { 49*4926Swnj udpstat.udps_hdrops++; 50*4926Swnj goto bad; 51*4926Swnj } 52*4926Swnj 53*4926Swnj /* 54*4926Swnj * Make mbuf data length reflect udp length. 55*4926Swnj * If not enough data to reflect udp length, drop. 56*4926Swnj */ 57*4926Swnj ulen = ntohs(ui->ui_ulen); 58*4926Swnj len = sizeof (struct udpiphdr) + ulen; 59*4926Swnj if (((struct ip *)ui)->ip_len != len) { 60*4926Swnj if (len > ((struct ip *)ui)->ip_len) { 61*4926Swnj udpstat.udps_badlen++; 62*4926Swnj goto bad; 63*4926Swnj } 64*4926Swnj m_adj(m, ((struct ip *)ui)->ip_len - len); 65*4926Swnj /* (struct ip *)ui->ip_len = len; */ 66*4926Swnj } 67*4926Swnj 68*4926Swnj /* 69*4926Swnj * Checksum extended udp header and data. 70*4926Swnj */ 714901Swnj if (udpcksum) { 72*4926Swnj ui->ui_next = ui->ui_prev = 0; 73*4926Swnj ui->ui_x1 = 0; 74*4926Swnj ui->ui_len = htons(sizeof (struct udpiphdr) + ulen); 75*4926Swnj if (ui->ui_sum = inet_cksum(m, len)) { 76*4926Swnj udpstat.udps_badsum++; 774901Swnj printf("udp cksum %x\n", ui->ui_sum); 784901Swnj m_freem(m); 794901Swnj return; 804901Swnj } 814901Swnj } 82*4926Swnj 83*4926Swnj /* 84*4926Swnj * Convert addresses and ports to host format. 85*4926Swnj * Locate pcb for datagram. 86*4926Swnj */ 87*4926Swnj ui->ui_src.s_addr = ntohl(ui->ui_src.s_addr); 88*4926Swnj ui->ui_dst.s_addr = ntohl(ui->ui_dst.s_addr); 89*4926Swnj ui->ui_sport = ntohs(ui->ui_sport); 90*4926Swnj ui->ui_dport = ntohs(ui->ui_dport); 91*4926Swnj inp = in_pcblookup(&udb, 92*4926Swnj ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport); 934887Swnj if (inp == 0) 94*4926Swnj goto bad; 95*4926Swnj 96*4926Swnj /* 97*4926Swnj * Construct sockaddr format source address. 98*4926Swnj * Stuff source address and datagram in user buffer. 99*4926Swnj */ 100*4926Swnj udp_in.sin_port = ui->ui_sport; 101*4926Swnj udp_in.sin_addr = ui->ui_src; 102*4926Swnj if (sbappendaddr(inp->inp_socket, &udp_in, m) == 0) 103*4926Swnj goto bad; 1044887Swnj return; 105*4926Swnj bad: 1064887Swnj m_freem(m); 1074784Swnj } 1084784Swnj 1094887Swnj udp_ctlinput(m) 1104887Swnj struct mbuf *m; 1114887Swnj { 1124887Swnj 1134887Swnj m_freem(m); 1144887Swnj } 1154887Swnj 116*4926Swnj /*ARGSUSED*/ 117*4926Swnj udp_output(inp, raddr, rport, m0) 118*4926Swnj struct inpcb *inp; 119*4926Swnj struct in_addr *raddr; 120*4926Swnj u_short rport; 121*4926Swnj struct mbuf *m0; 1224784Swnj { 123*4926Swnj register struct mbuf *m; 124*4926Swnj register struct udpiphdr *ui; 125*4926Swnj register int len = 0; 1264784Swnj 127*4926Swnj /* 128*4926Swnj * Calculate data length and get a mbuf 129*4926Swnj * for udp and ip headers. 130*4926Swnj */ 131*4926Swnj for (m = m0; m; m = m->m_next) 132*4926Swnj len += m->m_len; 133*4926Swnj m = m_get(0); 134*4926Swnj if (m == 0) 135*4926Swnj goto bad; 1364784Swnj 137*4926Swnj /* 138*4926Swnj * Fill in mbuf with extended udp header 139*4926Swnj * and addresses and length put into network format. 140*4926Swnj */ 141*4926Swnj m->m_off = MMAXOFF - sizeof (struct udpiphdr); 142*4926Swnj m->m_len = sizeof (struct udpiphdr); 143*4926Swnj m->m_next = m0; 144*4926Swnj ui = mtod(m, struct udpiphdr *); 145*4926Swnj ui->ui_next = ui->ui_prev = 0; 146*4926Swnj ui->ui_x1 = 0; 147*4926Swnj ui->ui_pr = IPPROTO_UDP; 148*4926Swnj ui->ui_len = htons(sizeof (struct udphdr) + len); 149*4926Swnj ui->ui_src.s_addr = htonl(inp->inp_lhost); 150*4926Swnj ui->ui_dst.s_addr = htonl(raddr->s_addr); 151*4926Swnj ui->ui_sport = htons(inp->inp_lport); 152*4926Swnj ui->ui_dport = htons(inp->inp_fport); 153*4926Swnj ui->ui_ulen = htons(len); 1544784Swnj 155*4926Swnj /* 156*4926Swnj * Stuff checksum and output datagram. 157*4926Swnj */ 158*4926Swnj ui->ui_sum = 0; 159*4926Swnj ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len); 1604887Swnj ip_output(m); 161*4926Swnj return; 162*4926Swnj bad: 163*4926Swnj 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); 174*4926Swnj struct sockaddr_in *sin; 1754887Swnj int error; 1764784Swnj 1774784Swnj switch (req) { 1784784Swnj 1794784Swnj case PRU_ATTACH: 1804887Swnj if (inp != 0) 1814887Swnj return (EINVAL); 1824912Swnj inp = in_pcballoc(); 1834887Swnj if (inp == NULL) 1844887Swnj return (ENOBUFS); 1854887Swnj so->so_pcb = (caddr_t)inp; 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: 1954887Swnj if (inp->inp_fhost) 1964887Swnj return (EISCONN); 197*4926Swnj in_hosteval(inp, (struct sockaddr *)addr, &error); 1984887Swnj if (inp->inp_fhost == 0) 1994887Swnj return (error); 2004887Swnj soisconnected(so); 2014887Swnj break; 2024784Swnj 203*4926Swnj case PRU_ACCEPT: 204*4926Swnj return (EOPNOTSUPP); 205*4926Swnj 2064784Swnj case PRU_DISCONNECT: 2074887Swnj if (inp->inp_fhost == 0) 2084887Swnj return (ENOTCONN); 2094912Swnj in_hostfree(inp->inp_fhost); 2104887Swnj inp->inp_fhost = 0; 2114887Swnj soisdisconnected(so); 2124784Swnj break; 2134784Swnj 2144912Swnj case PRU_SHUTDOWN: 2154912Swnj socantsendmore(so); 2164912Swnj break; 2174912Swnj 2184784Swnj case PRU_SEND: 2194887Swnj if (addr) { 2204887Swnj if (inp->inp_fhost) 2214887Swnj return (EISCONN); 222*4926Swnj sin = (struct sockaddr_in *)addr; 223*4926Swnj if (sin->sin_family != AF_INET) 224*4926Swnj return (EAFNOSUPPORT); 225*4926Swnj udp_output(inp, sin->sin_addr, sin->sin_port, m); 2264887Swnj } else 227*4926Swnj udp_output(inp, 228*4926Swnj inp->inp_fhost->h_addr, inp->inp_fport, m); 2294784Swnj break; 2304784Swnj 2314784Swnj case PRU_ABORT: 2324887Swnj in_pcbfree(inp); 2334887Swnj sofree(so); 2344887Swnj soisdisconnected(so); 2354784Swnj break; 2364784Swnj 2374784Swnj case PRU_CONTROL: 2384887Swnj return (EOPNOTSUPP); 2394784Swnj 2404784Swnj default: 2414784Swnj panic("udp_usrreq"); 2424805Swnj } 2434887Swnj return (0); 2444784Swnj } 2454805Swnj 246*4926Swnj udp_sense(m) 247*4926Swnj struct mbuf *m; 2484805Swnj { 249*4926Swnj return (EOPNOTSUPP); 2504805Swnj 2514805Swnj } 252